Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android自定義View實現縱向跑馬燈效果詳解

Android自定義View實現縱向跑馬燈效果詳解

編輯:關於Android編程

首先看看效果圖(錄制的gif有點卡,真實的效果還是很流暢的)

實現思路

通過上面的gif圖可以得出結論,其實它就是同時繪制兩條文本信息,然後通過動畫不斷的改變兩條文本信息距離頂部的高度,以此來實現滾動的效果。

具體實現

首先定義一些要用到的屬性

<declare-styleable name="MarqueeViewStyle">  
<attr name="textSize" format="dimension" />  
<attr name="textColor" format="color" />  
<attr name="paddingLeft" format="dimension" />  
<attr name="paddingTop" format="dimension" />  
<attr name="paddingBottom" format="dimension" />  
<attr name="paddingTopBottom" format="dimension"/>  
<attr name="startDelayTime" format="integer"/> 動畫開始延遲時間
<attr name="reRepeatDelayTime" format="integer"/> 動畫重復延遲時間 
<attr name="itemAnimationTime" format="integer"/> 單個動畫的執行時間
</declare-styleable>

接下來解析屬性值

private void init(Context context, AttributeSet attrs) {  
 TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MarqueeViewStyle);  
 mTextColor = typedArray.getColor(R.styleable.MarqueeViewStyle_textColor, Color.BLACK);  
 mTextSize = typedArray.getDimensionPixelSize(R.styleable.MarqueeViewStyle_textSize, 45);  

 mPaddingLeft = typedArray.getDimensionPixelSize(R.styleable.MarqueeViewStyle_paddingLeft, 15);  
 mPaddingTop = mPaddingBottom = typedArray.getDimensionPixelSize(R.styleable.MarqueeViewStyle_paddingTopBottom, 25);  
 mPaddingTop = typedArray.getDimensionPixelSize(R.styleable.MarqueeViewStyle_paddingTop, mPaddingTop);  
 mPaddingBottom = typedArray.getDimensionPixelSize(R.styleable.MarqueeViewStyle_paddingBottom, mPaddingBottom);  

 itemAnimationTime = typedArray.getInteger(R.styleable.MarqueeViewStyle_itemAnimationTime, 1000);  
 reRepeatDelayTime = typedArray.getInteger(R.styleable.MarqueeViewStyle_reRepeatDelayTime, 1000);  
 startDelayTime = typedArray.getInteger(R.styleable.MarqueeViewStyle_startDelayTime, 500);  
 typedArray.recycle();  

  mPaint = new Paint();  
  mPaint.setAntiAlias(true);  
  mPaint.setTextSize(mTextSize);  
  mPaint.setColor(mTextColor);  
  mPaint.setTextAlign(Paint.Align.LEFT);}

重寫onMeasure方法

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
  if(mTextArray == null || mTextArray.length == 0) {   
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);  
  } else {    
    int width = MeasureSpec.getSize(widthMeasureSpec);  
    int height = MeasureSpec.getSize(heightMeasureSpec);   
    ViewGroup.LayoutParams lp = getLayoutParams();    
    setMeasuredDimension(getViewWidth(lp, width), getViewHeight(lp, height));  
  }
}

數據為空時調用父類的方法,設置數據以後根據不同的布局計算寬高。

設置數據

public void setTextArray(String[] textArray) {  
  if(textArray == null || textArray.length <= 1) return;  
  mTextArray = textArray;  
  initTextRect();  
  setTextCurrentOrNextStatus(0, 1, true);  
  startAnimation();}

initTextRect()方法是計算出單個文本的高度和數組中最大文本的寬度,文本的高度用來計算繪制文本時的位置,文本的最大寬度在onMeasure()方法的時候會用到。

setTextCurrentOrNextStatus()方法設置當前的position,文本以及下一個position,文本。還有文本距離頂部的初始化高度。

startAnimation() 方法 開始執行動畫。

動畫實現

private void startAnimation() {  
 va = ValueAnimator.ofFloat(0, 1);  
 va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {    
 @Override    
 public void onAnimationUpdate(ValueAnimator animation) {  
   mProgress = (float) animation.getAnimatedValue();      
.   int moveOffset = (int) (mTextMoveOffset * mProgress); 
   mCurrentTextMoveMarginTop = mCurrentTextInitMarginTop - moveOffset;      
   mNextTextMoveMarginTop = mNextTextInitMarginTop - moveOffset;      
   postInvalidate();    
 }  
 });  

 va.addListener(new AnimatorListenerAdapter() {    
   @Override    
   public void onAnimationRepeat(Animator animation) {   
    va.pause();        
    setTextCurrentOrNextStatus(mNextTextPosition, mNextTextPosition + 1, false);      
    handler.postDelayed(new Runnable() {        
     @Override        
     public void run() {          
      va.resume();        
     } 
    }, reRepeatDelayTime);    
   }  
 });  
 va.setRepeatCount(-1);  
 va.setDuration(itemAnimationTime);  
 va.setStartDelay(startDelayTime);  
 va.start();
}

va.setRepeatCount(-1); 設置動畫無限重復

onAnimationUpdate() 方法得到動畫執行的進度,計算出text距離頂部的距離,調用postInvalidate()方法刷新界面。

onAnimationRepeat() 方法,通過handler延遲reRepeatDelayTime時間,再重新執行動畫。

繪制

protected void onDraw(Canvas canvas) {  
 if(mTextArray == null || mTextArray.length == 0) {   
  super.onDraw(canvas);  
 } else {    
  canvas.drawText(mCurrentText, mPaddingLeft, mCurrentTextMoveMarginTop, mPaint);  
  canvas.drawText(mNextText, mPaddingLeft, mNextTextMoveMarginTop, mPaint);  
 }
}

總結

到這裡所有的代碼已經分析完畢,其實實現這個效果還有很多種方法,通過繼承ViewGroup等等都可以實現,大家有興趣可以自己嘗試。希望本文的內容對大家的學習或者工作能有所幫助,如果有疑問大家可以留言交流。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved