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文件:
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" >
android:id="@+id/progressbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
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自定义进度条的圆角横向进度条实例详解,希望对大家有所帮助