欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android仿天天動聽歌曲自動滾動view

 更新時(shí)間:2016年05月19日 14:13:11   投稿:lijiao  
這篇文章主要為大家詳細(xì)介紹了Android仿天天動聽歌曲自動滾動view的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

最近項(xiàng)目中要做一個(gè)類似天天動聽歌曲自動滾動行數(shù)的效果。首先自己想了下Android要滾動的那就是scroller類或者scrollto、scrollby結(jié)合了,或者view.layout()方法,或者使用動畫。但是要循環(huán)滾動,貌似這些到最后一行滾動到第一行都有往回滾的效果,都不是很好的解決方法。怎么會忘記了可以繪制事件萬物的的canvas呢。好吧,既然找到了,那就用這個(gè)方案吧!但是天天動聽歌曲還有一個(gè)手動滑動的效果,貌似這篇文章沒寫。既然這樣,那就自己來寫下吧!實(shí)現(xiàn)之前還是先看下天天動聽的效果:

正文

想法1:獲取滑動的距離,然后計(jì)算滑動了多少行,然后更新數(shù)據(jù)。實(shí)現(xiàn)起來貌似效果不咋地。
想法2:我們可以看的出來他滾動是一行一行的滾動的,只是根據(jù)滾動的快慢來決定滾動行數(shù)的快慢。既然這樣的話,只要滾動了,就一定時(shí)間的去一行行的滾動,然后根據(jù)滾動的速度來決定更新的間隔時(shí)間。

嗯,想好了怎么實(shí)現(xiàn),現(xiàn)在就來寫代碼吧。

先來寫一個(gè)類,繼承TextView

VerticalScrollTextView.class

public class VerticalScrollTextView extends TextView implements Runnable{
 //繪制歌詞畫筆
 private Paint mContentPaint;
 //繪制基線畫筆
 private Paint mLinePaint;
 //繪制滑動進(jìn)度背景畫筆
 private Paint mRectPaint;
 //歌詞數(shù)據(jù)
 private List<Sentence> mDataList;
 //行數(shù)
 private int index = 0 ;
 //當(dāng)前view的寬
 private float mX;
 //當(dāng)前view的高
 private float mY;
 //當(dāng)前view垂直方向中線
 private float middleY;
 //行與行之間的間距
 private final static int DY = 80 ;
 //歌詞文字大小
 private int mTextSize = 35;
 //歌詞中間字體的大小
 private int mBigTextSize = 45;
 //當(dāng)前是否按下
 private boolean isTouch = false ;
 //上一次觸摸view的y軸坐標(biāo)
 private float mLastY;
 //是否正在滑動
 private boolean isMoving;
 //記錄上一次滑動的時(shí)間
 private long lastMoveTime;
 //滑動速度追蹤類
 private VelocityTracker mVelocityTracker;
 //滑動最大速度
 private int mMaximumVelocity;
 //歌詞是否為空
 private boolean isEmpty;

 public VerticalScrollTextView(Context context) {
 this(context,null);
 }

 public VerticalScrollTextView(Context context, AttributeSet attrs) {
 this(context, attrs,0);
 }

 public VerticalScrollTextView(Context context, AttributeSet attrs, int defStyleAttr) {
 super(context, attrs, defStyleAttr);
 //獲取最大的滑動速度值
 mMaximumVelocity = ViewConfiguration.get(context)
  .getScaledMaximumFlingVelocity();
 init();
 }
 private void init(){
 setFocusable(true);
 setClickable(true);
 //歌詞為空設(shè)置默認(rèn)值
 if(mDataList==null){
  mDataList = new ArrayList<>();
  Sentence sentence = new Sentence(0,"沒有獲取到歌詞",0);
  mDataList.add(sentence);
  isEmpty = true ;
 }
 //初始化歌詞畫筆
 mContentPaint = new Paint();
 mContentPaint.setTextSize(mTextSize);
 mContentPaint.setAntiAlias(true);
 mContentPaint.setColor(Color.parseColor("#e5e2e2"));
 //設(shè)置為serif字體
 mContentPaint.setTypeface(Typeface.SERIF);
 //設(shè)置字體為居中
 mContentPaint.setTextAlign(Paint.Align.CENTER);
 //初始化基線畫筆
 mLinePaint = new Paint();
 mLinePaint.setAntiAlias(true);
 mLinePaint.setStrokeWidth(1);
 mLinePaint.setColor(Color.WHITE);
 //進(jìn)度背景顏色畫筆
 mRectPaint = new Paint();
 mLinePaint.setAntiAlias(true);
 mRectPaint.setColor(Color.parseColor("#66666666"));
 }

 @Override
 protected void onDraw(Canvas canvas) {
 super.onDraw(canvas);
 //如果當(dāng)前進(jìn)度為-1,直接返回,不用繪制
 if (index == -1)
  return;
 Sentence sentence = mDataList.get(index);
 //繪制中間行的歌詞,設(shè)置為高亮白色,大字體
 mContentPaint.setColor(Color.WHITE);
 mContentPaint.setTextSize(mBigTextSize);
 canvas.drawText(sentence.getName(), mX/2, middleY, mContentPaint);
 //當(dāng)前為歌詞不為空并且按下的情況下,繪制基線和進(jìn)度
 if(!isEmpty&&isTouch){
  //獲取中間行字體最高的位置
  float baseLine = middleY-Math.abs(mContentPaint.ascent());
  //繪制進(jìn)度背景
  canvas.drawRect(10.0f,baseLine-70,150.0f,baseLine,mRectPaint);
  //繪制基線
  canvas.drawLine(10.0f,baseLine,mX-10,baseLine,mLinePaint);
  //設(shè)置進(jìn)度字體大小
  mContentPaint.setTextSize(mTextSize);
  //繪制進(jìn)度字體
  canvas.drawText(String.valueOf(index),85,baseLine-35,mContentPaint);
 }
 //初始化isEmpty
 isEmpty = false ;
 //初始化歌詞內(nèi)容畫筆
 mContentPaint.setColor(Color.parseColor("#e5e2e2"));
 mContentPaint.setTextSize(mTextSize);
 //暫時(shí)保存中間線位置,來繪制中間線以上的行數(shù)字體
 float tempY = middleY;
 //繪制中間線以上的歌詞
 for (int i = index - 1; i >= 0; i--) {
  tempY = tempY - DY;
  if (tempY < 0) {
  break;
  }
  Sentence preSentence = mDataList.get(i);
  canvas.drawText(preSentence.getName(), mX/2, tempY, mContentPaint);
 }
 tempY = middleY;
 //繪制中間線以下的歌詞
 for (int i = index + 1; i < mDataList.size(); i++) {
  tempY = tempY + DY;
  if (tempY > mY) {
  break;
  }
  Sentence nexeSentence = mDataList.get(i);
  canvas.drawText(nexeSentence.getName(), mX/2, tempY, mContentPaint);
 }
 //初始化isMoving,到這里表示滑動結(jié)束
 isMoving = false ;
 }
 protected void onSizeChanged(int w, int h, int ow, int oh) {
 super.onSizeChanged(w, h, ow, oh);
 //獲取view的寬和高
 mX = w;
 mY = h;
 middleY = h * 0.5f;
 }
 public long updateIndex(int index) {
 if (index == -1)
  return -1;
 this.index=index;
 return index;
 }
 public List<Sentence> getDataList() {
 return mDataList;
 }
 public void setDataList(List<Sentence> mDataList){
 this.mDataList = mDataList ;
 }
 public void updateUI(){
 new Thread(this).start();
 }

 @Override
 public boolean onTouchEvent(MotionEvent event) {
 int action = event.getAction();
 switch (action){
  case MotionEvent.ACTION_DOWN:
  isTouch =true;
  mLastY = event.getY();
  break;
  case MotionEvent.ACTION_MOVE:
  //創(chuàng)建速度追蹤器
  initVelocityTrackerIfNotExists();
  mVelocityTracker.addMovement(event);
  mVelocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
  //獲取當(dāng)前速度。默認(rèn)為100
  float velocity = mVelocityTracker.getYVelocity()==0?100:mVelocityTracker.getYVelocity();
  long currentTime = System.currentTimeMillis();
  //設(shè)置一個(gè)固定值和速度結(jié)合決定滑動更新的快慢
  if(!isMoving&&currentTime-lastMoveTime>20000/Math.abs(velocity)){
   isMoving = true ;
   lastMoveTime = System.currentTimeMillis();
   float currentY = event.getY();
   float mMoveY = currentY - mLastY;
   //向上滑動-1向下滑動+1
   int newIndex = mMoveY>0?index - 1:index+1;
   //循環(huán)滾動
   newIndex=newIndex<0?mDataList.size()-1:newIndex>=mDataList.size()?0:newIndex;
   updateIndex(newIndex);
   invalidate();
   mLastY = currentY;
  }
  break;
  case MotionEvent.ACTION_UP:
  isTouch = false ;
  recycleVelocityTracker();
  break;
 }
 return super.onTouchEvent(event);
 }

 @Override
 public void run() {
 //自動滾動刷新的時(shí)間間隔
 long time = 1000;
 //控制進(jìn)度
 int i=0;
 while (true) {
  //當(dāng)前不在按下的情況下自動滾動
  if(!isTouch){
  //設(shè)置當(dāng)前的進(jìn)度值
  long sleeptime = updateIndex(i);
  //使用handle刷新ui
  mHandler.post(mUpdateResults);
  if (sleeptime == -1)
   return;
  try {
   Thread.sleep(time);
   i++;
   //當(dāng)?shù)搅俗詈笠恍械臅r(shí)候自動跳轉(zhuǎn)到第一行
   if(i==getDataList().size())
   i=0;
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
  }
 }
 }
 Handler mHandler = new Handler();
 Runnable mUpdateResults = new Runnable() {
 public void run() {
  invalidate();
 }
 };
 //創(chuàng)建速度追蹤器
 private void initVelocityTrackerIfNotExists() {
 if (mVelocityTracker == null) {
  mVelocityTracker = VelocityTracker.obtain();
 }
 }
 //釋放
 private void recycleVelocityTracker() {
 if (mVelocityTracker != null) {
  mVelocityTracker.recycle();
  mVelocityTracker = null;
 }
 }
}

自定義view基本就是這樣了,我們可以把要定義的一些屬性寫在attrs里面了,這里就懶得寫了。大概的思路就是先繪制指定的index行的歌詞,然后繪制index上面行的歌詞,然后繪制index下面行的歌詞。然后新建一個(gè)線程,讓它通過handle隔一定的時(shí)間定時(shí)刷新歌詞行數(shù)。然后在onTouchEvent處理觸摸滾動行數(shù),獲取到當(dāng)前滾動速度來決定一個(gè)更新的時(shí)間間隔。從而實(shí)現(xiàn)觸摸滾動刷新的快慢?;旧暇褪沁@樣了。其他的看注釋。

再看下初始化數(shù)據(jù)測試的Activity:

VerticalScrollTextActivity.class

public class VerticalScrollTextActivity extends Activity {
 VerticalScrollTextView mSampleView;
 String[] str = {"你在南方的艷陽里 大雪紛飛",
  "我在北方的寒夜里 四季如春",
  "如果天黑之前來的及",
  "我要忘了你的眼睛",
  "窮極一生 做不完一場夢",
  "他不在和誰談?wù)撓喾甑墓聧u",
  "因?yàn)樾睦镌缫鸦臒o人煙",
  "他的心里在裝不下一個(gè)家",
  "做一個(gè)只對自己說謊的啞巴",
  "他說你任何為人稱道的美麗",
  "不及他第一次遇見你",
  "時(shí)光茍延殘喘 無可奈何",
  "如果所有土地連在一起",
  "走上一生只為擁抱你",
  "喝醉了他的夢 晚安",
  "你在南方的艷陽里 大雪紛飛",
  "我在北方的寒夜里 四季如春",
  "如果天黑之前來的及",
  "我要忘了你的眼睛",
  "窮極一生 做不完一場夢",
  "他不在和誰談?wù)撓喾甑墓聧u",
  "因?yàn)樾睦镌缫鸦臒o人煙",
  "他的心里在裝不下一個(gè)家",
  "做一個(gè)只對自己說謊的啞巴",
  "他說你任何為人稱道的美麗",
  "不及他第一次遇見你",
  "時(shí)光茍延殘喘 無可奈何",
  "如果所有土地連在一起",
  "走上一生只為擁抱你",
  "喝醉了他的夢 晚安"
 };
 @Override
 public void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 mSampleView = (VerticalScrollTextView) findViewById(R.id.sampleView1);
 List lst=new ArrayList<>();
 for(int i=0;i<str.length;i++){
  Sentence sen=new Sentence(i,str[i],i+1202034);
  lst.add(i, sen);
 }
 mSampleView.setDataList(lst);
 mSampleView.updateUI();
 } 
}

模擬了一首歌詞數(shù)據(jù),然后setDataList,在調(diào)用updateUI()就行了。

最后看下布局文件

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent">

 <com.goach.lib.VerticalScrollTextView
 android:id="@+id/sampleView1"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:background="@drawable/bg"
 />
</RelativeLayout>

測試下,我們就可以看到效果了:

 

源碼下載:Android仿天天動聽歌曲自動滾動

以上就是本文的全部內(nèi)容,希望對大家學(xué)習(xí)Android軟件編程有所幫助。

相關(guān)文章

最新評論