您的位置:首页 > 移动开发 > Android开发

Android 自定义View——带下载进度Button

2016-08-08 15:16 351 查看

之前看到某些应用商店的下载按钮带下载进度提示,感觉很实用,自己也试着简单地实现这个功能。下面是效果图







在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>


————————————————————————

源码地址

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息