Android自定义View之简约风歌词控件实战指南

目录
  • 前言
  • 一、 歌词解析
    • 1.歌词实体类LrcBean
    • 2. 解析歌词工具类LrcUtil
  • 二、歌词绘制
    • 1.设置自定View属性,在代码中设置默认值
    • 2. 初始化两支画笔
    • 3. 重复执行onDraw方法
      • 1.获得控件的测量后的宽高
      • 2. 得到当前歌词的位置
      • 4. 歌词同步滑动
      • 5.不断重绘
  • 三 、使用
  • 总结

前言

最近重构了之前的音乐播放器,添加了许多功能,比如歌词,下载功能等。这篇文章就让我们聊聊歌词控件的实现,先上效果图,如果感觉海星,就继续瞧下去!

看到这里,估计你对这个控件还有点感兴趣的吧,那接下来就让我们来瞧瞧实现这个歌词控件需要做些什么!

一、 歌词解析

首先,我们得知道正常的歌词格式是怎样的,大概是长这个样子:

1[ti:喜欢你]
 2[ar:.]
 3[al:]
 4[by:]
 5[offset:0]
 6[00:00.10]喜欢你 - G.E.M. 邓紫棋 (Gem Tang)
 7[00:00.20]词:黄家驹
 8[00:00.30]曲:黄家驹
 9[00:00.40]编曲:Lupo Groinig
10[00:00.50]
11[00:12.65]细雨带风湿透黄昏的街道
12[00:18.61]抹去雨水双眼无故地仰望
13[00:24.04]望向孤单的晚灯
14[00:26.91]
15[00:27.44]是那伤感的记忆
16[00:30.52]
17[00:34.12]再次泛起心里无数的思念
18[00:39.28]
19[00:40.10]以往片刻欢笑仍挂在脸上
20[00:45.49]愿你此刻可会知
21[00:48.23]
22[00:48.95]是我衷心的说声
23[00:53.06]
24[00:54.35]喜欢你 那双眼动人
25[00:59.35]
26[01:00.10]笑声更迷人
27[01:02.37]
28[01:03.15]愿再可 轻抚你
29[01:08.56]
30[01:09.35]那可爱面容
31[01:12.40]挽手说梦话
32[01:14.78]
33[01:15.48]像昨天 你共我
34[01:20.84]
35[01:26.32]满带理想的我曾经多冲动
36[01:32.45]屡怨与她相爱难有自由
37[01:37.82]愿你此刻可会知
38[01:40.40]
39[01:41.25]是我衷心的说声
40[01:44.81]
41[01:46.39]喜欢你 那双眼动人
42[01:51.72]
43[01:52.42]笑声更迷人
44[01:54.75]
45[01:55.48]愿再可 轻抚你
46[02:00.93]
47[02:01.68]那可爱面容
48[02:03.99]
49[02:04.73]挽手说梦话
50[02:07.13]
51[02:07.82]像昨天 你共我
52[02:14.53]
53[02:25.54]每晚夜里自我独行
54[02:29.30]随处荡 多冰冷
55[02:35.40]
56[02:37.83]以往为了自我挣扎
57[02:41.62]从不知 她的痛苦
58[02:52.02]
59[02:54.11]喜欢你 那双眼动人
60[03:00.13]笑声更迷人
61[03:02.38]
62[03:03.14]愿再可 轻抚你
63[03:08.77]
64[03:09.33]那可爱面容
65[03:11.71]
66[03:12.41]挽手说梦话
67[03:14.61]
68[03:15.45]像昨天 你共我

从上面可以看出这种格式前面是开始时间,从左往右一一对应分,秒,毫秒,后面就是歌词。所以我们要创建一个实体类来保存每一句的歌词信息。

1.歌词实体类LrcBean

 1public class LrcBean {
 2    private String lrc;//歌词
 3    private long start;//开始时间
 4    private long end;//结束时间
 5
 6    public String getLrc() {
 7        return lrc;
 8    }
 9
10    public void setLrc(String lrc) {
11        this.lrc = lrc;
12    }
13
14    public long getStart() {
15        return start;
16    }
17
18    public void setStart(long start) {
19        this.start = start;
20    }
21
22    public long getEnd() {
23        return end;
24    }
25
26    public void setEnd(long end) {
27        this.end = end;
28    }
29}

每句歌词,我们需要开始时间,结束时间和歌词这些信息,那么你就会有疑问了?上面提到的歌词格式好像只有歌词开始时间,那我们怎么知道结束时间呢?其实很简单,这一句歌词的开始时间就是上一句歌词的结束时间。有了歌词实体类,我们就得开始对歌词进行解析了!

2. 解析歌词工具类LrcUtil

 1public class LrcUtil {
 2
 3    /**
 4     * 解析歌词,将字符串歌词封装成LrcBean的集合
 5     * @param lrcStr 字符串的歌词,歌词有固定的格式,一般为
 6     * [ti:喜欢你]
 7     * [ar:.]
 8     * [al:]
 9     * [by:]
10     * [offset:0]
11     * [00:00.10]喜欢你 - G.E.M. 邓紫棋 (Gem Tang)
12     * [00:00.20]词:黄家驹
13     * [00:00.30]曲:黄家驹
14     * [00:00.40]编曲:Lupo Groinig
15     * @return 歌词集合
16     */
17    public static List<LrcBean> parseStr2List(String lrcStr){
18        List<LrcBean> res = new ArrayList<>();
19        //根据转行字符对字符串进行分割
20        String[] subLrc = lrcStr.split("\n");
21        //跳过前四行,从第五行开始,因为前四行的歌词我们并不需要
22        for (int i = 5; i < subLrc.length; i++) {
23            String lineLrc = subLrc[i];
24            //[00:00.10]喜欢你 - G.E.M. 邓紫棋 (Gem Tang)
25            String min = lineLrc.substring(lineLrc.indexOf("[")+1,lineLrc.indexOf("[")+3);
26            String sec = lineLrc.substring(lineLrc.indexOf(":")+1,lineLrc.indexOf(":")+3);
27            String mills = lineLrc.substring(lineLrc.indexOf(".")+1,lineLrc.indexOf(".")+3);
28            //进制转化,转化成毫秒形式的时间
29            long startTime = getTime(min,sec,mills);
30            //歌词
31            String lrcText = lineLrc.substring(lineLrc.indexOf("]")+1);
32            //有可能是某个时间段是没有歌词,则跳过下面
33            if(lrcText.equals("")) continue;
34            //在第一句歌词中有可能是很长的,我们只截取一部分,即歌曲加演唱者
35            //比如 光年之外 (《太空旅客(Passengers)》电影中国区主题曲) - G.E.M. 邓紫棋 (Gem Tang)
36            if (i == 5) {
37                int lineIndex = lrcText.indexOf("-");
38                int first = lrcText.indexOf("(");
39                if(first<lineIndex&&first!=-1){
40                    lrcText = lrcText.substring(0,first)+lrcText.substring(lineIndex);
41                }
42                LrcBean lrcBean = new LrcBean();
43                lrcBean.setStart(startTime);
44                lrcBean.setLrc(lrcText);
45                res.add(lrcBean);
46                continue;
47            }
48            //添加到歌词集合中
49            LrcBean lrcBean = new LrcBean();
50            lrcBean.setStart(startTime);
51            lrcBean.setLrc(lrcText);
52            res.add(lrcBean);
53            //如果是最后一句歌词,其结束时间是不知道的,我们将人为的设置为开始时间加上100s
54            if(i == subLrc.length-1){
55                res.get(res.size()-1).setEnd(startTime+100000);
56            }else if(res.size()>1){
57                //当集合数目大于1时,这句的歌词的开始时间就是上一句歌词的结束时间
58                res.get(res.size()-2).setEnd(startTime);
59            }
60
61        }
62        return res;
63    }
64
65    /**
66     *  根据时分秒获得总时间
67     * @param min 分钟
68     * @param sec 秒
69     * @param mills 毫秒
70     * @return 总时间
71     */
72    private static long getTime(String min,String sec,String mills){
73        return Long.valueOf(min)*60*1000+Long.valueOf(sec)*1000+Long.valueOf(mills);
74    }
75}

相信上面的代码和注释已经将这个歌词解析解释的挺明白了,需要注意的是上面对i=5,也就是歌词真正开始的第一句做了特殊处理,因为i=5这句有可能是很长的,假设i=5是“光年之外

(《太空旅客(Passengers)》电影中国区主题曲) - G.E.M. 邓紫棋 (Gem

Tang)”这句歌词,如果我们不做特殊处理,在后面绘制的时候,就会发现这句歌词会超过屏幕大小,很影响美观,所以我们只截取歌曲名和演唱者,有些说明直接省略掉了。解析好了歌词,接下来就是重头戏-歌词绘制!

二、歌词绘制

歌词绘制就涉及到了自定义View的知识,所以还未接触自定义View的小伙伴需要先去看看自定View的基础知识。歌词绘制的主要工作主要由下面几部分构成:

  • 为歌词控件设置自定义属性,在构造方法中获取并设置自定义属性的默认值
  • 初始化两支画笔。分别是歌词普通画笔,歌词高亮画笔。
  • 获取当前播放歌词的位置
  • 画歌词,根据当前播放歌词的位置来决定用哪支画笔画
  • 歌词随歌曲播放同步滑动
  • 重新绘制

1.设置自定View属性,在代码中设置默认值

在res文件中的values中新建一个attrs.xml文件,然后定义歌词的自定义View属性

1<?xml version="1.0" encoding="utf-8"?>
2<resources>
3    <declare-styleable name="LrcView">
4        <attr name="highLineTextColor" format="color|reference|integer"/>
5        <attr name="lrcTextColor" format="color|reference|integer"/>
6        <attr name="lineSpacing" format="dimension"/>
7        <attr name="textSize" format="dimension"/>
8    </declare-styleable>
9</resources>

这里只自定义了歌词颜色,歌词高亮颜色,歌词大小,歌词行间距的属性,可根据自己需要自行添加。

然后在Java代码中,设置默认值。

 1    private int lrcTextColor;//歌词颜色
 2    private int highLineTextColor;//当前歌词颜色
 3    private int width, height;//屏幕宽高
 4    private int lineSpacing;//行间距
 5    private int textSize;//字体大小
 6
 7    public LrcView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
 8        super(context, attrs, defStyleAttr);
 9        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.LrcView);
10        lrcTextColor = ta.getColor(R.styleable.LrcView_lrcTextColor, Color.GRAY);
11        highLineTextColor = ta.getColor(R.styleable.LrcView_highLineTextColor, Color.BLUE);
12        float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
13        float scale = context.getResources().getDisplayMetrics().density;
14        //默认字体大小为16sp
15        textSize = ta.getDimensionPixelSize(R.styleable.LrcView_textSize, (int) (16 * fontScale));
16        //默认行间距为30dp
17        lineSpacing = ta.getDimensionPixelSize(R.styleable.LrcView_lineSpacing, (int) (30 * scale));
18        //回收
19        ta.recycle();
20    }

2. 初始化两支画笔

 1    private void init() {
 2        //初始化歌词画笔
 3        dPaint = new Paint();
 4        dPaint.setStyle(Paint.Style.FILL);//填满
 5        dPaint.setAntiAlias(true);//抗锯齿
 6        dPaint.setColor(lrcTextColor);//画笔颜色
 7        dPaint.setTextSize(textSize);//歌词大小
 8        dPaint.setTextAlign(Paint.Align.CENTER);//文字居中
 9
10        //初始化当前歌词画笔
11        hPaint = new Paint();
12        hPaint.setStyle(Paint.Style.FILL);
13        hPaint.setAntiAlias(true);
14        hPaint.setColor(highLineTextColor);
15        hPaint.setTextSize(textSize);
16        hPaint.setTextAlign(Paint.Align.CENTER);
17    }

我们把初始化的方法放到了构造方法中,这样就可以避免在重绘时再次初始化。另外由于我们把init方法只放到了第三个构造方法中,所以在上面两个构造方法需要将super改成this,这样就能保证哪个构造方法都能执行init方法

 1    public LrcView(Context context) {
 2        this(context, null);
 3    }
 4
 5    public LrcView(Context context, @Nullable AttributeSet attrs) {
 6        this(context, attrs, 0);
 7    }
 8
 9    public LrcView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
10        super(context, attrs, defStyleAttr);
11        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.LrcView);
12        ......
13        //回收
14        ta.recycle();
15        init();
16    }

3. 重复执行onDraw方法

因为后面的步骤都是在onDraw方法中执行的,所以我们先贴出onDraw方法中的代码

 1    @Override
 2    protected void onDraw(Canvas canvas) {
 3        super.onDraw(canvas);
 4
 5        getMeasuredWidthAndHeight();//得到测量后的宽高
 6        getCurrentPosition();//得到当前歌词的位置
 7        drawLrc(canvas);//画歌词
 8        scrollLrc();//歌词滑动
 9        postInvalidateDelayed(100);//延迟0.1s刷新
10    }

1.获得控件的测量后的宽高

1     private int width, height;//屏幕宽高
2    private void getMeasuredWidthAndHeight(){
3        if (width == 0 || height == 0) {
4            width = getMeasuredWidth();
5            height = getMeasuredHeight();
6        }
7    }

为什么要获得控件的宽高呢?因为在下面我们需要画歌词,画歌词时需要画的位置,这时候就需要用到控件的宽高了。

2. 得到当前歌词的位置

 1     private List<LrcBean> lrcBeanList;//歌词集合
 2    private int currentPosition;//当前歌词的位置
 3    private MediaPlayer player;//当前的播放器
 4
 5
 6    private void getCurrentPosition() {
 7        int curTime = player.getCurrentPosition();
 8        //如果当前的时间大于10分钟,证明歌曲未播放,则当前位置应该为0
 9        if (curTime < lrcBeanList.get(0).getStart()||curTime>10*60*1000) {
10            currentPosition = 0;
11            return;
12        } else if (curTime > lrcBeanList.get(lrcBeanList.size() - 1).getStart()) {
13            currentPosition = lrcBeanList.size() - 1;
14            return;
15        }
16        for (int i = 0; i < lrcBeanList.size(); i++) {
17            if (curTime >= lrcBeanList.get(i).getStart() && curTime <= lrcBeanList.get(i).getEnd()) {
18                currentPosition = i;
19            }
20        }
21    }

我们根据当前播放的歌曲时间来遍历歌词集合,从而判断当前播放的歌词的位置。细心的你可能会发现在currentPosition = 0中有个curTime>10601000的判断,这是因为在实际使用中发现当player还未播放时,这时候得到的curTime会很大,所以才有了这个判断(因为正常的歌曲不会超过10分钟)。

在这个方法我们会发现出现了歌词集合和播放器,你可能会感到困惑,这些不是还没赋值吗?困惑就对了,所以我们需要提供外部方法来给外部传给歌词控件歌词集合和播放器。

 1    //将歌词集合传给到这个自定义View中
 2    public LrcView setLrc(String lrc) {
 3        lrcBeanList = LrcUtil.parseStr2List(lrc);
 4        return this;
 5    }
 6
 7    //传递mediaPlayer给自定义View中
 8    public LrcView setPlayer(MediaPlayer player) {
 9        this.player = player;
10        return this;
11    }

外部方法中setLrc的参数必须是前面提到的标准歌词格式的字符串形式,这样我们就能利用上文的解析工具类LrcUtil中的解析方法将字符串解析成歌词集合。

3. 画歌词

1     private void drawLrc(Canvas canvas) {
2        for (int i = 0; i < lrcBeanList.size(); i++) {
3            if (currentPosition == i) {//如果是当前的歌词就用高亮的画笔画
4                canvas.drawText(lrcBeanList.get(i).getLrc(), width / 2, height / 2 + i * lineSpacing, hPaint);
5            } else {
6                canvas.drawText(lrcBeanList.get(i).getLrc(), width / 2, height / 2 + i * lineSpacing, dPaint);
7            }
8        }
9    }

知道了当前歌词的位置就很容易画歌词了。遍历歌词集合,如果是当前歌词,则用高亮的画笔画,其它歌词就用普通画笔画。这里需注意的是两支画笔画的位置公式都是一样的,坐标位置为x=宽的一半,y=高的一半+当前位置*行间距。随着当前位置的变化,就能画出上下句歌词来。所以其实绘制出来后你会发现歌词是从控件的正中央开始绘制的,这是为了方便与下面歌词同步滑动功能配合。

4. 歌词同步滑动

 1     //歌词滑动
 2    private void scrollLrc() {
 3        //下一句歌词的开始时间
 4        long startTime = lrcBeanList.get(currentPosition).getStart();
 5        long currentTime = player.getCurrentPosition();
 6
 7        //判断是否换行,在0.5内完成滑动,即实现弹性滑动
 8        float y = (currentTime - startTime) > 500 ? currentPosition * lineSpacing : lastPosition * lineSpacing + (currentPosition - lastPosition) * lineSpacing * ((currentTime - startTime) / 500f);
 9        scrollTo(0,(int)y);
10        if (getScrollY() == currentPosition * lineSpacing) {
11            lastPosition = currentPosition;
12        }
13    }

如果不实现弹性滑动的话,只要判断当前播放歌曲的时间是否大于当前位置歌词的结束时间,然后进行scrollTo(0,(int)currentPosition * lineSpacing)滑动即可。但是为了实现弹性滑动,我们需要将一次滑动分成若干次小的滑动并在一个时间段内完成,所以我们动态设置y的值,由于不断重绘,就能实现在0.5秒内完成View的滑动,这样就能实现歌词同步弹性滑动。

500其实就是0.5s,因为在这里currentTime和startTime的单位都是ms

1        float y = (currentTime - startTime) > 500 ? currentPosition * lineSpacing : lastPosition * lineSpacing + (currentPosition - lastPosition) * lineSpacing * ((currentTime - startTime) / 500f);

5.不断重绘

通过不断重绘才能实现歌词同步滑动,这里每隔0.1s进行重绘

1postInvalidateDelayed(100);//延迟0.1s刷新

你以为这样就结束了吗?其实还没有,答案下文揭晓!

三 、使用

然后我们兴高采烈的在xml中,引用这个自定义View

LrcView前面的名称为你建这个类的完整包名

1    <com.example.library.view.LrcView
2        android:id="@+id/lrcView"
3        android:layout_width="match_parent"
4        android:layout_height="match_parent"
5        app:lineSpacing="40dp"
6        app:textSize="18sp"
7        app:lrcTextColor="@color/colorPrimary"
8        app:highLineTextColor="@color/highTextColor"
9        />

在Java代码中给这个自定义View传入标准歌词字符串和播放器。

1lrcView.setLrc(lrc).setPlayer(player);

点击运行,满心期待自己的成果,接着你就会一脸懵逼,what?怎么是一片空白,什么也没有!其实这时候你重新理一下上面歌词绘制的流程,就会发现问题所在。 首先我们的自定义View控件引用到布局中时是先执行onDraw方法的,所以当你调用setLrc和setPlayer方法后,是不会再重新调用onDraw方法的,等于你并没有传入歌词字符串和播放器,所以当然会显示一片空白

解决方法 :我们在刚才自定义View歌词控件中添加一个外部方法来调用onDraw,刚好这个invalidate()就能够重新调用onDraw方法

1    public LrcView draw() {
2        currentPosition = 0;
3        lastPosition = 0;
4        invalidate();
5        return this;
6    }

然后我们在主代码中,在调用setLrc和setPlayer后还得调用draw方法

1lrcView.setLrc(lrc).setPlayer(player).draw();

这样我们节约风的歌词控件就大功告成了。

总结

到此这篇关于Android自定义View之简约风歌词控件的文章就介绍到这了,更多相关Android简约风歌词控件内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Android自定义View控件实现刷新效果

    三种得到LinearInflater的方法 a. LayoutInflater inflater = getLayoutInflater(); b. LayoutInflater localinflater = (LayoutInflater)context.getSystemService (Context.LAYOUT_INFLATER_SERVICE); c. LayoutInflater inflater = LayoutInflater.from(context); onDraw 方法

  • Android自定义View控件实现多种水波纹涟漪扩散效果

    效果图 实现思路 这个效果实现起来并不难,重要的是思路 此View满足了多种水波纹涟漪扩散效果,这要求它能满足很多的变化 根据上面的样式,可以看出此View需要满足以下变化 圆圈从中心可循环向外扩散 圆圈之间的扩散间距可以改变 可控制扩散圆的渐变度 圆圈可以是线条样式或者实心样式 圆圈扩散的速度可以控制 适配圆圈不同大小下的扩散效果 具体实现 创建自定义属性 首先为View创建自定义的xml属性 在工程的values目录下新建attrs.xml文件 <declare-styleable name

  • Android自定义View圆形百分比控件(一)

    做一个自定义View的小练习,效果如下 只需要画一个圆.一个圆弧.一个百分比文本,添加一个点击事件,传入百分比重绘 1.在res/values文件夹下新建attrs.xml文件,编写自定义属性: <?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="CirclePercentView" > <attr nam

  • Android自定义View简易折线图控件(二)

    继续练习自定义View,这次带来的是简易折线图,支持坐标点点击监听,效果如下: 画坐标轴.画刻度.画点.连线..x.y轴的数据范围是写死的 1 <= x <= 7 ,1 <= y <= 70 ..写活的话涉及到坐标轴刻度的动态计算.坐标点的坐标修改,想想就头大,这里只练习自定义View. 1.在res/values文件夹下新建attrs.xml文件,编写自定义属性: <?xml version="1.0" encoding="utf-8"

  • Android自定义View实现随手势滑动控件

    本文控件为大家分享了Android随手势滑动控件的具体代码,供大家参考,具体内容如下 1.新建自定义控件类:MyView public class MyView extends Button{ //记录上次滑动后的坐标值 private int lastX; private int lastY; public MyView(Context context) { super(context); // TODO Auto-generated constructor stub } public MyV

  • Android自定义View之简约风歌词控件实战指南

    目录 前言 一. 歌词解析 1.歌词实体类LrcBean 2. 解析歌词工具类LrcUtil 二.歌词绘制 1.设置自定View属性,在代码中设置默认值 2. 初始化两支画笔 3. 重复执行onDraw方法 1.获得控件的测量后的宽高 2. 得到当前歌词的位置 4. 歌词同步滑动 5.不断重绘 三 .使用 总结 前言 最近重构了之前的音乐播放器,添加了许多功能,比如歌词,下载功能等.这篇文章就让我们聊聊歌词控件的实现,先上效果图,如果感觉海星,就继续瞧下去! 看到这里,估计你对这个控件还有点感兴

  • Android自定义View实现多图片选择控件

    前言 相信很多朋友在开发中都会遇到图片上传的情况,尤其是多图上传,最经典的莫过于微信的图片选择了.所有很多情况下会使用到多图选择,所以就有了这篇文章,今天抽点时间写了个控件.  •支持自定义选择图片的样式  •支持设置图片选择数量  •支持图片预览,删除  •支持图片拍照 先来看看效果 实现分析 假如不定义控件,我们要实现这样一个功能,无非是写个GridView在item点击的时候去显示图片进行选择,在返回界面的时候进行GridView的数据刷新.我们把这些逻辑写在我们自定义的GridView中

  • Android自定义view实现水波进度条控件

    通过自定义view实现了一个水滴滴落到水波面,溅起水花并且水波流动上涨的进度条控件.之前看到过好多水波流动的进度条,感觉欠缺些东西,就想到了水滴到水平面,溅起水花然后水流动上涨的进度条效果,于是自己动手写了出来.效果如下,视频录制有些卡顿,实际会流畅很多. 一.用法 1.布局文件中添加WaveProgressView,circleColor属性为圆环颜色,waterColor属性为水波水滴的颜色,progress属性为初始的进度 <com.yhongm.wave_progress_view.Wa

  • Android自定义ViewGroup实现朋友圈九宫格控件

    目录 一.简介 1.1.效果图如下 1.2.主要功能如下 二.使用 2.1.自定义属性如下 2.2.布局中使用自定义NineImageLayout 2.3.Adapter方式绑定数据和UI 2.4.列表里面使用 三.源码地址 四.总结 一.简介 最近项目里有个类似微信朋友圈的九图控件的需求,Github找了一下,发现都不太满足需求,我需要单张图片的时候可以按照图片宽高比列在一定范围内自适应,而大多开源项目单张图片也是一个小正方形,所以,干脆自己动手写一个 1.1.效果图如下 1.2.主要功能如下

  • Kotlin自定义View系列教程之标尺控件(选择身高、体重等)的实现

    前言 本篇文章讲的是Kotlin 自定义view之实现标尺控件Ruler,以选择身高.体重等.开发中,当我们需要获取用户的身高和体重等信息时,如果直接让他们输入,显然体验不够好.像类似于唯品会.好轻等APP都是使用了类似于刻度尺的控件让用户滑动选择身高体重,觉得很棒.网上已有人使用Java语言实现这样的功能,但不影响我对其的学习.和往常一样,主要还是想总结一下自定义view之实现标尺控件的开发过程以及一些需要注意的地方. 按照惯例,我们先来看看效果图 一.先总结下自定义View的步骤: 1.自定

  • Android自定义商品购买数量加减控件

    在购买商品时,大家可以自定义数字加减控件,来确定购买商品的实际数量,如何实现此控件,请参考下文: 1.自定义数字加减控件的要求 创建Module -NumberAddSubView A_输入的只能是数字,而且不能通过键盘输入 B_通过加减按钮操作数字 C_监听加减按钮 D_数组有最小值和最大值的限制 E_自定义属性 2.提供接口,让外界监听到数字的变化 1_设置接口 @Override public void onClick(View v) { if (v.getId() == R.id.btn

  • 漂亮的Android音乐歌词控件 仿网易云音乐滑动效果

    前言: 项目有个音乐播发器功能,实现音乐在线播放,同时需要带有歌词显示功能.网上也找过,在github找到勉强能用的控件,只是效果还是差强人意,不是特别好.于是趁有空的时间,参考了网上的部分demo,自己也写了个歌词控件. 只要demo可以拉到最底部. 一.歌词控件效果. 目前的歌词控件效果如下: 主要效果有以下: 1.实现自动滑动切换到下一句. 2.实现滑动歌词切换播放时间. 3.实现拖动歌词时仿网易云音乐显示时间线,将要选择的歌词颜色变化. 4.音乐进度跳转时,歌词跳转可以滑动切换. 二.歌

  • Android自定义View之自定义评价打分控件RatingBar实现自定义星星大小和间距

    在Android开发中,我们经常会用到对商家或者商品的评价,运用星星进行打分.然而在Android系统中自带的打分控件,RatingBar特别不好用,间距和大小无法改变.所以,我就自定义了一个特别好用的打分控件.在项目中可以直接使用,特别简单.下面直接上图: 效果图 实现原理 其实就是自定义View继承LinearLayout ,然后里面动态加了五个ImageView. 实现代码,有详细的注释 在attrs中声明的可以在xml中设置的变量 <declare-styleable name="

随机推荐