博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android 高手进阶,自己定义圆形进度条
阅读量:4325 次
发布时间:2019-06-06

本文共 15299 字,大约阅读时间需要 50 分钟。

背景介绍

在Android 开发中,我们常常遇到各种各样绚丽的控件,所以,依靠我们Android本身所带的控件是远远不够的,许多时候须要我们自定义控件,在开发的过程中。我们公司遇到了一种须要自己写的一个自定义带进度的圆形进度条,看起来很的绚丽,当然另一些其它的。比方:水纹形的圆形进度条等效果都是很nice的。假设哪位朋友有实现,希望分享出来,我也好学习学习。

好了多的不说。接下来,我们就来看看来怎样实现圆形进度条。

原文地址:

一:先上效果图

                            

二:实例代码

1.自己定义属性

ps:自己定义属性呢。事实上大家也许不是非常明确,有些小伙伴们也许知道,我这样用。能够调用它的一个值。能够获取值,或者说赋予值。比方:你用Android 系统本身所带的控件,textview其它等,你知道他有height。width,textsize,textcolor等,这些属性。你能赋值。可是有去理解过如何去获取值么。假设不了解,没关系,我这有一篇鸿洋写的比較具体。推荐给你:,还在等什么。赶紧戳进去,带你装逼带你飞。

2.自己定义控件

源代码1:

package com.example.testdemo.view;import android.annotation.SuppressLint;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.RectF;import android.graphics.Typeface;import android.util.AttributeSet;import android.view.View;import com.example.testdemo.R;/** * 仿iphone带进度的进度条。线程安全的View,可直接在线程中更新进度 *  * @author zengtao 2015年5月12日下午7:43:32 * * */@SuppressLint("DrawAllocation")public class RoundProgressBar extends View {	/**	 * 画笔对象的引用	 */	private Paint paint;	/**	 * 圆环的颜色	 */	private int roundColor;	/**	 * 圆环进度的颜色	 */	private int roundProgressColor;	/**	 * 中间进度百分比的字符串的颜色	 */	private int textColor;	/**	 * 中间进度百分比的字符串的字体	 */	private float textSize;	/**	 * 圆环的宽度	 */	private float roundWidth;	/**	 * 最大进度	 */	private int max;	/**	 * 当前进度	 */	private int progress;	/**	 * 是否显示中间的进度	 */	private boolean textIsDisplayable;	/**	 * 进度的风格。实心或者空心	 */	private int style;	public static final int STROKE = 0;	public static final int FILL = 1;	public RoundProgressBar(Context context) {		this(context, null);	}	public RoundProgressBar(Context context, AttributeSet attrs) {		this(context, attrs, 0);	}	public RoundProgressBar(Context context, AttributeSet attrs, int defStyle) {		super(context, attrs, defStyle);		paint = new Paint();		TypedArray mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.RoundProgressBar);		// 获取自己定义属性和默认值		roundColor = mTypedArray.getColor(R.styleable.RoundProgressBar_roundColor, Color.rgb(228, 232, 237));		roundProgressColor = mTypedArray.getColor(R.styleable.RoundProgressBar_roundProgressColor, Color.rgb(216, 6, 7));		textColor = mTypedArray.getColor(R.styleable.RoundProgressBar_textColor, Color.rgb(216, 6, 7));		textSize = mTypedArray.getDimension(R.styleable.RoundProgressBar_textSize, 18);		roundWidth = mTypedArray.getDimension(R.styleable.RoundProgressBar_roundWidth, 3);		max = mTypedArray.getInteger(R.styleable.RoundProgressBar_max, 100);		textIsDisplayable = mTypedArray.getBoolean(R.styleable.RoundProgressBar_textIsDisplayable, true);		style = mTypedArray.getInt(R.styleable.RoundProgressBar_style, 0);		mTypedArray.recycle();	}	@Override	protected void onDraw(Canvas canvas) {		super.onDraw(canvas);		/**		 * 1.画最外层的大圆环		 */		int centre = getWidth() / 2; // 获取圆心的x坐标		int radius = (int) (centre - roundWidth / 2); // 圆环的半径		paint.setColor(roundColor); // 设置圆环的颜色		paint.setStyle(Paint.Style.STROKE); // 设置空心		paint.setStrokeWidth(roundWidth); // 设置圆环的宽度		paint.setAntiAlias(true); // 消除锯齿		canvas.drawCircle(centre, centre, radius, paint); // 画出圆环		/**		 * 2.画进度百分比		 */		paint.setStrokeWidth(0);		paint.setColor(textColor);		paint.setTextSize(textSize);		paint.setTypeface(Typeface.DEFAULT); // 设置字体		// 中间的进度百分比,先转换成float在进行除法运算,不然都为0		int percent = (int) (((float) progress / (float) max) * 100);		float textWidth = paint.measureText(percent + "%"); // 測量字体宽度,我们须要依据字体的宽度设置在圆环中间		if (textIsDisplayable && style == STROKE) {			 canvas.drawText(percent + "%", centre - textWidth / 2, centre + textSize/2, paint); //画出进度百分比  		}		/**		 * 3.画圆弧 。画圆环的进度		 */		// 设置进度是实心还是空心		paint.setStrokeWidth(roundWidth); // 设置圆环的宽度		paint.setColor(roundProgressColor); // 设置进度的颜色		RectF oval = new RectF(centre - radius, centre - radius, centre + radius, centre + radius); // 用于定义的圆弧的形状和大小的界限		switch (style) {		case STROKE: {			paint.setStyle(Paint.Style.STROKE);			canvas.drawArc(oval, -90, 360 * progress / max, false, paint); // 依据进度画圆弧			break;		}		case FILL: {			paint.setStyle(Paint.Style.FILL_AND_STROKE);			if (progress != 0)				canvas.drawArc(oval, -90, 360 * progress / max, true, paint); // 依据进度画圆弧			break;		}		}	}	public synchronized int getMax() {		return max;	}	/**	 * 设置进度的最大值	 * 	 * @param max	 */	public synchronized void setMax(int max) {		if (max < 0) {			throw new IllegalArgumentException("max not less than 0");		}		this.max = max;	}	/**	 * 获取进度.须要同步	 * 	 * @return	 */	public synchronized int getProgress() {		return progress;	}	/**	 * 设置进度。此为线程安全控件,因为考虑多线的问题,须要同步 刷新界面调用postInvalidate()能在非UI线程刷新	 * 	 * @param progress	 */	public synchronized void setProgress(int progress) {		if (progress < 0) {			throw new IllegalArgumentException("progress not less than 0");		}		if (progress > max) {			progress = max;		}		if (progress <= max) {			this.progress = progress;			postInvalidate();		}	}	public int getCricleColor() {		return roundColor;	}	public void setCricleColor(int cricleColor) {		this.roundColor = cricleColor;	}	public int getCricleProgressColor() {		return roundProgressColor;	}	public void setCricleProgressColor(int cricleProgressColor) {		this.roundProgressColor = cricleProgressColor;	}	public int getTextColor() {		return textColor;	}	public void setTextColor(int textColor) {		this.textColor = textColor;	}	public float getTextSize() {		return textSize;	}	public void setTextSize(float textSize) {		this.textSize = textSize;	}	public float getRoundWidth() {		return roundWidth;	}	public void setRoundWidth(float roundWidth) {		this.roundWidth = roundWidth;	}	public int getStyle() {		return style;	}		public void setStyle(int style) {		this.style = style;	}}
源代码2:

package com.example.testdemo.view;import android.annotation.SuppressLint;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.RectF;import android.graphics.Typeface;import android.util.AttributeSet;import android.view.View;import com.example.testdemo.R;/** * 仿iphone带进度的进度条,线程安全的View,可直接在线程中更新进度 *  * @author zengtao 2015年5月12日下午7:43:32 * * */@SuppressLint("DrawAllocation")public class RoundProgressBar2 extends View {	/**	 * 画笔对象的引用	 */	private Paint paint;	/**	 * 圆环的颜色	 */	private int roundColor;	/**	 * 圆环进度的颜色	 */	private int roundProgressColor;	/**	 * 中间进度百分比的字符串的颜色	 */	private int textColor;	/**	 * 中间进度百分比的字符串的字体	 */	private float textSize;	/**	 * 圆环的宽度	 */	private float roundWidth;	/**	 * 最大进度	 */	private int max;	/**	 * 当前进度	 */	private int progress;	/**	 * 是否显示中间的进度	 */	private boolean textIsDisplayable;	/**	 * 进度的风格。实心或者空心	 */	private int style;	public static final int STROKE = 0;	public static final int FILL = 1;	public RoundProgressBar2(Context context) {		this(context, null);	}	public RoundProgressBar2(Context context, AttributeSet attrs) {		this(context, attrs, 0);	}	public RoundProgressBar2(Context context, AttributeSet attrs, int defStyle) {		super(context, attrs, defStyle);		paint = new Paint();		TypedArray mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.RoundProgressBar);		// 获取自己定义属性和默认值		roundColor = mTypedArray.getColor(R.styleable.RoundProgressBar_roundColor, Color.rgb(228, 232, 237));		roundProgressColor = mTypedArray.getColor(R.styleable.RoundProgressBar_roundProgressColor, Color.rgb(216, 6, 7));		textColor = mTypedArray.getColor(R.styleable.RoundProgressBar_textColor, Color.rgb(216, 6, 7));		textSize = mTypedArray.getDimension(R.styleable.RoundProgressBar_textSize, 18);		roundWidth = mTypedArray.getDimension(R.styleable.RoundProgressBar_roundWidth, 3);		max = mTypedArray.getInteger(R.styleable.RoundProgressBar_max, 100);		textIsDisplayable = mTypedArray.getBoolean(R.styleable.RoundProgressBar_textIsDisplayable, true);		style = mTypedArray.getInt(R.styleable.RoundProgressBar_style, 0);		mTypedArray.recycle();	}	@Override	protected void onDraw(Canvas canvas) {		super.onDraw(canvas);		/**		 * 画最外层的大圆环		 */		int centre = getWidth() / 2; // 获取圆心的x坐标		int radius = (int) (centre - roundWidth / 2); // 圆环的半径		paint.setColor(roundColor); // 设置圆环的颜色		paint.setStyle(Paint.Style.STROKE); // 设置空心		paint.setStrokeWidth(roundWidth); // 设置圆环的宽度		paint.setAntiAlias(true); // 消除锯齿		canvas.drawCircle(centre, centre, radius, paint); // 画出圆环		/**		 * 画进度百分比		 */		paint.setStrokeWidth(0);		paint.setColor(textColor);		paint.setTextSize(textSize);		paint.setTypeface(Typeface.DEFAULT); // 设置字体		// int percent = (int) (((float) progress / (float) max) * 100); //		// 中间的进度百分比,先转换成float在进行除法运算,不然都为0		float textWidth = paint.measureText("抢"); // 測量字体宽度。我们须要依据字体的宽度设置在圆环中间		if (textIsDisplayable && style == STROKE) {			canvas.drawText("抢", centre - textWidth / 2, centre + textSize / 2 - 4, paint); // 画出进度百分比		}		/**		 * 画圆弧 ,画圆环的进度		 */		// 设置进度是实心还是空心		paint.setStrokeWidth(roundWidth); // 设置圆环的宽度		paint.setColor(roundProgressColor); // 设置进度的颜色		RectF oval = new RectF(centre - radius, centre - radius, centre + radius, centre + radius); // 用于定义的圆弧的形状和大小的界限		switch (style) {		case STROKE: {			paint.setStyle(Paint.Style.STROKE);			canvas.drawArc(oval, -90, 360 * progress / max, false, paint); // 依据进度画圆弧			break;		}		case FILL: {			paint.setStyle(Paint.Style.FILL_AND_STROKE);			if (progress != 0)				canvas.drawArc(oval, -90, 360 * progress / max, true, paint); // 依据进度画圆弧			break;		}		}	}	public synchronized int getMax() {		return max;	}	/**	 * 设置进度的最大值	 * 	 * @param max	 */	public synchronized void setMax(int max) {		if (max < 0) {			throw new IllegalArgumentException("max not less than 0");		}		this.max = max;	}	/**	 * 获取进度.须要同步	 * 	 * @return	 */	public synchronized int getProgress() {		return progress;	}	/**	 * 设置进度,此为线程安全控件,因为考虑多线的问题。须要同步 刷新界面调用postInvalidate()能在非UI线程刷新	 * 	 * @param progress	 */	public synchronized void setProgress(int progress) {		if (progress < 0) {			throw new IllegalArgumentException("progress not less than 0");		}		if (progress > max) {			progress = max;		}		if (progress <= max) {			this.progress = progress;			postInvalidate();		}	}	public int getCricleColor() {		return roundColor;	}	public void setCricleColor(int cricleColor) {		this.roundColor = cricleColor;	}	public int getCricleProgressColor() {		return roundProgressColor;	}	public void setCricleProgressColor(int cricleProgressColor) {		this.roundProgressColor = cricleProgressColor;	}	public int getTextColor() {		return textColor;	}	public void setTextColor(int textColor) {		this.textColor = textColor;	}	public float getTextSize() {		return textSize;	}	public void setTextSize(float textSize) {		this.textSize = textSize;	}	public float getRoundWidth() {		return roundWidth;	}	public void setRoundWidth(float roundWidth) {		this.roundWidth = roundWidth;	}}

ps:以上两份自己定义源代码。事实上你细致看。区别不是非常大,就改变了一个地方,这个更改的地方,事实上是在我们如今的项目中所遇到的,所以,发不这个圆形控件,我想你以后会用到的,值得收藏。

三.详细调用

package com.example.testdemo;import android.annotation.SuppressLint;import android.app.Activity;import android.graphics.Color;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import com.example.testdemo.view.RoundProgressBar;import com.example.testdemo.view.RoundProgressBar2;/** * 主界面 * @author zengtao 2015年6月10日 下午4:02:13 * */public class MainActivity extends Activity {	private RoundProgressBar2 r3;	private RoundProgressBar r1, r2, r4, r5;	private int pro1 = 80; // 想要显示的进度值:如项目中。从server返回的数据	private int progress = 0;	private boolean flag = false;	private MyThread thread1;	private MyThread2 thread2;	private Button start;	@Override	protected void onCreate(Bundle savedInstanceState) {		super.onCreate(savedInstanceState);		setContentView(R.layout.activity_main);		initView();		setRoundAttribute(); // 可设置可不设置	}	/**	 * 開始方法	 */	private void start() {		// 线程1		thread1 = new MyThread();		thread1.start();		// 线程2		thread2 = new MyThread2();		thread2.start();	}	/**	 * 初始化控件	 */	private void initView() {		r1 = (RoundProgressBar) findViewById(R.id.prpgress1);		r2 = (RoundProgressBar) findViewById(R.id.prpgress2);		r3 = (RoundProgressBar2) findViewById(R.id.prpgress3);		r4 = (RoundProgressBar) findViewById(R.id.prpgress4);		r5 = (RoundProgressBar) findViewById(R.id.prpgress5);		start = (Button) findViewById(R.id.start);		start.setOnClickListener(listener);	}	/**	 * 设置圆的属性	 */	private void setRoundAttribute() {		r1.setRoundWidth(10);		r1.setTextColor(Color.parseColor("#00ff00"));		r1.setCricleColor(Color.parseColor("#ff0000"));		r2.setRoundWidth(20);		r2.setTextColor(Color.parseColor("#0000ff"));		r2.setCricleColor(Color.parseColor("#ff00ff"));		r4.setRoundWidth(20);		r4.setTextColor(Color.parseColor("#ff00ff"));		r4.setCricleColor(Color.parseColor("#ff0000"));		r4.setStyle(0);		r4.setRoundWidth(20);		r4.setTextColor(Color.parseColor("#000000"));		r4.setCricleColor(Color.parseColor("#ffff00"));		r4.setStyle(1);	}	/**	 * 点击事件	 */	OnClickListener listener = new OnClickListener() {		@Override		public void onClick(View v) {			if (v == start) {				start();			}		}	};	/**	 * 用于更新ui	 */	@SuppressLint("HandlerLeak")	private Handler mHandler = new Handler() {		public void handleMessage(android.os.Message msg) {			final int x = msg.what;			final int temp = (int) msg.obj;			if (x == 0 * 1) {				if (pro1 - temp > 0) {					r1.setProgress(temp);					r2.setProgress(temp);					r3.setProgress(temp);					r4.setProgress(temp);					r5.setProgress(temp);				} else {					r1.setProgress(pro1);					r2.setProgress(pro1);					r3.setProgress(pro1);					r4.setProgress(pro1);					r5.setProgress(pro1);					thread1.stopThread();				}			} else if (x == 0 * 2) {				if (pro1 - temp > 0) {					r1.setProgress(temp);					r2.setProgress(temp);					r3.setProgress(temp);					r4.setProgress(temp);					r5.setProgress(temp);				} else {					r1.setProgress(pro1);					r2.setProgress(pro1);					r3.setProgress(pro1);					r4.setProgress(pro1);					r5.setProgress(pro1);					thread2.stopThread();				}			}		};	};	/**	 * 线程,控制进度动画	 * @author zengtao 2015年6月10日 下午4:31:11	 *	 */	class MyThread extends Thread {		@Override		public void run() {			while (!flag) {				try {					progress += 1;					Message msg = new Message();					msg.what = 0 * 1;					msg.obj = progress;					Thread.sleep(100);					mHandler.sendMessage(msg);				} catch (InterruptedException e) {					e.printStackTrace();				}			}		}		public void stopThread() {			flag = true;		}	}	/**	 * 线程。控制进度动画	 * @author zengtao 2015年6月10日 下午4:31:11	 *	 */	class MyThread2 extends Thread {		@Override		public void run() {			while (!flag) {				try {					progress += 2;					Message msg = new Message();					msg.what = 0 * 2;					msg.obj = progress;					Thread.sleep(200);					mHandler.sendMessage(msg);				} catch (InterruptedException e) {					e.printStackTrace();				}			}		}		public void stopThread() {			flag = true;		}	}	@Override	protected void onDestroy() {		super.onDestroy();		if (thread1 != null) {			thread1.stopThread();		}		if (thread2 != null) {			thread2.stopThread();		}	}}

四.总结

实现以上步骤,就实现了一个安全可靠的自己定义控件的实现。看起来简简单单,不说分分钟,可是略微花点时间这就是你的。

   源代码下载地址:

转载于:https://www.cnblogs.com/bhlsheji/p/5179474.html

你可能感兴趣的文章
微信支付之异步通知签名错误
查看>>
2016 - 1 -17 GCD学习总结
查看>>
linux安装php-redis扩展(转)
查看>>
Vue集成微信开发趟坑:公众号以及JSSDK相关
查看>>
vue项目开发之v-for列表渲染的坑
查看>>
C# 输出流转化成输入流操作XML
查看>>
CSS外边距合并(塌陷/margin越界)
查看>>
Swift给每个开发者赢取500万的机会!不看一生后悔。
查看>>
UIView详解
查看>>
MSSQL如何将查询结果拼接成字符串
查看>>
20169217 《Linux内核原理与分析》 第十周作业
查看>>
20169217 2016-2017-2 《网络攻防实践》第四周学习总结
查看>>
MemCache在Windows下环境的搭建及启动
查看>>
<nginx.conf> nginx设置用户权限
查看>>
python实现redis三种cas事务操作
查看>>
同步异步与阻塞非阻塞
查看>>
C++ 安全单例模式总结
查看>>
bzoj4754: [Jsoi2016]独特的树叶
查看>>
toj 4069 简易统计
查看>>
【Unity】Update()和FixedUpdate()
查看>>