环形的ProgressBar
来源:互联网 发布:暴雪什么游戏支持mac 编辑:程序博客网 时间:2024/05/17 01:32
学习安卓笔记之自定义控件(二)
——环形的进度条
上文讲了一个带指示器的进度条,实现的方式很简单,小伙伴们可以参考《学习安卓笔记之自定义控件(一)之带三角指示器的ProgressBar》。本章将会作一个如下图效果的圆形进度条(这个图没截好,左边差了一点)。
【准备动手之前】
那吗如何做呢?我们先来分析一下,从图中可以看出该控件是由两部分组成的,一部分是圆环的部分,另一部分就是文本区域。该如何去绘制这些图形呢?我们来看下下图:
图中红色正方形区域控件,也相当于一块画布。之后所有要绘制的图形都会在这个正方形的区域中去绘制。红色圆形部分表示控件中的进度条。而绿色区域则表示文本的区域。接下来将准备将会用到的自定义属性。
【创建自定义属性】
为了这个控件能使用的更加灵活,这里设置了一些将会用到的属性(模仿了一下之前用到的一些类似的控件):
<?xml version="1.0" encoding="utf-8"?><resources> <declare-styleable name="CircleProgressBar"> <!-- 文字的颜色 --> <attr name="circle_ring_text_color" format="color"/> <!-- 数值的颜色 --> <attr name="circle_ring_values_color" format="color"/> <!-- 显示的文本 --> <attr name="circle_ring_text" format="string"/> <!-- 单位 --> <attr name="circle_ring_unit" format="string"/> <!-- 圆环的宽度 --> <attr name="circle_ring_width" format="dimension"/> <!-- 默认圆环的颜色 --> <attr name="circle_ring_background_color" format="color"/> <!-- 显示进度的圆环的颜色 --> <attr name="circle_ring_foreground_color" format="color"/> </declare-styleable></resources>
【开始动手】
同样这次代码量也不是很多,所以还是把整个类都贴出来了(包都不用导了直接复制就OK了):
package lyan.circleprogressbar.view;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.RectF;import android.graphics.Typeface;import android.util.AttributeSet;import android.util.TypedValue;import android.widget.ProgressBar;import lyan.circleprogressbar.R;/** * Author LYJ * Created on 2016/9/12. * Time 13:33 */public class MyCircleProgressBar extends ProgressBar { /** * 默认属性 */ private static final int CIRCLE_RING_TEXT_COLOR = 0xff000000;//文本默认颜色为黑色 private static final String CIRCLE_RING_TEXT = "当前里程";//默认文本 private static final String CIRCLE_RING_UNIT = "米";//默认单位 private static final int CIRCLE_RING_WIDTH = 30;//圆环的默认宽度 private static final int CIRCLE_RING_BACKGROUND_COLOR = 0xfff2f2f2;//默认背景圆环颜色为灰色 private static final int CIRCLE_RING_FOREGROUND_COLOR = 0xff00ffff;//默认前景圆环颜色为青色 private static final int CIRCLE_RING_VALUES_COLOR = 0xffff0000;//值的颜色默认为红色 /** * 声明变量 */ private int circle_ring_Side;//包含圆环容器的边长 private int circle_ring_radius;//圆环的半径 private int draw_offset;//因为画笔的宽度产生的误差 private int text_color;//文本的颜色 private int values_color;//值得颜色 private String text;//内容 private String unit;//单位 private int ring_width;//圆环的宽度 private int ring_back_color;//默认的颜色 private int ring_fore_color;//展示进度的颜色 private Paint textPaint, backPaint, forePaint, testPaint;//画笔 private RectF drawArcRect;//绘制弧形的区域 /** * @param context */ public MyCircleProgressBar(Context context) { this(context, null); } public MyCircleProgressBar(Context context, AttributeSet attrs) { this(context, attrs, 0); } public MyCircleProgressBar(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); obtainAttributes(attrs);//获取并设置自定义属性 init();//初始化 initPaints();//初始化画笔 } /** * 获取自定义属性 * * @param attrs */ private void obtainAttributes(AttributeSet attrs) { TypedArray typedArray = getContext().obtainStyledAttributes( attrs, R.styleable.CircleProgressBar); text = typedArray.getString(R.styleable.CircleProgressBar_circle_ring_text); text = text == null ? CIRCLE_RING_TEXT : text; unit = typedArray.getString(R.styleable.CircleProgressBar_circle_ring_unit); unit = unit == null ? CIRCLE_RING_UNIT : unit; values_color = typedArray.getColor( R.styleable.CircleProgressBar_circle_ring_values_color,CIRCLE_RING_VALUES_COLOR); text_color = typedArray.getColor( R.styleable.CircleProgressBar_circle_ring_text_color, CIRCLE_RING_TEXT_COLOR); ring_width = dip2px((int) typedArray.getDimension( R.styleable.CircleProgressBar_circle_ring_width, CIRCLE_RING_WIDTH)); ring_back_color = typedArray.getColor( R.styleable.CircleProgressBar_circle_ring_background_color, CIRCLE_RING_BACKGROUND_COLOR); ring_fore_color = typedArray.getColor( R.styleable.CircleProgressBar_circle_ring_foreground_color, CIRCLE_RING_FOREGROUND_COLOR); typedArray.recycle(); } /** * 初始化 */ private void init() { draw_offset = ring_width / 2 + dip2px(2);//偏移量 drawArcRect = new RectF();//绘制弧形的区域 } /** * 初始化画笔 */ private void initPaints() {// //测试画笔// testPaint = new Paint();// testPaint.setStrokeWidth(2);// testPaint.setColor(Color.BLACK);// testPaint.setStyle(Paint.Style.STROKE);// testPaint.setAntiAlias(true); //绘制默认圆环的画笔 backPaint = new Paint();//用于绘制默认的圆环 backPaint.setColor(ring_back_color);//画笔颜色 backPaint.setAntiAlias(true);//抗锯齿 backPaint.setDither(true);//防抖动 backPaint.setStrokeWidth(ring_width);//设置笔刷宽度 backPaint.setStyle(Paint.Style.STROKE);//不填充 //绘制进度的画笔 forePaint = new Paint();//用于绘制进度的画笔 forePaint.setColor(ring_fore_color); forePaint.setStrokeWidth(ring_width); forePaint.setAntiAlias(true); forePaint.setDither(true); forePaint.setStyle(Paint.Style.STROKE); forePaint.setStrokeCap(Paint.Cap.ROUND);//笔刷边界为圆形 //绘制文本的画笔 textPaint = new Paint();//绘制文字 textPaint.setAntiAlias(true); textPaint.setDither(true); textPaint.setStyle(Paint.Style.FILL);//填充 textPaint.setTypeface(Typeface.DEFAULT_BOLD);//文字粗体 textPaint.setTextAlign(Paint.Align.CENTER);//文字居中 } @Override protected synchronized void onDraw(Canvas canvas) { super.onDraw(canvas);// canvas.drawColor(0xffffffff); circle_ring_radius = circle_ring_Side / 2 - draw_offset;//半径 //绘制默认的圆环 canvas.drawCircle(circle_ring_Side / 2, circle_ring_Side / 2, circle_ring_radius, backPaint); //绘制弧形 drawArcRect.left = draw_offset; drawArcRect.top = draw_offset; drawArcRect.right = circle_ring_Side - draw_offset; drawArcRect.bottom = circle_ring_Side - draw_offset; canvas.drawArc(drawArcRect, 90, getProgress() * 360 / getMax(), false, forePaint); //绘制文本的区域 int chord_length = (int) Math.sqrt(Math.pow(circle_ring_Side, 2) + Math.pow(circle_ring_Side, 2));//获取矩形的对角线长度 int draw_text_left = (int) ((chord_length / 2 - circle_ring_radius) * Math.sin(45)); int draw_text_top = draw_text_left; int draw_text_right = circle_ring_Side - draw_text_left; int draw_text_bottom = circle_ring_Side - draw_text_top;// canvas.drawRect(draw_text_left, draw_text_top, draw_text_right, draw_text_bottom, testPaint); //绘制文本 int text_4_side = Math.abs(draw_text_bottom - draw_text_top) / 4;//绘制区域的1/4份 //固定提示文本 textPaint.setColor(text_color); textPaint.setTextSize((float) (text_4_side * 0.6)); canvas.drawText(text, circle_ring_Side / 2, draw_text_top + text_4_side, textPaint); //固定单位文本 canvas.drawText(unit, circle_ring_Side / 2, draw_text_bottom - text_4_side/2, textPaint); //变换的数值 textPaint.setColor(values_color); textPaint.setTextSize((float) (text_4_side)*1.5f); canvas.drawText(String.valueOf(getProgress()),circle_ring_Side/2, circle_ring_Side/2 + text_4_side/2,textPaint); } /** * 测量 * * @param widthMeasureSpec * @param heightMeasureSpec */ @Override protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec);//测量宽度 int heightSize = MeasureSpec.getSize(heightMeasureSpec);//测量高度 circle_ring_Side = Math.min(widthSize, heightSize);//取最小值 setMeasuredDimension(circle_ring_Side, circle_ring_Side);//设置包含圆环的容器为正方形 } /** * dp-->px * * @param decisionType * @return */ private int dip2px(int decisionType) { return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, decisionType, getResources().getDisplayMetrics()); }}
——让我们看一下运行效果
光看着确实有点像那么回事的意思。
【测试一下功能】
刚刚仅仅是看了一下效果图,并没有测试它的功能是否好使,接下来完整的测试一下这个自定义控件的功能是否符合要求吧:
【向布局文件中添加自意义控件】,那个名为lyan的命名空间先不用管!
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:lyan="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".activity.MainActivity"> <lyan.circleprogressbar.view.MyCircleProgressBar android:id="@+id/test" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_centerInParent="true" /></RelativeLayout>
【向Activity中添加测试代码】随便创建一个就OK。这里一样整类贴出。
package lyan.circleprogressbar.activity;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.support.v7.app.AppCompatActivity;import android.util.Log;import lyan.circleprogressbar.R;import lyan.circleprogressbar.view.MyCircleProgressBar;public class MainActivity extends AppCompatActivity { private MyCircleProgressBar circleProgressBar; private int count = 0; private Handler handler = new Handler(new Handler.Callback() { @Override public boolean handleMessage(Message message) { if (message.what == 1){ ++count; circleProgressBar.setProgress(count); Log.e("handleMessage: ", count + ""); } return false; } }); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); circleProgressBar = (MyCircleProgressBar) findViewById(R.id.test); circleProgressBar.setMax(100); new Thread(new Runnable() { @Override public void run() { while (count < 100){ try { handler.sendEmptyMessage(1); Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); }}
——我们再看一下运行效果
看着还行,就差使用自定义的属性了。
【收工】
更改一下布局文件,将自定义的属性添加上:
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:lyan="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".activity.MainActivity"> <lyan.circleprogressbar.view.MyCircleProgressBar android:id="@+id/test" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_centerInParent="true" lyan:circle_ring_background_color="#545454" lyan:circle_ring_foreground_color="#4592F3" lyan:circle_ring_text_color="#4592F3" lyan:circle_ring_values_color="#FBB900" lyan:circle_ring_width = "30dp" lyan:circle_ring_text = "消耗热量" lyan:circle_ring_unit = "卡路里" /></RelativeLayout>
【最后运行一次】
为了与一开始区分开,在布局里更改了几个字:
至此我们的功能都实现完了
参考资料
- http://blog.csdn.net/lmj623565791/article/details/43371299
1 0
- 环形的ProgressBar
- 环形ProgressBar
- 环形ProgressBar特效
- Android自定义环形ProgressBar
- 环形ProgressBar特效
- 环形ProgressBar特效
- 环形ProgressBar特效
- Android改变系统自带环形ProgressBar的大小
- 一个类似于环形的 ProgressBar 的,可以自定义 Color,style 等属性的 View,支持 Material 风格.
- 环形buffer的管理
- 环形输出的源代码
- 环形缓冲区的实现
- 环形缓冲区的实现
- 环形缓冲区的实现
- 环形buffer的实现
- 环形缓冲区的实现
- 简单的环形进度
- 环形进度条的制作
- ActiveMq集群全集
- eclipse中文的乱码问题
- 怎样让background-color在background-img的上边显示呢?
- 根据AWR计算IOPS与MBPS
- 博弈之Nim游戏
- 环形的ProgressBar
- 数组基础及应用
- Ubuntu下hue集成hbase
- EditText所有属性
- uva294 Divisors
- 小回顾-累加算法
- 图像感兴趣区域ROI获取的正确方式
- 项目中 .net framework (v4.0 ->v3.5)降级引发的问题及解决方案
- c.hashMap源码解析(1.7)