Android 进度条按钮实现(ProgressButton)

有些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" />

 

 

posted @ 2018-10-26 19:29  浮云Cloud  阅读(7578)  评论(0编辑  收藏  举报