android基础学习之一个简单的歌词滚动软件的实现

来源:互联网 发布:4g网络优化师 编辑:程序博客网 时间:2024/05/17 22:17

在开发当中我们时常会自己定义View对象,今天我写了一个View对象,来实现了歌词的滚动,因为知识不全面,所以之前或者现在的代码都有一定的缺陷,在以后会慢慢修改,,现在只是为了了解大概框图,然后不断学习,废话不多说代码实现

程序入口

package com.example.viewdemo;import android.os.Bundle;import android.app.Activity;import android.view.Menu;public class MainActivity extends Activity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);    }    }

在写xml文件的时候,我们自己定义的View一定要记得引入包名

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    tools:context=".MainActivity" >   <com.example.viewdemo.LrcView        android:layout_width="fill_parent"        android:layout_height="fill_parent" /></RelativeLayout>

自定义View' 代码注解里面应该说的很清楚了

package com.example.viewdemo;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.util.ArrayList;import org.xml.sax.InputSource;import android.content.Context;import android.content.res.AssetManager;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.util.AttributeSet;import android.view.View;public class LrcView extends View {  private Paint paint;  private int text_x,text_y;  private int width,height;  private int refreshIndex;  private int currentLrcIndex;  private ArrayList<String> lrcs;  private ArrayList<Integer> lrcTimes;  private int move_y;  private int move_count;  //3个构造方法,前两个用于xml解析,第三个是用于java构建对象public LrcView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);//通过为最多的参数设置初始化,然后让其它的都直接调用它init();}public LrcView(Context context, AttributeSet attrs) {this(context,attrs,0);}public LrcView(Context context) {this(context,null);}private void init() {//创建画笔paint=new Paint();paint.setTextSize(30);//获取字体的大小,字体是正方形的float TextSize=paint.getTextSize();text_x=0;text_y=(int) TextSize;//每次取得歌词时,向上移动一个字的高度move_y=(int) TextSize;//歌词初始值currentLrcIndex=-1;refreshIndex=-2;//读取歌词try {readLrc();} catch (IOException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}new Thread(new Runnable() {@Overridepublic void run() {//时间一般由多媒体框架返回,但是这里我们是测试,所以我们就使用线程的开始时间long musicStart=System.currentTimeMillis();while(true){try {Thread.sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}//计算应该放哪一句歌词long currentTime=System.currentTimeMillis();long duration=currentTime-musicStart;int lrcDataLength=lrcTimes.size();//从所有的歌词中找到当前时间应该显示的歌词的下标for(int i=0;i<lrcDataLength;i++){int time=lrcTimes.get(i);System.out.println("time="+time);System.out.println("duration="+duration);//找到第一个大于我们当前的时间点,那么前一个就是我们需要找的歌词if(time>duration){currentLrcIndex=i-1;if(currentLrcIndex!=-1&&refreshIndex!=currentLrcIndex){//调用postInvalidata()方法,这个方法回毁掉onDraw方法绘制试图postInvalidate();//下标更新refreshIndex=currentLrcIndex;}break;}}}}}).start();}//重写onLayout方法,为了获得容器的宽和高@Overrideprotected void onLayout(boolean changed, int left, int top, int right,int bottom) {// TODO Auto-generated method stubsuper.onLayout(changed, left, top, right, bottom);width=right-left;height=bottom-top;}//重写onDraw方法,实现视图的展示@Overrideprotected void onDraw(Canvas canvas) {// TODO Auto-generated method stubsuper.onDraw(canvas);int lrcShowLength=lrcs.size();for(int i=0;i<lrcShowLength;i++){if(i==currentLrcIndex){paint.setColor(Color.BLUE);}else{paint.setColor(Color.BLACK);}//取出歌词String lrc=lrcs.get(i);//重新获取画笔的大小float textSize=paint.getTextSize();float[] widths=new float[lrcs.size()];int number=paint.getTextWidths(lrc, 0, lrc.length()-1, widths);int textwidth=0;for (float w : widths) {textwidth+=w;}//设置文字的锚点x坐标text_x=width/2-textwidth/2;//设置文字的锚点的y坐标int text_y_offset=(int) (i*textSize);int text_time_offset=move_y*move_count;text_y=(int) (height/2+textSize/2+text_y_offset+text_time_offset);canvas.drawText(lrc, text_x, text_y, paint);}//每绘制一次,我们的坐标就像上移动一次move_count--;}private void readLrc() throws IOException {lrcs=new ArrayList<String>();lrcTimes=new ArrayList<Integer>();//由于每个View的构造器都有一个context,那么在LrcView中也会有一个contextContext context=getContext();//assests中的文件不会被转换成为2进制AssetManager assetsManager=context.getAssets();InputStream in=assetsManager.open("text.txt");InputStreamReader isr=new InputStreamReader(in);BufferedReader bReader=new BufferedReader(isr);String lineStr = null;bReader.readLine() ;//while ((lineStr = bReader.readLine()) != null) {// 不为空,则能读取到数据String timeStr = lineStr.substring(1, 9);String lrcStr = lineStr.substring(10);//System.out.println("timeStr = "+timeStr);//System.out.println("lrcStr = "+lrcStr);//解析 00:00.00String min = timeStr.substring(0, 2) ;String sec = timeStr.substring(3, 5) ;String ms = timeStr.substring(6) ;//使用封装类,将数字组成的字符串,转换为数字int minI = Integer.valueOf(min) ;int secI = Integer.valueOf(sec) ;int msI = Integer.valueOf(ms) ;int lrcTime = minI*60*1000 + secI*1000 + msI*10 ;System.out.println("lrcTime = "+lrcTime);//添加时间点lrcTimes.add(lrcTime) ;//添加歌词lrcs.add(lrcStr) ;}}}
需要解析的lrc歌词文件,自己可以去看,格式是差不多的,这里主要是提供了一种思路

0 0
原创粉丝点击