LrcView逐行歌词


今天来谈谈歌词控件的实现。大体思路

先解析歌词,歌词配合控件的宽高计算坐标(歌词必须显示在行的中间),然后进行绘制onDraw,最后就是事件处理(歌词 拖动)和歌词随着时间自动移动,这个相对比较麻烦点。

小二   先上个图看看效果




来一段歌词源数据

[02:59.03][01:31.44]双眼也不需要魅力的长发也不需要魅力的长发
[03:07.54][01:33.99]我真不知道我们的命运会这样知道我们的命运会这样
[03:16.36][01:38.59]我只能牺牲自己的感情离你远去只能牺牲自己的感情离你远去
[03:51.19][01:46.80]我只好让你伤心的流泪
[03:52.94][01:57.69]远离你的世界
[03:55.07][02:02.47]我其实不需要你美丽的双眼
[03:57.81][02:06.22]也不需要魅力的长发  

按照上面格式对数据进行解析,这里比较简单大笑,开始绘制,网上很多哥们说绘制的时候先绘制高亮区域,然后绘制高亮之前或者后面的歌词,我觉得没必要,只要坐标计算好了,拿起键盘一阵狂干,完事


 if (lrcs == null || lrcs.size() == 0) {
            //没有歌词
            canvas.drawText(noLrc, nolrcX, center, mNormalpaint);

            return;
        }
        for (int i = 0, size = lrcs.size(); i < size; i++) {
            LrcBean lrcBean = lrcs.get(i);
            String lrc = lrcBean.getLrc();

            if (!TextUtils.isEmpty(lrc)) {
                if (playTime >= lrcBean.getBeginTime() && playTime < lrcBean.getEndTime()) {
                    canvas.drawText(lrc, lrcBean.getX(), lrcBean.getY(), mHighLightpaint);
                } else {
                    canvas.drawText(lrc, lrcBean.getX(), lrcBean.getY(), mNormalpaint);

                }
            }

        }


这个时候不出意外的话,漂亮的歌词已经显示在你的手机上了,下面就要开始处理事件了onTouchEvent。这里就要用的系统提供的滑动工具类了Scroller,只要给他传入参数,它就可以控制控件的移动。其实这里也可以不用Scroller,我们可以直接变换坐标,也可以实现滑动效果,但是这样就会一直在计算坐标,效率有点略低

 public boolean onTouchEvent(MotionEvent event) {


        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                y = event.getY();
                isMoving = (isStop ? false : true);
                isClick = true;
                break;
            case MotionEvent.ACTION_MOVE:
                float durY = event.getY() - y;
                if (Math.abs(durY) > scaledTouchSlop / 2) {
                    isClick = false;
                    if (mlrcs.size() > 0 && !isStop) {
                        if (getScrollY() < 0) {
                            durY = durY / 3;
                        } else if (getScrollY() > mlrcs.size() * wordHight) {
                            durY = durY / 3;
                        }
                        scrollBy(getScrollX(), -(int) durY);
                        y = event.getY();
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:

                int old = getScrollY();
                if (old < 0) {
                    smootscroll(mLrcDrawTool.getIndexline() * (wordHight) - old, ANIMATION_TIME, old);
                } else if (getScrollY() > mlrcs.size() * wordHight) {
                    smootscroll(mLrcDrawTool.getIndexline() * (wordHight) - old, ANIMATION_TIME, old);
                }
                if (isClick) {
                    isClick = true;
                    if (mOnclicklisener != null) {
                        mOnclicklisener.onClick();
                    }
                }
                invalidate();
                isMoving = false;

                break;
        }
        return true;
    }

细心的你肯定会发现这里做了一个小小的处理,当歌词第一行歌词或者最后一个歌词滑动到中间位置的时候,把滑动偏移量消耗了一部分,效果看起来会好点。


下面就是重头戏,随着时间自动滚动。

 int indexline = mLrcDrawTool.getIndexline();
     if (preLrc != indexline) {
         int old = getScrollY();
         int offset = indexline * wordHight - old;
         smootscroll(offset, durtime, old);
         preLrc = indexline;
         invalidate();
     }

getScrollY 这个方法很重要,getScrollY就是当前view的左上角相对于母视图的左上角的Y轴偏移量。 当歌词第一移动上去,getScrollY的值也是变化一行歌词的高度,通过这种方式就可以计算出每次歌词的偏移量,然后给mScroller.startScroll(getScrollX(), old, getScrollX(), offset, durtime);传值,实现自动滚动。

好了逐行歌词已经完成,下面是demo地址

LrcView





如果想了解更多可以关注公众号:















  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值