之前看到某些應用商店的下載按鈕帶下載進度提示,感覺很實用,自己也試着簡單地實現這個功能。下面是效果圖
在attrs.xml添加下載進度按鈕所需的自定義屬性
<declare-styleable name="DownLoadButton">
<attr name="normalBackground" format="reference|color"/>
<attr name="downLoadedBackground" format="reference|color"/>
<attr name="downLoadCompleteBackground" format="reference|color"/>
<attr name="textColor" format="reference|color"/>
</declare-styleable>
自定義下載進度按鈕的代碼
/**
* Created by 犀利的小牛 on 2016/8/8.
*/
public class DownLoadButton extends Button {
private Paint paint;
/**
* 文本顏色
*/
private int textColor;
/**
* 未下載狀態背景
*/
private Drawable normalBackground;
/**
* 已下載進度背景
*/
private Drawable downLoadBackground;
/**
* 下載完成背景
*/
private Drawable completeBackground;
/**
* 未下載狀態
*/
public final static int STATE_NORMAL = 0;
/**
* 下載中
*/
public final static int STATE_DOWNLOADING = 1;
/**
* 下載完成
*/
public final static int STATE_COMPLETE = 2;
/**
* 當前狀態
*/
private int curState = 0;
/**
* 當前下載進度
* 百分比
*/
private int curPrecent = 0;
private OnDownLoadButtonClickListener onDownLoadButtonClickListener;
public DownLoadButton(Context context) {
this(context, null);
}
public DownLoadButton(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public DownLoadButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DownLoadButton, defStyleAttr, 0);
normalBackground = getResources().getDrawable(R.drawable.rect_normal_bg);
downLoadBackground = getResources().getDrawable(R.drawable.rect_downloaded_bg);
completeBackground = getResources().getDrawable(R.drawable.rect_complete_bg);
final int N = a.getIndexCount();
for (int i = 0; i < N; i++) {
int attr = a.getIndex(i);
switch (attr) {
case R.styleable.DownLoadButton_normalBackground:
normalBackground = a.getDrawable(attr);
break;
case R.styleable.DownLoadButton_downLoadedBackground:
downLoadBackground = a.getDrawable(attr);
break;
case R.styleable.DownLoadButton_downLoadCompleteBackground:
completeBackground = a.getDrawable(attr);
break;
case R.styleable.DownLoadButton_textColor:
textColor = a.getColor(attr, getResources().getColor(R.color.color_white));
break;
}
}
/**
* 設置button本身的文字爲透明以免干擾我們自己繪製上去的文字
*/
setTextColor(getResources().getColor(R.color.color_transparent));
paint = new Paint();
paint.setAntiAlias(true);
paint.setTextSize(getTextSize());
paint.setColor(textColor);
curState = STATE_NORMAL;
setGravity(Gravity.CENTER);
/**
* 設置點擊事件
* 這個方法行得通,但是我感覺有更好的實現方式。
*/
setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (onDownLoadButtonClickListener != null) {
//點擊時返回當前的狀態
onDownLoadButtonClickListener.onClick(v, curState);
}
}
});
}
/**
* 設置當前狀態
*
* @param state
*/
public void setState(int state) {
this.curState = state;
postInvalidate();
}
/**
* 設置下載進度
*
* @param precent
* 完成進度百分比
*/
public void setDownLoadProgress(int precent) {
this.curPrecent = precent;
postInvalidate();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int width = 0;
int height = 0;
/**
* 計算文本顯示所需寬高
*/
Rect textBound = new Rect();
String tip = getResources().getString(R.string.download_complete);
paint.getTextBounds("下載完成", 0, tip.length(), textBound);
if(widthMode == MeasureSpec.EXACTLY){
width = widthSize+getPaddingLeft()+getPaddingRight();
}else{
width = textBound.width()+getPaddingLeft()+getPaddingRight();
}
if(heightMode == MeasureSpec.EXACTLY){
height = heightSize+getPaddingTop()+getPaddingBottom();
}else{
height = textBound.height()+getPaddingTop()+getPaddingBottom();
}
setMeasuredDimension(width,height);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
String tip = "";
switch (curState) {
case STATE_NORMAL:
tip = getResources().getString(R.string.download);
curPrecent = 0;
setBackgroundDrawable(normalBackground);
break;
case STATE_DOWNLOADING:
tip = curPrecent+"%";
//計算當前進度所需寬度
int downLoadedWidth = (int) (getMeasuredWidth() * ((double) curPrecent / 100));
Rect rect = new Rect(0, 0, downLoadedWidth, getMeasuredHeight());
downLoadBackground.setBounds(rect);
downLoadBackground.draw(canvas);
break;
case STATE_COMPLETE:
tip = getResources().getString(R.string.download_complete);
setBackgroundDrawable(completeBackground);
break;
}
/**
* 繪製提示文本
*/
Rect textBound = new Rect();
paint.getTextBounds(tip, 0, tip.length(), textBound);
canvas.drawText(tip,(getMeasuredWidth()-textBound.width())/2,(getMeasuredHeight()+textBound.height())/2, paint);
}
public void setOnDownLoadButtonClickListener(OnDownLoadButtonClickListener onDownLoadButtonClickListener) {
this.onDownLoadButtonClickListener = onDownLoadButtonClickListener;
}
public interface OnDownLoadButtonClickListener {
void onClick(View v, int curState);
}
}
MainActicity中的代碼很簡單,模擬下載過程
/**
* Created by 犀利的小牛 on 2016/8/8.
*/
public class MainActivity extends AppCompatActivity implements DownLoadButton.OnDownLoadButtonClickListener {
private DownLoadButton downLoadButton;
private DownLoadHandler downLoadHandler;
private final static int MESSAGE_DOWNLOADING = 0;
private int downLoadedPrecent = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
downLoadHandler = new DownLoadHandler();
downLoadButton = (DownLoadButton) findViewById(R.id.downLoadButton);
downLoadButton.setOnDownLoadButtonClickListener(this);
}
@Override
public void onClick(View v, int curState) {
if (curState == DownLoadButton.STATE_NORMAL) {
//開始下載
downLoadButton.setState(DownLoadButton.STATE_DOWNLOADING);
downLoadHandler.sendEmptyMessageDelayed(MESSAGE_DOWNLOADING,2000);
}else if(curState == DownLoadButton.STATE_DOWNLOADING){
//下載中如果被點擊時停止下載,這裏可以根據自個的需求換成暫停或者其他
downLoadButton.setState(DownLoadButton.STATE_NORMAL);
downLoadedPrecent = 0;
downLoadHandler.removeMessages(MESSAGE_DOWNLOADING);
}
}
private class DownLoadHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case MESSAGE_DOWNLOADING:
//模擬下載
downLoadedPrecent+=10;
if(downLoadedPrecent>=100){
downLoadButton.setState(DownLoadButton.STATE_COMPLETE);
}else{
downLoadButton.setDownLoadProgress(downLoadedPrecent);
sendEmptyMessageDelayed(MESSAGE_DOWNLOADING,2000);
}
break;
}
}
}
}
最後是佈局的代碼
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:orientation="horizontal">
<com.xiaoniu.downloadbuttom.DownLoadButton
android:id="@+id/downLoadButton"
android:layout_width="120dp"
android:layout_height="80px"
android:textColor="@android:color/white"
app:normalBackground="@drawable/rect_normal_bg"
app:downLoadedBackground="@drawable/rect_downloaded_bg"
app:downLoadCompleteBackground="@drawable/rect_downloaded_bg"
android:textSize="20sp"
app:textColor="@color/color_white"
/>
</LinearLayout>