還在爲了一個小小的效果,依賴一個一個的第三方?
看着別人隨隨便便寫了一個自定義效果,自己卻除了666啥也做不了?
如果你認爲自己就是這樣,那麼,你要好好看一下這篇文章了!
進度條作爲移動開發的一個常用功能,相信你一定不陌生。本篇,我們要手動編寫一個簡單的進度條,模擬一下下載的效果。
一、效果
二、分析
自定義View,分析裏面的元素:
1、進度條背景顏色
2、進度條背景是否是實心
3、進度條的顏色
4、進度(文字)的顏色和字體大小
5、進度條的圓角大小
三、實現
1、自定義View類,繼承View
public class CustomProgressView extends View {
public CustomProgressView(Context context) {
this(context, null);
}
public CustomProgressView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public CustomProgressView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
2、在attr文件中,定義樣式
<declare-styleable name="CustomProgressView">
<!--百分比文字大小-->
<attr name="cp_percent_textsize" format="dimension"/>
<!--百分比文字顏色-->
<attr name="cp_percent_textcolor" format="color|integer"/>
<!--進度條背景顏色-->
<attr name="cp_background_color" format="color|integer"/>
<!--進度條背景是否空心-->
<attr name="cp_background_is_stroke" format="boolean"/>
<!--進度條顏色-->
<attr name="cp_progress_color" format="color|integer"/>
<!--進度條圓角值-->
<attr name="cp_rect_round" format="dimension"/>
</declare-styleable>
定義元素,並賦予正確的屬性類型。
3、在構造方法中,調用obtainStyledAttributes方法,獲取自定義的style,並初始化個屬性,同時,初始化畫筆Paint
private int cp_percent_textsize = 18;//百分比字體大小
private int cp_percent_textcolor = 0xff009ACD;
private int cp_background_color = 0xff636363;
private int cp_progress_color = 0xff00C5CD;
private boolean cp_background_is_stroke = true;
private int cp_rect_round = 5;
private Paint mPaint;
private int mCenterX;
private int mCenterY;
private int progressCurrent = 0;
private int progressMax = 100;
public CustomProgressView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray typedArray = context.obtainStyledAttributes(R.styleable.CustomProgressView);
cp_percent_textsize = (int) typedArray.getDimension(R.styleable.CustomProgressView_cp_percent_textsize, cp_percent_textsize);
cp_percent_textcolor = typedArray.getColor(R.styleable.CustomProgressView_cp_percent_textcolor, cp_percent_textcolor);
cp_background_color = typedArray.getColor(R.styleable.CustomProgressView_cp_background_color, cp_background_color);
cp_progress_color = typedArray.getColor(R.styleable.CustomProgressView_cp_progress_color, cp_progress_color);
cp_background_is_stroke = typedArray.getBoolean(R.styleable.CustomProgressView_cp_background_is_stroke, cp_background_is_stroke);
cp_rect_round = (int) typedArray.getDimension(R.styleable.CustomProgressView_cp_rect_round, cp_rect_round);
typedArray.recycle();
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
}
4、複寫最重要的方法onDraw
@Override
protected void onDraw(Canvas canvas) {
mCenterX = getWidth() / 2;
mCenterY = getHeight() / 2;
drawHorProgress(mPaint, canvas);
}
private void drawHorProgress(Paint paint, Canvas canvas) {
//畫背景
paint.setColor(cp_background_color);
if (cp_background_is_stroke) {
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(1);
} else {
paint.setStyle(Paint.Style.FILL);
}
canvas.drawRoundRect(new RectF(mCenterX - getWidth() / 2, mCenterY - getHeight() / 2,
mCenterX + getWidth() / 2, mCenterY + getHeight() / 2), cp_rect_round, cp_rect_round, paint);
//畫進度條
paint.setColor(cp_progress_color);
paint.setStyle(Paint.Style.FILL);
canvas.drawRoundRect(new RectF(mCenterX - getWidth() / 2, mCenterY - getHeight() / 2,
(int) (progressCurrent * getWidth() / progressMax), mCenterY + getHeight() / 2), cp_rect_round, cp_rect_round, paint);
//畫文字
paint.setColor(cp_percent_textcolor);
paint.setTextSize(cp_percent_textsize);
paint.setStyle(Paint.Style.FILL);
String value_str = (int) (progressCurrent * 100 / progressMax) + "%";
Rect rect = new Rect();
paint.getTextBounds(value_str, 0, value_str.length(), rect);
float textWidth = rect.width();
float textHeight = rect.height();
if (textWidth >= getWidth()) {
textWidth = getWidth();
}
Paint.FontMetrics metrics = paint.getFontMetrics();
float baseline = (getMeasuredHeight() - metrics.bottom + metrics.top) / 2 - metrics.top;
canvas.drawText(value_str, mCenterX - textWidth / 2, baseline, paint);
}
步驟:
1、想一下,其實很簡單。
進度條背景和進度條,就是兩個圓角矩形疊加在一起。最後再把文字畫在矩形的中間位置。
2、找到View的中心點,getWidth / 2 , getHeight / 2。
3、畫背景。
其實背景很簡單。固定的圓角矩形。left、top、right、bottom座標其實是固定的。根據中心點,很容易畫出來。
4、畫進度條。
進度條是根據的進度值的變化實時刷新的。所以我們要定義一個當前進度progressCurrent和最大進度progressMax。
爲什麼要定義最大進度?實際生產中,你要根據下載文件的總大小和當前已經下載的大小來計算進度,所以這個是要設置的。
仔細分析,可以知道,在你畫進度條的時候,其實只有一個座標值是變化的,那就是 right 。你可以根據當前進度的百分比來計算當前精度下的 right 佔寬度的多少比例。
5、畫文字
使文字居中的baseline是一個知識點,需要重點掌握。
6、給各屬性值設置setter和getter方法。
這裏主要說一下,進度值的設定。
public int getProgressCurrent() {
return progressCurrent;
}
public void setProgressCurrent(int progressCurrent) {
if (progressCurrent > progressMax) {
this.progressCurrent = progressMax;
} else {
this.progressCurrent = progressCurrent;
}
postInvalidate();
}
噹噹前進度超過最大進度時,當前進度設定爲最大進度。(當前進度爲100%的下一秒,就會出現超過最大進度的情況)
記得重新繪製View 調用postInvalidate();方法。
5、佈局
<net.feelingtech.example_work.custom.ownprogress.CustomProgressView
android:id="@+id/cpv_one"
android:layout_width="match_parent"
android:layout_height="15dp" />
6、跑起來
mCustomProgressView = view.findViewById(R.id.cpv_one);
mCustomProgressView.setProgressMax(100);
mCustomProgressView.setCp_background_color(Color.parseColor("#A2CD5A"));
mCustomProgressView.setCp_percent_textcolor(Color.RED);
mCustomProgressView.setCp_rect_round(16);
mCustomProgressView.setCp_background_is_stroke(false);
mCustomProgressView.setCp_percent_textsize(30);
view.findViewById(R.id.bt_start).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (progressCurrent != 0) {
progressCurrent = 0;
return;
}
mRunnable = new Runnable() {
@Override
public void run() {
progressCurrent += 1;
mCustomProgressView.setProgressCurrent(progressCurrent);
mHandler.postDelayed(mRunnable, 5);
}
};
mHandler.postDelayed(mRunnable, 1);
}
});
OVER ! ! !
掃碼關注,共同進步