按康师傅指示 完成下载进度条自定义view 效果如下
其实主要是draw内部进行绘制 断点也给了点思路
代码很少 主要是绘制叠层和裁剪画布 可能写法不是最优解 如果有错误请指出哈 我去验证修改 (本文代码有java/kotlin) 区分状态只做到了 准备下载 、开始下载、暂停下载、完成下载 自定义view当然少不了一些简单步骤 完整代码在文章最后 自提
关键代码
// 以下代码是java
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 设置背景 圆角矩形绘制
mPaint.setColor(bgColor);
canvas.drawRoundRect(new RectF(0, 0, width, height) ,100, 100, mPaint);
// 根据状态制定绘制
if (status == STATUS_DOWNLOAD){
mText = mProgress + "%";
float progressRight = mProgress / 100f * width;
canvas.save();
// 进度条颜色 并绘制
mPaint.setColor(proColor);
// 进度条 裁剪画布
canvas.clipRect(0, 0, progressRight, height);
// 进度条背景
canvas.drawRoundRect(new RectF(0, 0, width, height) ,100, 100, mPaint);
canvas.restore();
}else if(status == STATUS_COMPLETE){
mText ="下载完成";
}else if(status == STATUS_PREPARE){
mText = "点击下载";
}else if (status == STATUS_PAUSE){
mText = "暂停下载";
}
Paint.FontMetrics fm = mTextPaint.getFontMetrics();
float y = height / 2 + (fm.descent - fm.ascent) / 2 - fm.descent;
canvas.drawText(mText,width/2,y , mTextPaint);
}
复制代码
//kotlin
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
// 设置背景 圆角矩形绘制
mPaint?.color = bgColor
canvas.drawRoundRect(RectF(0f, 0f, width.toFloat(), height.toFloat()), 100f, 100f, mPaint!!)
// 根据状态制定绘制
when (status){
STATUS_downLoad -> {
text = "$mProgress%"
val progressRight = mProgress / 100f * width
canvas.save()
// 进度条颜色 并绘制
mPaint!!.color = progressColor
// 进度条 裁剪画布
canvas.clipRect(0f, 0f, progressRight, height.toFloat())
// 进度条背景
canvas.drawRoundRect(RectF(0f, 0f, width.toFloat(), height.toFloat()), 100f, 100f, mPaint!!)
canvas.restore() // 释放资源
}
STATUS_complete -> text = "下载完成"
STATUS_Prepare -> text = "点击下载"
STATUS_PAUSE -> text = "暂停下载"
else -> { }
}
val fm = mTextPaint?.fontMetrics
val y = height / 2 + (fm.descent - fm.ascent) / 2 - fm.descent
canvas.drawText(text!!, (width / 2).toFloat(), y, mTextPaint)
}
复制代码
解析: 分为3层绘制 1.绘制背景 2.裁剪画布 绘制进度条 3.根据状态进行文本绘制
(我在绘制图层吃了亏 文本(步骤3)一直会根据进度条(步骤2)才会显示 后面按照一层层关系去调整就解决该问题了) 这只是关于绘制的部分 重要的是还是设置进度和刷新的对外方法
//java
/**
* 设置进度
*/
public void setProgress(int progress) {
status = STATUS_DOWNLOAD;
mProgress = progress;
if (mProgress == 100) {
status = STATUS_COMPLETE;
}
invalidate();
}
复制代码
//Kotlin
/**
* 设置进度
*/
fun setProgress(progress: Int) {
status = STATUS_downLoad
mProgress = progress
if (mProgress == 100) {
status = STATUS_complete
}
invalidate() // 刷新
}
复制代码
点击调用设置倒计时有很多方法 这里只提供了最简单的调用测试
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case 0:
if (downView.isLoading()){
downView.setProgress(mProgress++);
}
if (mProgress <= 100)
mHandler.sendEmptyMessageDelayed(0, 100);
break;
}
}
};
// onCreate
downView.setOnClickListener(v-> {
if (downView.isLoading())
downView.pause();
else
downView.start();
});
mHandler.sendEmptyMessageDelayed(0, 100);
复制代码
代码如上 点击时 进行状态判断 正在下载 可进行暂停操作 再次点击可继续回复进度条
好了作业已交 完整代码如下
public class DownloadView extends View {
public static final int STATUS_PREPARE = 1; // 准备下载
public static final int STATUS_DOWNLOAD = 2; // 正在下载
public static final int STATUS_PAUSE = 3; // 暂停下载
public static final int STATUS_COMPLETE = 4; // 完成下载
private int status = STATUS_PREPARE;
private int bgColor ; // 背景色
private int proColor ; // 进度条se
private int textColor ; // 文本颜色
private int pauseColor ; // 暂停
private Canvas mCanvas;
private String mText;
/**
* 是否在下载
* @return
*/
public boolean isLoading() {
if (status == STATUS_DOWNLOAD){
return true;
}
return false;
}
public DownloadView(@NonNull Context context) {
this(context,null);
}
public DownloadView(@NonNull Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}
Paint mPaint =null;
Paint mTextPaint =null;
public DownloadView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init (attrs);
initPaint();
}
private void initPaint() {
mPaint = new Paint();
mPaint.setColor(Color.BLUE);
mPaint.setAntiAlias(true); // 消除锯齿
mPaint.setStyle(Paint.Style.FILL);
mTextPaint = new Paint();
mTextPaint.setColor(textColor);
mTextPaint.setAntiAlias(true); // 消除锯齿
mTextPaint.setStyle(Paint.Style.FILL);
mTextPaint.setTextAlign(Paint.Align.CENTER);
mTextPaint.setTextSize(18);
}
/**
* 初始化
* @param attrs
*/
private void init(AttributeSet attrs) {
TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.DownloadView);
bgColor = typedArray.getColor(R.styleable.DownloadView_bgColor,0xFF00CC99);
proColor = typedArray.getColor(R.styleable.DownloadView_progressColor,0x4400CC99);
textColor = typedArray.getColor(R.styleable.DownloadView_textColor,0x4400CC99);
pauseColor = typedArray.getColor(R.styleable.DownloadView_pauseColor,0xFFFFFFFF);
typedArray.recycle();
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
}
int width = 0;
int height = 50;
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
width = MeasureSpec.getSize(widthMeasureSpec);
height = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
}
public String getText() {
return mText;
}
public void setText(String text) {
mText = text;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 设置背景 圆角矩形绘制
mPaint.setColor(bgColor);
canvas.drawRoundRect(new RectF(0, 0, width, height) ,100, 100, mPaint);
// 根据状态制定绘制
if (status == STATUS_DOWNLOAD){
mText = mProgress + "%";
float progressRight = mProgress / 100f * width;
canvas.save();
// 进度条颜色 并绘制
mPaint.setColor(proColor);
// 进度条 裁剪画布
canvas.clipRect(0, 0, progressRight, height);
// 进度条背景
canvas.drawRoundRect(new RectF(0, 0, width, height) ,100, 100, mPaint);
canvas.restore();
}else if(status == STATUS_COMPLETE){
mText ="下载完成";
}else if(status == STATUS_PREPARE){
mText = "点击下载";
}else if (status == STATUS_PAUSE){
mText = "暂停下载";
}
Paint.FontMetrics fm = mTextPaint.getFontMetrics();
float y = height / 2 + (fm.descent - fm.ascent) / 2 - fm.descent;
canvas.drawText(mText,width/2,y , mTextPaint);
}
public void start(){
if (status == STATUS_PREPARE ||
status == STATUS_PAUSE) {
status = STATUS_DOWNLOAD;
}
}
public void pause (){
if (status == STATUS_DOWNLOAD) {
status = STATUS_PAUSE;
}
invalidate();
}
int mProgress = 0;
/**
* 设置进度
*/
public void setProgress(int progress) {
status = STATUS_DOWNLOAD;
mProgress = progress;
if (mProgress == 100) {
status = STATUS_COMPLETE;
}
invalidate();
}
复制代码
// kotlin
class DownloadView @JvmOverloads constructor(context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0)
: View(context, attrs, defStyleAttr) {
private var status = STATUS_Prepare
private var bgColor // 背景色
= 0
private var progressColor // 进度条se
= 0
private var pauseColor // 暂停
= 0
var text: String? = "点击下载"
private var mTextColor = 0
var width = 120f
var height = 50f
var mProgress = 0
/**
* 是否在下载
* @return
*/
fun isLoading(): Boolean {
return if (status == STATUS_downLoad) {
true
} else false
}
private lateinit var mPaint: Paint
private lateinit var mTextPaint: Paint
/**
* 画笔
*/
private fun initPaint() {
// 画笔初始化
mPaint = Paint()
mPaint?.apply {
color = mProgress
isAntiAlias = true // 消除锯齿
style = Paint.Style.FILL
}
mTextPaint = Paint()
mTextPaint?.apply {
color = mTextColor
isAntiAlias = true // 消除锯齿
style = Paint.Style.FILL
textAlign = Paint.Align.CENTER
textSize = 18f
}
}
/**
* 初始化
* @param attrs
*/
private fun init(attrs: AttributeSet?) {
context.obtainStyledAttributes(attrs, R.styleable.DownloadView)?.apply {
bgColor =getColor(R.styleable.DownloadView_bgColor, -0xff3367)
progressColor = getColor(R.styleable.DownloadView_progressColor, 0x4400CC99)
pauseColor = getColor(R.styleable.DownloadView_pauseColor, -0xff3367)
mTextColor = getColor(R.styleable.DownloadView_text, -0x1)
recycle()
}
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
width = MeasureSpec.getSize(widthMeasureSpec).toFloat()
height = MeasureSpec.getSize(heightMeasureSpec).toFloat()
setMeasuredDimension(MeasureSpec.makeMeasureSpec(width.toInt(), MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(height.toInt(), MeasureSpec.EXACTLY))
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
// 设置背景 圆角矩形绘制
mPaint?.color = bgColor
canvas.drawRoundRect(RectF(0f, 0f, width.toFloat(), height.toFloat()), 100f, 100f, mPaint!!)
// 根据状态制定绘制
when (status){
STATUS_downLoad -> {
text = "$mProgress%"
val progressRight = mProgress / 100f * width
canvas.save()
// 进度条颜色 并绘制
mPaint!!.color = progressColor
// 进度条 裁剪画布
canvas.clipRect(0f, 0f, progressRight, height.toFloat())
// 进度条背景
canvas.drawRoundRect(RectF(0f, 0f, width.toFloat(), height.toFloat()), 100f, 100f, mPaint!!)
canvas.restore() // 释放资源
}
STATUS_complete -> text = "下载完成"
STATUS_Prepare -> text = "点击下载"
STATUS_PAUSE -> text = "暂停下载"
else -> { }
}
val fm = mTextPaint?.fontMetrics
val y = height / 2 + (fm.descent - fm.ascent) / 2 - fm.descent
canvas.drawText(text!!, (width / 2).toFloat(), y, mTextPaint)
}
fun start() {
if (status == STATUS_Prepare ||
status == STATUS_PAUSE) {
status = STATUS_downLoad
}
}
fun pause() {
if (status == STATUS_downLoad) {
status = STATUS_PAUSE
}
invalidate()
}
/**
* 设置进度
*/
fun setProgress(progress: Int) {
status = STATUS_downLoad
mProgress = progress
if (mProgress == 100) {
status = STATUS_complete
}
invalidate() // 刷新
}
companion object {
const val STATUS_Prepare = 1 // 准备下载
const val STATUS_downLoad = 2 // 正在下载
const val STATUS_PAUSE = 3 // 暂停下载
const val STATUS_complete = 4 // 完成下载
}
init {
init(attrs)
initPaint()
}
复制代码
// xml 属性部分
扫描二维码关注公众号,回复:
14473442 查看本文章

<declare-styleable name="DownloadView">
<attr name="progressColor" format="color"></attr>
<attr name="bgColor" format="color"></attr>
<attr name="textColor" format="color"></attr>
<attr name="text" format="string"></attr>
<attr name="pauseColor" format="color"></attr>
</declare-styleable>
复制代码
如有问题 沙滩联系 gogogo