欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android自定义进度条的圆角横向进度条实例详解

程序员文章站 2024-03-06 11:18:49
1.本文将向你介绍自定义进度条的写法,比较简单,但还是有些知识点是需要注意的: invalidate()方法 rectf方法的应用 onmeasure方法的应用 2...

1.本文将向你介绍自定义进度条的写法,比较简单,但还是有些知识点是需要注意的:

invalidate()方法
rectf方法的应用
onmeasure方法的应用

2.原理

画3层圆角矩形,底层为黑色,第二层为灰色,最上一层为进度条颜色,示例图如下:

Android自定义进度条的圆角横向进度条实例详解

3.效果图

Android自定义进度条的圆角横向进度条实例详解 

实现圆角进度条还有很多其他方法,比如在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自定义进度条的圆角横向进度条实例详解,希望对大家有所帮助