有些App在點擊下載按鈕的時候,可以在按鈕上顯示進度,我們可以通過繼承原生Button,重寫onDraw來實現帶進度條的按鈕。 Github:https://github.com/imcloudfloating/ProgressBar 1.效果: 2.原理: 創建三個GradientDrawable ...
有些App在點擊下載按鈕的時候,可以在按鈕上顯示進度,我們可以通過繼承原生Button,重寫onDraw來實現帶進度條的按鈕。
Github:https://github.com/imcloudfloating/ProgressBar
1.效果:
2.原理:
創建三個GradientDrawable作為按鈕背景、進度條背景和進度條前景,通過計算進度條的百分比來設置寬度,然後調用invalidate()重繪。GradientDrawable設置顏色、圓角等參數,當然你也可以直接載入xml作為背景。
3.自定義參數:
在values目錄建一個attrs.xml文件
1 <?xml version="1.0" encoding="utf-8"?> 2 <resources> 3 4 <attr name="progressColor" format="color" /> 5 <attr name="progressBackColor" format="color" /> 6 <attr name="progress" format="integer" /> 7 <attr name="minProgress" format="integer" /> 8 <attr name="maxProgress" format="integer" /> 9 10 <declare-styleable name="ProgressButton"> 11 <attr name="progressColor" /> 12 <attr name="progressBackColor" /> 13 <attr name="buttonColor" format="color" /> 14 <attr name="cornerRadius" format="dimension" /> 15 <attr name="progress" /> 16 <attr name="minProgress" /> 17 <attr name="maxProgress" /> 18 <attr name="progressMargin" format="dimension" /> 19 </declare-styleable> 20 21 </resources>
3.按鈕類:
在setProgress方法中改變mProgress的值,然後調用invalidate()重繪,因為我這裡定義了一個minProgress(預設為0),所以在計算進度條寬度的時候,當前進度和最大進度都要先減去minProgress再做除法。
if (progressWidth < mCornerRadius * 2) {
progressWidth = mCornerRadius * 2;
}
當進度條寬度小於2倍圓角半徑的時候,進度條的圓角就和背景的圓角不一致,所以加上了上面這段代碼。
獲取寬度和高度其實用getWidth()和getHeight()也可以,只不過在設計器中沒法看到效果,所以我用了getMeasuredWidth()和getMeasuredHeight()。
1 package com.cloud.customviews; 2 3 import android.content.Context; 4 import android.content.res.TypedArray; 5 import android.graphics.Canvas; 6 import android.graphics.drawable.GradientDrawable; 7 import android.support.v7.widget.AppCompatButton; 8 import android.util.AttributeSet; 9 10 public class ProgressButton extends AppCompatButton { 11 12 private float mCornerRadius = 0; 13 private float mProgressMargin = 0; 14 15 private boolean mFinish; 16 17 private int mProgress; 18 private int mMaxProgress = 100; 19 private int mMinProgress = 0; 20 21 private GradientDrawable mDrawableButton; 22 private GradientDrawable mDrawableProgressBackground; 23 private GradientDrawable mDrawableProgress; 24 25 public ProgressButton(Context context, AttributeSet attrs) { 26 super(context, attrs); 27 initialize(context, attrs); 28 } 29 30 public ProgressButton(Context context, AttributeSet attrs, int defStyle) { 31 super(context, attrs, defStyle); 32 initialize(context, attrs); 33 } 34 35 private void initialize(Context context, AttributeSet attrs) { 36 //Progress background drawable 37 mDrawableProgressBackground = new GradientDrawable(); 38 //Progress drawable 39 mDrawableProgress = new GradientDrawable(); 40 //Normal drawable 41 mDrawableButton = new GradientDrawable(); 42 43 //Get default normal color 44 int defaultButtonColor = getResources().getColor(R.color.colorGray, null); 45 //Get default progress color 46 int defaultProgressColor = getResources().getColor(R.color.colorGreen, null); 47 //Get default progress background color 48 int defaultBackColor = getResources().getColor(R.color.colorGray, null); 49 50 TypedArray attr = context.obtainStyledAttributes(attrs, R.styleable.ProgressButton); 51 52 try { 53 mProgressMargin = attr.getDimension(R.styleable.ProgressButton_progressMargin, mProgressMargin); 54 mCornerRadius = attr.getDimension(R.styleable.ProgressButton_cornerRadius, mCornerRadius); 55 //Get custom normal color 56 int buttonColor = attr.getColor(R.styleable.ProgressButton_buttonColor, defaultButtonColor); 57 //Set normal color 58 mDrawableButton.setColor(buttonColor); 59 //Get custom progress background color 60 int progressBackColor = attr.getColor(R.styleable.ProgressButton_progressBackColor, defaultBackColor); 61 //Set progress background drawable color 62 mDrawableProgressBackground.setColor(progressBackColor); 63 //Get custom progress color 64 int progressColor = attr.getColor(R.styleable.ProgressButton_progressColor, defaultProgressColor); 65 //Set progress drawable color 66 mDrawableProgress.setColor(progressColor); 67 68 //Get default progress 69 mProgress = attr.getInteger(R.styleable.ProgressButton_progress, mProgress); 70 //Get minimum progress 71 mMinProgress = attr.getInteger(R.styleable.ProgressButton_minProgress, mMinProgress); 72 //Get maximize progress 73 mMaxProgress = attr.getInteger(R.styleable.ProgressButton_maxProgress, mMaxProgress); 74 75 } finally { 76 attr.recycle(); 77 } 78 79 //Set corner radius 80 mDrawableButton.setCornerRadius(mCornerRadius); 81 mDrawableProgressBackground.setCornerRadius(mCornerRadius); 82 mDrawableProgress.setCornerRadius(mCornerRadius - mProgressMargin); 83 setBackgroundDrawable(mDrawableButton); 84 85 mFinish = false; 86 } 87 88 @Override 89 protected void onDraw(Canvas canvas) { 90 if (mProgress > mMinProgress && mProgress <= mMaxProgress && !mFinish) { 91 //Calculate the width of progress 92 float progressWidth = 93 (float) getMeasuredWidth() * ((float) (mProgress - mMinProgress) / mMaxProgress - mMinProgress); 94 95 //If progress width less than 2x corner radius, the radius of progress will be wrong 96 if (progressWidth < mCornerRadius * 2) { 97 progressWidth = mCornerRadius * 2; 98 } 99 100 //Set rect of progress 101 mDrawableProgress.setBounds((int) mProgressMargin, (int) mProgressMargin, 102 (int) (progressWidth - mProgressMargin), getMeasuredHeight() - (int) mProgressMargin); 103 104 //Draw progress 105 mDrawableProgress.draw(canvas); 106 107 if (mProgress == mMaxProgress) { 108 setBackgroundDrawable(mDrawableButton); 109 mFinish = true; 110 } 111 } 112 super.onDraw(canvas); 113 } 114 115 /** 116 * Set current progress 117 */ 118 public void setProgress(int progress) { 119 if (!mFinish) { 120 mProgress = progress; 121 setBackgroundDrawable(mDrawableProgressBackground); 122 invalidate(); 123 } 124 } 125 126 public void setMaxProgress(int maxProgress) { 127 mMaxProgress = maxProgress; 128 } 129 130 public void setMinProgress(int minProgress) { 131 mMinProgress = minProgress; 132 } 133 134 public void reset() { 135 mFinish = false; 136 mProgress = mMinProgress; 137 } 138 }
使用:
1 <com.cloud.customviews.ProgressButton 2 android:id="@+id/button_progress_green" 3 android:layout_width="270dp" 4 android:layout_height="wrap_content" 5 android:layout_marginTop="4dp" 6 android:textAllCaps="false" 7 android:textColor="@color/colorWhite" 8 android:text="@string/button_progress" 9 app:cornerRadius="8dp" 10 app:progressMargin="2dp" 11 app:progressColor="@color/colorGreen" 12 app:buttonColor="@color/colorGreen" />