Android自定義View實(shí)現(xiàn)縱向跑馬燈效果詳解
首先看看效果圖(錄制的gif有點(diǎn)卡,真實(shí)的效果還是很流暢的)
實(shí)現(xiàn)思路
通過上面的gif圖可以得出結(jié)論,其實(shí)它就是同時(shí)繪制兩條文本信息,然后通過動(dòng)畫不斷的改變兩條文本信息距離頂部的高度,以此來實(shí)現(xiàn)滾動(dòng)的效果。
具體實(shí)現(xiàn)
首先定義一些要用到的屬性
<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"/> 動(dòng)畫開始延遲時(shí)間 <attr name="reRepeatDelayTime" format="integer"/> 動(dòng)畫重復(fù)延遲時(shí)間 <attr name="itemAnimationTime" format="integer"/> 單個(gè)動(dòng)畫的執(zhí)行時(shí)間 </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)); } }
數(shù)據(jù)為空時(shí)調(diào)用父類的方法,設(shè)置數(shù)據(jù)以后根據(jù)不同的布局計(jì)算寬高。
設(shè)置數(shù)據(jù)
public void setTextArray(String[] textArray) { if(textArray == null || textArray.length <= 1) return; mTextArray = textArray; initTextRect(); setTextCurrentOrNextStatus(0, 1, true); startAnimation();}
initTextRect()
方法是計(jì)算出單個(gè)文本的高度和數(shù)組中最大文本的寬度,文本的高度用來計(jì)算繪制文本時(shí)的位置,文本的最大寬度在onMeasure()
方法的時(shí)候會(huì)用到。
setTextCurrentOrNextStatus()
方法設(shè)置當(dāng)前的position,文本以及下一個(gè)position,文本。還有文本距離頂部的初始化高度。
startAnimation()
方法 開始執(zhí)行動(dòng)畫。
動(dòng)畫實(shí)現(xiàn)
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);
設(shè)置動(dòng)畫無限重復(fù)
onAnimationUpdate()
方法得到動(dòng)畫執(zhí)行的進(jìn)度,計(jì)算出text距離頂部的距離,調(diào)用postInvalidate()
方法刷新界面。
onAnimationRepeat()
方法,通過handler延遲reRepeatDelayTime時(shí)間,再重新執(zhí)行動(dòng)畫。
繪制
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); } }
總結(jié)
到這里所有的代碼已經(jīng)分析完畢,其實(shí)實(shí)現(xiàn)這個(gè)效果還有很多種方法,通過繼承ViewGroup等等都可以實(shí)現(xiàn),大家有興趣可以自己嘗試。希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能有所幫助,如果有疑問大家可以留言交流。
- Android TextView實(shí)現(xiàn)跑馬燈效果的方法
- Android 中TextView中跑馬燈效果的實(shí)現(xiàn)方法
- Android自定義View實(shí)現(xiàn)豎直跑馬燈效果案例解析
- Android中使用TextView實(shí)現(xiàn)文字跑馬燈效果
- Android跑馬燈MarqueeView源碼解析
- Android基于TextView不獲取焦點(diǎn)實(shí)現(xiàn)跑馬燈效果
- Android自定義textview實(shí)現(xiàn)豎直滾動(dòng)跑馬燈效果
- Android 實(shí)現(xiàn)不依賴焦點(diǎn)和選中的TextView跑馬燈
- Android基于TextView屬性android:ellipsize實(shí)現(xiàn)跑馬燈效果的方法
- android自定義View實(shí)現(xiàn)跑馬燈效果
相關(guān)文章
android中用xml文件實(shí)現(xiàn)帶邊框背景效果的方法
這篇文章主要給大家介紹了在android中xml文件實(shí)現(xiàn)帶邊框背景效果的方法,其實(shí)實(shí)現(xiàn)的功能不是很難,僅作記錄,幫助需要的朋友們做個(gè)參考,需要的朋友們下面來一起看看吧。2017-06-06Android編程實(shí)現(xiàn)保存圖片到系統(tǒng)圖庫的方法示例
這篇文章主要介紹了Android編程實(shí)現(xiàn)保存圖片到系統(tǒng)圖庫的方法,結(jié)合實(shí)例形式分析了Android保存圖片到系統(tǒng)圖庫的常見操作方法、注意事項(xiàng)與相關(guān)問題解決技巧,需要的朋友可以參考下2017-08-08Android運(yùn)行時(shí)權(quán)限終極方案(PermissionX)
這篇文章主要介紹了Android運(yùn)行時(shí)權(quán)限終極方案(PermissionX),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05Android實(shí)戰(zhàn)教程第四十篇之Chronometer實(shí)現(xiàn)倒計(jì)時(shí)
這篇文章主要介紹了Android實(shí)戰(zhàn)教程第四十篇之Chronometer實(shí)現(xiàn)倒計(jì)時(shí),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-11-11Android仿滴滴出行驗(yàn)證碼輸入框功能實(shí)例代碼
最近項(xiàng)目經(jīng)理交給我們組一個(gè)類似滴滴出行填寫驗(yàn)證碼的彈框功能,拿到這個(gè)項(xiàng)目需求真是把我忙暈了,下面通過本文給大家分享Android仿滴滴出行驗(yàn)證碼輸入框功能實(shí)例代碼,需要的朋友參考下吧2017-12-12ViewPager 與 Fragment相結(jié)合實(shí)現(xiàn)微信界面實(shí)例代碼
這篇文章主要介紹了ViewPager 與 Fragment相結(jié)合實(shí)現(xiàn)微信界面實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2016-07-07android實(shí)現(xiàn)漢字轉(zhuǎn)拼音功能 帶多音字識(shí)別
這篇文章主要介紹了android實(shí)現(xiàn)漢字轉(zhuǎn)拼音功能,帶多音字識(shí)別,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-02-02