显示歌词行数的优化

在我之前的的文章简单音乐播放器的设计(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);  }  @Overrideprotected void onDraw(Canvas canvas) {// TODO Auto-generated method stubsuper.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);}  }@Overrideprotected 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);}@Overrideprotected void onDraw(Canvas canvas) {// TODO Auto-generated method stubsuper.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);}}@Overrideprotected 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;}
}

自定义歌词View的优化(一)相关推荐

  1. 顺风车Android性能优化之View布局优化

    一.问题背景 在开发过程中,往往会听到 "性能优化" 这个概念,这个概念很大,比如网络性能优化.耗电量优化等等,对 RD 而言,最容易做的或者是影响最大的,应该是 View 的性能 ...

  2. Android中自定义视图View

    标签: 前言 好长时间没写blog了,心里感觉有点空荡荡的,今天有时间就来写一个关于自定义视图的的blog吧.关于这篇blog,网上已经有很多案例了,其实没什么难度的.但是我们在开发的过程中有时候会用 ...

  3. Android中自定义视图View之---前奏篇

    前言 好长时间没写blog了,心里感觉有点空荡荡的,今天有时间就来写一个关于自定义视图的的blog吧.关于这篇blog,网上已经有很多案例了,其实没什么难度的.但是我们在开发的过程中有时候会用到一些自 ...

  4. android sqlite自定义函数,Android中自定义一个View的方法详解

    本文实例讲述了Android中自定义一个View的方法.分享给大家供大家参考,具体如下: Android中自定义View的实现比较简单,无非就是继承父类,然后重载方法,即便如此,在实际编码中难免会遇到 ...

  5. android自定义组合view,自定义View之组合View

    前言 自定义View是安卓开发中比较重要的一环,很多地方都需要用到自定义View.而自定义View比较常见的一种形式就是组合View,也是比较简单的一种方式.下面通过一个实例来学习一下自定义组合vie ...

  6. ML之LiR:利用LiR线性回归算法(自定义目标函数MSE和优化器GD)对Boston房价数据集(两特征+归一化)进行回归预测

    ML之LiR:利用LiR线性回归算法(自定义目标函数MSE和优化器GD)对Boston房价数据集(两特征+归一化)进行回归预测 目录 利用LiR线性回归算法(自定义目标函数MSE和优化器GD)对Bos ...

  7. 【Android开发】用户界面设计-开发自定义的View

    效果图: Android中,所有的UI界面都是由View类和ViewGroup类及其子类组合而成的.View是所有UI组件的基类(父类),为ViewGroup类是容纳这些UI组件的容器,其本身也是Vi ...

  8. asp.net mvc 自定义 pager 封装与优化

    asp.net mvc 自定义 pager 封装与优化 Intro 之前做了一个通用的分页组件,但是有些不足,从翻页事件和分页样式都融合在后台代码中,到翻页事件可以自定义,再到翻页和样式都和代码分离, ...

  9. android群英传 自定义滑动view,Android群英传学习之路-View的滑动

    滑动效果是如何产生的? 滑动一个View从本质上来说就是移动一个View,改变其当前的坐标.所以,想要滑动一个View,就必须监听该View的触摸事件,并且根据事件的坐标,不断的改变View的坐标从而 ...

最新文章

  1. php和mysql实现模糊查询_PHP MYSQL实现登陆和模糊查询两大功能_PHP
  2. 太原科技大学计算机在哪个校区,太原科技大学有几个校区及校区地址 哪个校区最好...
  3. 12.PDE与PTE
  4. 电话光端机与PCM复用设备的区别
  5. php 汉王云名片_汉王云-名片识别【最新版】_OCR_人工智能_API-云市场-阿里云
  6. 【转】DLL中类的显式链接
  7. Windows核心编程_Visual Studio快速修改一列所有字符
  8. 面向对象编程 --- 反射
  9. keras保存的h5、hdf5模型,加载时出现“AttributeError: ‘str‘ object has no attribute ‘decode‘ “
  10. union中结构体整合后字节对齐问题
  11. Android中删除照片操作
  12. null和空 not null
  13. android 自定义心电图,Android自定义 View 练习 —— 心电图的绘制
  14. java coap_CoAP协议-以Californium(Java)为例的CoAP初步实现
  15. re学习笔记(25)BUUCTF-re-[2019红帽杯]easyRE
  16. 卡内基梅隆计算机专业排名,2019年卡内基梅隆大学计算机专业排名多少?
  17. 微信与多闪之争背后,好友关系链到底是如何窃取的?
  18. 标准应用 | 数据库防火墙安全技术解析与实践
  19. 中国石油大学《工程概预算与招投标》第一阶段在线作业
  20. windows隐藏CMD窗口,使jar程序在后台执行

热门文章

  1. 1709 ltsb 内存占用_一次C++伪“内存泄漏”的排查之旅
  2. c在线编译器(c语言在线编程)
  3. 刚刚完成的一个宅男看图利器(你懂的)
  4. 基础算法002-----百钱百鸡问题(扩展问题)
  5. okhttp3测试框架_Okhttp3的使用详解
  6. 游戏——TextOut函数
  7. java shell spool_批量快速的导入导出Oracle的数据(spool缓冲池、java实现)
  8. 软件测试功能到自动化学习路线图,2022年最新版技术栈
  9. 埃科光电在科创板上市:同创伟业、毅达资本为股东,实控人为董宁
  10. OFDM载波间隔_如果用30Khz子载波间隔会比15Khz子载波间隔传递的有效数据少吗?...