如何使用Android实现音乐播放器歌词显示效果
创始人
2024-12-21 17:40:29
0次

首先实现这种效果有两种方式:

1.自定义View里重载onDraw方法,自己绘制歌词

2.用ScrollView实现

第一种方式比较精确,但要支持滑动之后跳转播放的话难度很大,所以我选择第二种,自定义ScrollView。

一.自定义LycicView extends ScrollView

里面包括一个空白布局,高度是LycicView的一半,再是一个布局存放歌词的,最后是一个空白布局高度是LycicView的一半。

这里动态的向第二个布局里面添加了显示歌词的TextView,并利用ViewTreeObserver得到每个textview的高度,方便知道每个textview歌词所要滑动到的高度。

public class LycicView extends ScrollView { LinearLayout rootView;//父布局 LinearLayout lycicList;//垂直布局 ArrayList lyricItems = new ArrayList();//每项的歌词集合  ArrayList lyricTextList = new ArrayList();//每行歌词文本集合,建议先去看看手机音乐里的歌词格式和内容 ArrayList lyricTimeList = new ArrayList();//每行歌词所对应的时间集合 ArrayList lyricItemHeights;//每行歌词TextView所要显示的高度  int height;//控件高度 int width;//控件宽度 int prevSelected = 0;//前一个选择的歌词所在的item   public LycicView(Context context) { super(context); init(); }  public LycicView(Context context, AttributeSet attrs) { super(context, attrs); init(); }  public LycicView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init(){ rootView = new LinearLayout(getContext()); rootView.setOrientation(LinearLayout.VERTICAL); //创建视图树,会在onLayout执行后立即得到正确的高度等参数 ViewTreeObserver vto = rootView.getViewTreeObserver(); vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { height = LycicView.this.getHeight(); width = LycicView.this.getWidth();  refreshRootView();  } }); addView(rootView);//把布局加进去 }  /** * */ void refreshRootView(){ rootView.removeAllViews();//刷新,先把之前包含的所有的view清除 //创建两个空白view LinearLayout blank1 = new LinearLayout(getContext()); LinearLayout blank2 = new LinearLayout(getContext()); //高度平分 LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(width,height/2); rootView.addView(blank1,params); if(lycicList !=null){ rootView.addView(lycicList);//加入一个歌词显示布局 rootView.addView(blank2,params); }  }  /** *设置歌词, */ void refreshLyicList(){ if(lycicList == null){ lycicList = new LinearLayout(getContext()); lycicList.setOrientation(LinearLayout.VERTICAL); //刷新,重新添加 lycicList.removeAllViews(); lyricItems.clear(); lyricItemHeights = new ArrayList(); prevSelected = 0; //为每行歌词创建一个TextView for(int i = 0;i=16 lyricItemHeights.add(index,textView.getHeight());//将高度添加到对应的item位置 } }); lycicList.addView(textView); lyricItems.add(index,textView); } } } /** * 滚动到index位置 */ public void scrollToIndex(int index){ if(index < 0){ scrollTo(0,0); } //计算index对应的textview的高度 if(index < lyricTextList.size()){ int sum = 0; for(int i = 0;i<=index-1;i++){ sum+=lyricItemHeights.get(i); } //加上index这行高度的一半 sum+=lyricItemHeights.get(index)/2; scrollTo(0,sum); } }  /** * 歌词一直滑动,小于歌词总长度 * @param length * @return */  int getIndex(int length){ int index = 0; int sum = 0; while(sum <= length){ sum+=lyricItemHeights.get(index); index++; } //从1开始,所以得到的是总item,脚标就得减一 return index - 1; }  /** * 设置选择的index,选中的颜色 * @param index */ void setSelected(int index){ //如果和之前选的一样就不变 if(index == prevSelected){ return; } for(int i = 0;i textList,ArrayList timeList){ //因为你从歌词lrc里面可以看出,每行歌词前面都对应有时间,所以两者必须相等 if(textList.size() != timeList.size()){ throw new IllegalArgumentException(); } this.lyricTextList = textList; this.lyricTimeList = timeList;  refreshLyicList(); }  @Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); //滑动时,不往回弹,滑到哪就定位到哪 setSelected(getIndex(t)); if(listener != null){ listener.onLyricScrollChange(getIndex(t),getIndex(oldt)); } } OnLyricScrollChangeListener listener; public void setOnLyricScrollChangeListener(OnLyricScrollChangeListener l){ this.listener = l; }  /** * 向外部提供接口 */ public interface OnLyricScrollChangeListener{ void onLyricScrollChange(int index,int oldindex); }}

二..MainActivity中的布局

   

相关内容

热门资讯

空调连续工作多久需要停机休息 空调连续工作的时间取决于多个因素,包括空调的型号、功率、使用环境和维护情况等。一般来说,空调可以连续...
空调哪个符号是除湿的 空调除湿功能通常用一个水滴形状的符号表示。不同品牌和型号的空调遥控器可能会有所差异,但一般来说,除湿...
格力空调多长时间加一次氟利昂 1、一般情况下,空调对氟利昂的使用量是非常小的,所以在空调使用了四年左右的时候再考虑加也没问题。2、...
空调用多长时间需要加氟一次 一般情况下是五年。当出现以下这几种情况时,空调才需要加氟。1、空调的室内机和室外机各有两个接口,当接...
格调生活·C标思享荟:卡萨帝在... 9月12日的郑州龙湖金融岛,夜风轻拂,灯光璀璨。“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑...
品牌价值破千亿、高端份额持续领... 9月12日,“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑州站”在郑州龙湖金融岛举办。2026...
空调主板坏了修800还是换新的 空调主板坏了是修还是换新,需要考虑多个因素,以下是一些建议:1. 维修成本:如果维修费用较低,比如 ...
空调开多久需要休息多长时间 问题:空调开多久需要休息多长时间回答:1、在使用空调的过程中,一般空调开7~8个小时左右需要休息2~...
中央空调多长时间清洗一次 1、一般空调开机前清洗一次即可,空调开机中间时段再清洗一次,空调关机时清洗一次,这样比较合理。2、空...
中央空调氟利昂多久加一次 看空调制热和制冷程度,很多人的观点认为氟利昂必须一年放一次,其实这个观点是错误的,理解上面有点偏差,...