效果如下圖第一個控件

源碼在文末
自定義一個漸變色的進度條,需要怎樣定義?又會遇到什么坑?
帶著這些問題,開始發(fā)車。
思考
1如何繪制
2遇到什么坑
如何繪制
只要安卓開發(fā)中,扯上了自定義控件這個字眼,那么,使用canvas就八九不離十了。本次實踐中,自定義的是一個進度條,那么,進度條,有什么最最基本要素?
(一)當前進度
(二)背景顏色
除了上述意外,還有一些要素,如:緩存進度等等。確實都是大同小異,只要了解實現(xiàn)的原理,那這些都是時間的產(chǎn)物而已。
話回正題,如何實現(xiàn)。
首先,定義好外部調(diào)用的時候,需要傳入什么參數(shù),這個很關(guān)鍵,定義不好,就會有很多返工的機會。
筆者針對當前開發(fā)需求,定義了一個外部傳入對象,代碼如下:
//進度條背景色--resource color
private int bgColor = R.color.color_a8a8a8;
//進度條開始顏色
private int progressStartColor = R.color.colorPrimaryDark;
//進度條結(jié)束顏色
private int progressEndColor = R.color.blue_light;
//進度條圓角
private int radius = 20;
//進度條文字大小,文字顏色,顯示的文字
private int textSize = 16;
private int textColor = R.color.color_ffffff;
private String text = "100%";
//文字是否加粗
private boolean textBold = false;
//進度--最大100
private int progress = 6;
上圖中的定義,基本滿足當時的需求了。定義好以后,就可以進行自定義view中的canvas開發(fā)了。
canvas繪制是有層級的,所以,繪制背景,是第一個操作,再者,就是當前進度,最后,就是進度的文字了。
其中,繪制的字體的時候,注意canvas的drawtext中,y的真正含義。具體可以自行了解開發(fā)文檔。
繪制進度條背景核心代碼如下:
int radius = dp2px(mDrawInfo.getRadius());
mPaint.setColor(getResources().getColor(mDrawInfo.getBgColor()));
canvas.drawRoundRect(0, 0, mViewWidth, mViewHeight, radius, radius, mPaint);
其實就是一個drawRoundRect的api調(diào)用,沒什么特別的。
繪制當前進度核心代碼如下:
mPaint.setShader(new LinearGradient(0, 0, mDrawProgress, mViewHeight,
getResources().getColor(mDrawInfo.getProgressStartColor()),
getResources().getColor(mDrawInfo.getProgressEndColor()),
Shader.TileMode.CLAMP
));
RectF rectProgress = new RectF(0, 0, mDrawProgress, mViewHeight);
canvas.drawRoundRect(rectProgress, radius, radius, mPaint);
因為需求需要當前進度顯示一個漸變的顏色,所以,就要對paint畫筆對象,設(shè)置一個過渡效果,調(diào)用setShader對象即可。
最后,繪制文字,核心代碼如下:
canvas.drawText(mDrawText, mDrawTextX,
mViewHeight - mDrawTextHeightInterval, mPaint);
其實就是也是一個drawText方法調(diào)用,沒什么特別的。
至此,思路已經(jīng)說完了。但是實際開發(fā)中,會有一些地方需要注意的,下面開始發(fā)車。
遇到的問題
一、當畫筆對象setShader后,若下一個繪制操作不需要,記得要調(diào)用setShader(null)。否則會繼續(xù)保持。
二、對于進度值很少的時候,會出現(xiàn)一個很特別的情況,由于調(diào)用的是drawRoundRect方法,所以圓角的地方,會不重合,開發(fā)者可以試一下。
如何解決?這就要使用Paint.setXfermode的方法中的PorterDuff.Mode.SRC_IN方法。此外,還要禁用硬件加速setLayerType(View.LAYER_TYPE_SOFTWARE, null)。注意?。?!畫筆在調(diào)用setXfermode方法后,記得及時set null。
動畫
對于設(shè)置進度的動畫,用插值器實現(xiàn)就好,這里不一一敘述。
寫在最后
對于自定義控件,難的不是調(diào)用canvas的接口,而是調(diào)用完這些接口以后,如何保證結(jié)果如期,如何調(diào)整整合帶來的兼容問題。
that's all----------------------------------------------------------------------------------------------