摘要:大家都知道的最大好處就是開源,其實(shí)很多項(xiàng)目能全部用開源就能搞定。好了其它的也不多說,正式進(jìn)入主題,分享一下自己最近對(duì)開源代碼的理解。注釋源碼鏈接更多關(guān)注
大家都知道android的最大好處就是開源,其實(shí)很多項(xiàng)目能全部用開源就能搞定。但是當(dāng)我們?cè)谟瞄_源項(xiàng)目的時(shí)候,不懂得它們的原理,就相當(dāng)于過眼云煙,行尸走肉,只有空殼沒有寶貴的思想。當(dāng)我們的項(xiàng)目一旦要維護(hù)于優(yōu)化的時(shí)候,適應(yīng)需求時(shí),我們對(duì)那些只會(huì)拿來用的開源項(xiàng)目只能目瞪口呆。這樣不僅沒有加快我們的開發(fā)速度而且還會(huì)讓我們?nèi)P皆輸。好了其它的也不多說,正式進(jìn)入主題,分享一下自己最近對(duì)SlideSwitch開源代碼的理解。
說明首先還是要說明下SlideSwitch是什么開源項(xiàng)目,其實(shí)它就是一個(gè)我們幾乎每個(gè)項(xiàng)目中都會(huì)遇到的滑動(dòng)開關(guān),還不懂請(qǐng)看下圖:
對(duì)于大神來說我想早就已經(jīng)會(huì)了,所用這圖也請(qǐng)大神早點(diǎn)回家吃飯的分析要點(diǎn)
TypedArray 的使用
onMeasure 各個(gè)參數(shù)的初始化
onDraw 繪制圖形
onTouchEvent 監(jiān)聽觸摸點(diǎn)擊
ValueAnimator 動(dòng)畫實(shí)現(xiàn)
SlideSwitchListener 接口
TypedArray一般自定義控件都要用到TypedArray,所以SlideSwitch自然少不了。它就繼承了Android原生的View。而*TypedArray是獲取自定義屬性的參數(shù)值。
首先我們會(huì)在styles&或者attrs中定義屬性參數(shù)
format屬性類型,然后在XML中引用,引用之前一定要加入下面的聲明
xmlns:slideswitch="http://schemas.android.com/apk/res/xxx"
xxx:代表包名。直接引用就行
slideswitch:themeColor="#ffaaff"
最后在構(gòu)造方法中通過下面代碼獲取設(shè)置的參數(shù)值:
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.slideswitchview); theme_color = ta.getColor(R.styleable.slideswitchview_themeColor, DEFAULT_THEME_COLOR); ta.recycle();
使用完后務(wù)必recycle否則會(huì)對(duì)下次的使用造成影響onMeasure
每次視圖的創(chuàng)建都要先獲取視圖的寬高,次方法就會(huì)被調(diào)用。該方法參數(shù)widthMeasureSpec與heightMeasuerSpec不是一般的尺寸,而是包括了size與mode。所以為了獲取實(shí)際的寬高,要使用如下方法分別獲取size與mode:
int size = MeasureSpec.getSize(measureSpec); int mode = MeasureSpec.getMode(measureSpec);
通過mode來獲取size,mode有三種:
EXACTLY 精確尺寸,就是我們指定的尺寸
UNSPECIFIED 為指定的
AT_MOST 最大尺寸 形如指定WRAP_CONTENT在父控件允許的范圍內(nèi)
if (mode == MeasureSpec.EXACTLY) { result = size; } else { result = DefaultSize; //UNSPECIFIED if (mode == MeasureSpec.AT_MOST) { result = Math.min(size, result); } }
其它簡(jiǎn)單的參數(shù)值設(shè)置就不多說了,請(qǐng)移步最后的源碼onDraw
尺度獲取到了后,下面自然就是繪制,我們都知道選擇開關(guān)形狀有矩形的也有圓角矩形所以根據(jù)shpe的值來繪制相應(yīng)的形狀,這里以矩形為例
if (shape == 1) { mPaint.setColor(Color.GRAY); //繪制close時(shí)的灰色背景 canvas.drawRect(backRect, mPaint); mPaint.setColor(theme_color); mPaint.setAlpha(alpha); //繪制open時(shí)的彩色漸變背景 canvas.drawRect(backRect, mPaint); mPaint.setColor(Color.WHITE); frontRect.set(front_left, pandding, front_left + getMeasuredWidth() / 2 - pandding , getMeasuredHeight() - pandding); //繪制滑動(dòng)器 canvas.drawRect(frontRect, mPaint); }
其中padding代表內(nèi)邊距,就是滑動(dòng)器距邊框的距離
onTouchEvent這里就是實(shí)現(xiàn)動(dòng)態(tài)的觸摸滑動(dòng),根據(jù)ACTION_DOWN,ACTION_MOVE,ACTION_UP來實(shí)現(xiàn)動(dòng)態(tài)效果,至于點(diǎn)坐標(biāo)的處理,源碼很清楚。這里主要提下alpha參數(shù)的變化,該參數(shù)是實(shí)現(xiàn)顏色的透明效果,在這里通過觸摸滑動(dòng)的間距,動(dòng)態(tài)的改變alpha
alpha = (int) (255 * (float) front_left / (float) max_left);ValueAnimator
這個(gè)類是動(dòng)畫效果的核心,通過簡(jiǎn)單的幾步就能迅速的實(shí)現(xiàn)一些簡(jiǎn)單的動(dòng)畫
首先實(shí)例化這里使用的是ofInt(),當(dāng)然也有ofFloat()等靜態(tài)實(shí)例化方法
ValueAnimator valueAnimator = ValueAnimator.ofInt(front_left, toRight ? max_left : min_left);
兩個(gè)參數(shù)初值與結(jié)束值
//設(shè)置插值器 valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator()); valueAnimator.setDuration(500); valueAnimator.start();
Interpolator是定義動(dòng)畫的變化過程下面是一些常用參數(shù)
AccelerateDecelerateInterpolator 開始結(jié)束慢 中間過程快
AccelerateInterpolator 加速狀態(tài)
AnticipateInterpolator 先后移一點(diǎn),再快速移動(dòng)
BounceInterpolator 在最后有彈球效果
當(dāng)然你也可以自定義效果,只要繼承TimeInterpolator類,重寫getInterpolation方法自定義計(jì)算值
@Override public float getInterpolation(float input) { // 編寫相關(guān)的邏輯計(jì)算 return input; }
既然是動(dòng)畫自然有監(jiān)聽設(shè)置addUpdateListener實(shí)時(shí)改變滑動(dòng)初始值雨alpha
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { front_left = (int) animation.getAnimatedValue(); alpha = (int) (255 * (float) front_left / (float) max_left); initloop(); } });
最后增加addListener調(diào)用下面的接口SlideSwitchListener中的方法
valueAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (toRight) { isOpen = true; if (mSlideSwitchListener != null) mSlideSwitchListener.onOpen(); front_start_left = max_left; } else { isOpen = false; if (mSlideSwitchListener != null) mSlideSwitchListener.onClose(); front_start_left = min_left; } } });SlideSwitchListener
接口的定義使得在操作類中能更好的實(shí)現(xiàn)狀態(tài)改變后的相關(guān)操作
public void setSlideSwitchListener(SlideSwitchListener sideSwitchListener) { mSlideSwitchListener = sideSwitchListener; } public interface SlideSwitchListener { public void onOpen(); public void onClose(); }
只要稍微復(fù)雜的在這里都講到了,還有不明白的可以點(diǎn)擊查看下面我注釋的源碼,或者留言,謝謝瀏覽。
注釋源碼鏈接:https://github.com/idisfkj/Sl...
更多:https://idisfkj.github.io/
關(guān)注文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/110337.html
摘要:音樂團(tuán)隊(duì)分享數(shù)據(jù)綁定運(yùn)行機(jī)制分析一個(gè)項(xiàng)目搞定所有主流架構(gòu)單元測(cè)試一個(gè)項(xiàng)目搞定所有主流架構(gòu)系列的第二個(gè)項(xiàng)目。代碼開源,展示了的用法,以及如何使用進(jìn)行測(cè)試,還有用框架對(duì)的進(jìn)行單元測(cè)試。 Android 常用三方框架的學(xué)習(xí) Android 常用三方框架的學(xué)習(xí) likfe/eventbus3-intellij-plugin AS 最新可用 eventbus3 插件,歡迎品嘗 簡(jiǎn)單的 MVP 模...
閱讀 2902·2021-11-25 09:43
閱讀 2320·2021-11-24 09:39
閱讀 2708·2021-09-23 11:51
閱讀 1400·2021-09-07 10:11
閱讀 1449·2019-08-27 10:52
閱讀 1929·2019-08-26 12:13
閱讀 3356·2019-08-26 11:57
閱讀 1393·2019-08-26 11:31