Android自定义进度条的圆角横向进度条实例详解
1.本文将向你介绍自定义进度条的写法,比较简单,但还是有些知识点是需要注意的:
invalidate()方法
rectf方法的应用
onmeasure方法的应用
2.原理
画3层圆角矩形,底层为黑色,第二层为灰色,最上一层为进度条颜色,示例图如下:
3.效果图
实现圆角进度条还有很多其他方法,比如在progress控件里填充圆角图片,通过拉伸图片来达到预想的效果,虽然听起来很简单,但实现起来还是有些麻烦的。
4.解说方法
(1)invalidate()方法
invalidate()是用来刷新view的,必须是在ui线程中进行工作。比如在修改某个view的显示时, 调用invalidate()才能看到重新绘制的界面。invalidate()的调用是把之前的旧的view从主ui线程队列中pop掉。一般在自定义控件中会用到这个方法。
(2)rectf方法的应用
rectf是用来绘画矩形的方法。
rectf(left,top,right,bottom),四个参数的含义分别是父控件距离矩形左上右下边距的距离,以下用图来说明:
drawroundrect方法是用来绘制圆角矩形的,它的参数如下:
参数说明
rect:rectf对象。
rx:x方向上的圆角半径。
ry:y方向上的圆角半径。
paint:绘制时所使用的画笔。
(3)onmeasure方法
指定自定义控件在屏幕上的大小,onmeasure方法的两个参数是由上一层控件 传入的大小,而且是模式和尺寸混合在一起的数值,需要measurespec.getmode(widthmeasurespec) 得到模式,measurespec.getsize(widthmeasurespec)得到尺寸。
onmeasure的几种模式分别为exactly,at_most,unspecified。
[1]measurespec.exactly
measurespec.exactly是精确尺寸,当我们将控件的layout_width或layout_height指定为具体数值时如andorid:layout_width=”50dip”,或者为fill_parent是,都是控件大小已经确定的情况,都是精确尺寸。
[2]measurespec.at_most
measurespec.at_most是最大尺寸,当控件的layout_width或layout_height指定为wrap_content时,控件大小一般随着控件的子空间或内容进行变化,此时控件尺寸只要不超过父控件允许的最大尺寸即可。因此,此时的mode是at_most,size给出了父控件允许的最大尺寸。
[3]measurespec.unspecified
measurespec.unspecified是未指定尺寸,这种情况不多,一般都是父控件是adapterview,通过measure方法传入的模式。
5.activity_main.xml文件:
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.progresstest.mainactivity" tools:ignore="mergerootframe" > <com.example.progresstest.progressviewtest android:id="@+id/progressbar" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </linearlayout>
6.progressviewtest.java文件
package com.example.progresstest; import android.content.context; import android.graphics.canvas; import android.graphics.color; import android.graphics.paint; import android.graphics.rectf; import android.util.attributeset; import android.view.view; public class progressviewtest extends view { /**进度条最大值*/ private float maxcount; /**进度条当前值*/ private float currentcount; /**画笔*/ private paint mpaint; private int mwidth,mheight; public progressviewtest(context context, attributeset attrs, int defstyle) { super(context, attrs, defstyle); // todo auto-generated constructor stub } public progressviewtest(context context, attributeset attrs) { super(context, attrs); // todo auto-generated constructor stub } public progressviewtest(context context) { super(context); // todo auto-generated constructor stub } /*** * 设置最大的进度值 * @param maxcount */ public void setmaxcount(float maxcount) { this.maxcount = maxcount; } /** * 得到最大进度值 */ public double getmaxcount(){ return maxcount; } /*** * 设置当前的进度值 * @param currentcount */ public void setcurrentcount(float currentcount) { this.currentcount = currentcount > maxcount ? maxcount : currentcount; /** * invalidate()是用来刷新view的,必须是在ui线程中进行工作。比如在修改某个view的显示时, * 调用invalidate()才能看到重新绘制的界面。invalidate()的调用是把之前的旧的view从主ui * 线程队列中pop掉。 */ invalidate(); } @override protected void ondraw(canvas canvas) { // todo auto-generated method stub super.ondraw(canvas); mpaint = new paint(); //设置抗锯齿效果 mpaint.setantialias(true); //设置画笔颜色 mpaint.setcolor(color.black); int round = mheight/2; /** * rectf:绘制矩形,四个参数分别是left,top,right,bottom * 类型是单精度浮点数 */ rectf rf = new rectf(0, 0, mwidth, mheight); /*绘制圆角矩形,背景色为画笔颜色*/ canvas.drawroundrect(rf, round, round, mpaint); /*设置progress内部是灰色*/ mpaint.setcolor(color.rgb(211, 211, 211)); rectf rectblackbg = new rectf(2, 2, mwidth-2, mheight-2); canvas.drawroundrect(rectblackbg, round, round, mpaint); //设置进度条进度及颜色 float section = currentcount/maxcount; rectf rectprogressbg = new rectf(3, 3, (mwidth-3)*section, mheight-3); if(section!=0.0f){ mpaint.setcolor(color.green); }else{ mpaint.setcolor(color.transparent); } canvas.drawroundrect(rectprogressbg, round, round, mpaint); } //dip * scale + 0.5f * (dip >= 0 ? 1 : -1) private int diptopx(int dip){ float scale = getcontext().getresources().getdisplaymetrics().density; return (int) (dip * scale + 0.5f * (dip >= 0 ? 1 : -1));//加0.5是为了四舍五入 } /**指定自定义控件在屏幕上的大小,onmeasure方法的两个参数是由上一层控件 * 传入的大小,而且是模式和尺寸混合在一起的数值,需要measurespec.getmode(widthmeasurespec) * 得到模式,measurespec.getsize(widthmeasurespec)得到尺寸 * */ @override protected void onmeasure(int widthmeasurespec, int heightmeasurespec) { // todo auto-generated method stub super.onmeasure(widthmeasurespec, heightmeasurespec); int widthspecmode = measurespec.getmode(widthmeasurespec); int heightspecmode = measurespec.getmode(heightmeasurespec); int widthspecsize = measurespec.getsize(widthmeasurespec); int heightspecsize = measurespec.getsize(heightmeasurespec); //measurespec.exactly,精确尺寸 if (widthspecmode == measurespec.exactly || widthspecmode == measurespec.at_most) { mwidth = widthspecsize; } else { mwidth = 0; } //measurespec.at_most,最大尺寸,只要不超过父控件允许的最大尺寸即可,measurespec.unspecified未指定尺寸 if (heightspecmode == measurespec.at_most || heightspecmode == measurespec.unspecified) { mheight = diptopx(20); } else { mheight = heightspecsize; } //设置控件实际大小 setmeasureddimension(mwidth, mheight); } }
mainactivity.java文件
package com.example.progresstest; import android.support.v7.app.actionbaractivity; import android.os.bundle; import android.os.handler; import android.os.message; public class mainactivity extends actionbaractivity { private progressviewtest progress; @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); progress = (progressviewtest) findviewbyid(r.id.progressbar); progress.setmaxcount(100); new thread(new runnable() { @override public void run() { // todo auto-generated method stub for (int i = 0; i <=progress.getmaxcount(); i++) { message msg = new message(); msg.arg1 = i; msg.what = 0x01; handler.sendmessage(msg); try { //每隔0.1秒进度前进1 thread.sleep(100); } catch (interruptedexception e) { // todo auto-generated catch block e.printstacktrace(); } } } }).start(); } handler handler = new handler(){ public void handlemessage(message msg) { if(msg.what==0x01){ progress.setcurrentcount(msg.arg1); } }; }; }
以上所述是小编给大家介绍的android自定义进度条的圆角横向进度条实例详解,希望对大家有所帮助
上一篇: Android系统永不锁屏永不休眠的方法