自定义歌词View的优化(一)

显示歌词行数的优化

在我之前的的文章简单音乐播放器的设计(http://blog.csdn.net/xz_studying/article/details/51584309) 中,自定义的歌词View当时是在借鉴的基础上完成的,因此在自己的应用中多少存在一些问题。在后来的不断学习中,发现了一些解决的办法,和大家分享一下。
原歌词的View是:

public class LyricView extends TextView{
    private float width;        //歌词视图宽度  
    private float height;       //歌词视图高度  
    private Paint currentPaint; //当前歌词画笔对象  
    private Paint notCurrentPaint;  //非当前歌词画笔对象  
    private float textHeight = 30;  //间隔高度  
    private float textSize = 18;    //文本大小  
    private int index = 0;      //歌词list集合下标  

    private List<Lyric> mLrcList = new ArrayList<>();
    public void setmLrcList(List<Lyric> mLrcList) {
        this.mLrcList = mLrcList;
    }
    public LyricView(Context context) {
        super(context);
        init();
    }
    public LyricView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    public LyricView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }
    private void init() {  
        setFocusable(true);     //设置可对焦  

        //当前播放歌词,高亮部分  
        currentPaint = new Paint();  
        currentPaint.setAntiAlias(true);    //设置抗锯齿,让文字美观饱满  
        currentPaint.setTextAlign(Paint.Align.CENTER);//设置文本对齐方式  

        //非当前播放歌词,非高亮部分  
        notCurrentPaint = new Paint();  
        notCurrentPaint.setAntiAlias(true);  
        notCurrentPaint.setTextAlign(Paint.Align.CENTER);  
    }  
    @Override
    protected void onDraw(Canvas canvas) {
        // TODO Auto-generated method stub
        super.onDraw(canvas);
        if(canvas == null) {  
            return;  
        }  

        currentPaint.setColor(Color.argb(210, 251, 248, 29));  
        notCurrentPaint.setColor(Color.argb(140, 255, 255, 255));  

        currentPaint.setTextSize(24);  
        currentPaint.setTypeface(Typeface.SERIF);  

        notCurrentPaint.setTextSize(textSize);  
        notCurrentPaint.setTypeface(Typeface.DEFAULT);  

        try {  
            canvas.drawText(mLrcList.get(index).getLcontent(), width / 2, height / 2, currentPaint); //显示当前歌词

            float tempY = height / 2;  
            //画出本句之前的句子  
            for(int i = index - 1; i >= 0; i--) {  
                //向上推移  
                tempY = tempY - textHeight;  
                canvas.drawText(mLrcList.get(i).getLcontent(), width / 2, tempY, notCurrentPaint);

            }  
            tempY = height / 2;  
            //画出本句之后的句子  
            for(int i = index + 1; i < mLrcList.size(); i++) {
                //往下推移
                tempY = tempY + textHeight;
                    canvas.drawText(mLrcList.get(i).getLcontent(), width / 2, tempY, notCurrentPaint);
            }
        } catch (Exception e) {  
            canvas.drawText("...没发现歌词文件...", width / 2, height/2, notCurrentPaint);

        }  
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        this.width=w;
        this.height=h;
    }
    //设置歌词文件的对应歌词的位置
    public void setIndex(int index) {
        this.index = index;
    }
}

1、此View目前存在的一些问题:
(1)歌词出现的超出了布局中范围,此问题比较明显,在我上次的截图中也可以看到这种情况
(2)太长歌词显示不全的情况
2、现针对(1)问题作出说明
(1)歌词出现的超出了布局中范围,是因为onDraw()中未对绘制文本的范围加以限制,直接绘制完整个歌词,另为让整个Activity的界面采用同一个背景,歌词上、下的其他控件的是透明的,因此歌词也就显示在整个界面中。
3、解决的办法:
(1)根据分析的原因可以有两种解决办法:
<1>为歌词的上、下控件的控件的区域设置非透明的背景,遮挡住相应的歌词,即可显示正常。
<2>如果要设置整体的布局背景的话,则需要控制绘制文本的范围。为保证歌词在不同大小下的自动失配,需要计算文本绘制的具体数据。
4.相关的具体说明:
(1)歌词View通过onSizeChanged()获取控件在布局中的大小,得到的大小值是以像素px为单位,大家可以通过打印查看得到的数据。
绘制文本的单位是sp,在标准大小的情况下,
1sp=1dp=dpi*px。
dpi的获取可通过:

getResources().getDisplayMetrics().density

(2)绘制文本时以下图中的baseLine为基准
这里写图片描述
因此歌词View中textHeight是距离上次绘制的间隔,而非文本的实际高度,因此textHeight要大于textSize,否则会出现文字重叠。因此可以据此计算出大致每一行歌词的在Y轴的位置,即
tempY+row*textHeight*dpi
据此可计算向上和向下的绘制的行数,以本View计算,
row=Height/2/textHeight/dpi
(4)更改后的代码如下:

public class LyricView extends TextView{
    private float width;        //歌词视图宽度
    private float height;       //歌词视图高度
    private Paint currentPaint; //当前画笔对象
    private Paint notCurrentPaint;  //非当前画笔对象
    private float textHeight = 50;  //间隔高度
    private float textSize = 20;   //文本大小
    private int index = 0;      //list集合下标


    private float dpi=getResources().getDisplayMetrics().density;
    private int row;

    private List<Lyric> mLrcList = new ArrayList<>();
    public void setmLrcList(List<Lyric> mLrcList) {
        this.mLrcList = mLrcList;
    }
    public LyricView(Context context) {
        super(context);
        init();
    }
    public LyricView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    public LyricView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }
    private void init() {
        setFocusable(true);     //设置可对焦
        //高亮部分
        currentPaint = new Paint();
        currentPaint.setAntiAlias(true);    //设置抗锯齿,让文字美观饱满
        currentPaint.setTextAlign(Paint.Align.CENTER);//设置文本对齐方式

        //非高亮部分
        notCurrentPaint = new Paint();
        notCurrentPaint.setAntiAlias(true);
        notCurrentPaint.setTextAlign(Paint.Align.CENTER);
    }
    @Override
    protected void onDraw(Canvas canvas) {
        // TODO Auto-generated method stub
        super.onDraw(canvas);
        if(canvas == null) {  
            return;  
        }
        row=(int)(height/2/textHeight/dpi);

        currentPaint.setColor(Color.argb(210, 251, 248, 29));
        notCurrentPaint.setColor(Color.argb(140, 255, 255, 255));
        currentPaint.setTextSize(25);
        currentPaint.setTypeface(Typeface.SERIF);

        notCurrentPaint.setTextSize(textSize);  
        notCurrentPaint.setTypeface(Typeface.DEFAULT);

        try {
            float tempY = height / 2;
            Paint linePaint=new Paint();
            linePaint.setTextSize(16);
                                linePaint.setColor(Color.argb(210, 251, 248, 29));          
            canvas.drawText(MusicListAdapter.toTime(mLrcList.get(index).getLyrictime()),width/2, tempY+20, linePaint);                        canvas.drawText(mLrcList.get(index).getLcontent(), width / 2, tempY, currentPaint);
            //画出本句之前的句子
            for(int i = index - 1; i >= 0; i--) {
                //向上推移
                tempY = tempY - textHeight;

                if (tempY<height/2-row*textHeight) {
                    break;
                }
          canvas.drawText(mLrcList.get(i).getLcontent(), width / 2, tempY, notCurrentPaint);

            }
            tempY = height / 2;
            //画出本句之后的句子
            for(int i = index + 1; i < mLrcList.size(); i++) {
                //往下推移
                tempY = tempY + textHeight;

                if (tempY>height / 2+row*textHeight){
                    break;
                }
                /*if (tempY>height / 2+5*textHeight){
                    break;
                }*/
                canvas.drawText(mLrcList.get(i).getLcontent(), width / 2, tempY, notCurrentPaint);

            }
        } catch (Exception e) {
            canvas.drawText("...没有歌词文件...", width / 2, height/2, notCurrentPaint);

        }
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        this.width=w;
        this.height=h;
    }
    public void setIndex(int index) {
        this.index = index;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值