在一次项目需求中,第一次接触到了仪表盘,先来说下需求吧:定时获取数据然后根据数据动态改变指针位置。今天我在这里分享我自己写的一个仪表盘控件,这里我就不定时获取,而是定时使用随机数得到一个值。
先来看看效果截图
我的布局很简单,就三个控件,一个表盘,一个指针,一个中间的文本。在布局上为了方便,我使用了居于水平居中。这样三个控件都会叠在一起,形成上面图片的效果。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<ImageView
android:id="@+id/panelimage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="20dp"
android:src="@drawable/temperature_bg" />
<ImageView
android:id="@+id/needle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="20dp"
android:src="@drawable/pointer" />
<TextView
android:id="@+id/degreeID"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="85dp"
android:background="@drawable/small_semicircle"
android:textSize="30sp"
android:gravity="center" />
</RelativeLayout>
布局看完了,最重要是实现,从网络上获取回来值,再把这个值显示在TextView中,并且对指针经行控制,通过动画实现旋转过程。这里我用Random()方法来设置这个值。
在初始化时new一个timer,每1秒触发一次,发送消息到handler触发随机函数产生随机数
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tmptest);
// 指针
needleView = (ImageView) findViewById(R.id.needle);
// 表盘读数
showText = (TextView) findViewById(R.id.degreeID);
// 定时器,1秒启动一次
Timer timer = new Timer();
timer.schedule(mTimerTask, 0, 1000);
}
// TimerTask
private TimerTask mTimerTask = new TimerTask() {
public void run() {
Message message1 = new Message();
message1.what = 1;
thandler.sendMessage(message1);
}
};
private Handler thandler = new Handler() {
public void handleMessage(Message msg1) {
// 产生随机数0-40
Random random = new Random();
int a = -20 + random.nextInt(61);
// 设置最高值
maxDegree = Float.parseFloat(String.valueOf(a + 20));
// 开始转动
mTimer = new Timer();
// 设置每10毫秒转动一下
mTimer.schedule(new NeedleTask(), 0, 10);
showText.setText(String.valueOf(a));
flag = true;
}
};
thandler里我们再new了一个timer来对指针进行控制,通过animation动画来实现指针的跳转
private class NeedleTask extends TimerTask {
@Override
public void run() {
if (degree <= maxDegree * (3.0f)) {
mHandler.sendEmptyMessage(0);
}
if (degree >= maxDegree * (3.0f) && flag == true) {
mHandler2.sendEmptyMessage(0);
}
}
}
// 顺时
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// 设置仪表盘指针转动动画
// 仪表盘最大是180度
if (degree >= maxDegree * (3.0f)) {
mTimer.cancel();
} else {
degree += 5.0f;
// 设置转动动画
animation = new RotateAnimation(degree, maxDegree * (3.0f),
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
}
// 设置动画时间5毫秒
animation.setDuration(5);
animation.setFillAfter(true);
needleView.startAnimation(animation);
flag = false;
}
};
// 逆时
private Handler mHandler2 = new Handler() {
@Override
public void handleMessage(Message msg) { // 设置仪表盘指针转动动画
// 仪表盘最大是180度,这个是自己测出来的
if (degree <= maxDegree * (3.0f)) {
mTimer.cancel();
} else {
degree += -5.0f;
animation = new RotateAnimation(degree, maxDegree * (3.0f),
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
}
// 设置动画时间5毫秒
animation.setDuration(5);
animation.setFillAfter(true);
needleView.startAnimation(animation);
flag = true;
}
};
大致思路就是这样,不过这里还有问题,在某些情况下会出现指针卡住没有跳转的情况,懒得完善。
demo下载