Android - 刻度圆圈
1、onMeasure中:match_parent与exactly数值 对应Mode = MeasureSpec.EXACTLY;
wrap_content 需要处理宽与高;
2、ValueAnimator 实现动画效果
MyDashCircle
package com.yizhui.dashcircle.widget;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
import com.yizhui.dashcircle.R;
/**
* Created by Yizhui on 2016/3/2.
*/
public class MyDashCircle extends View {
private float circleRadiu;//内圆半径长度
private float dashWidth; //刻度长度
private int firstColor; //当前进度颜色
private int secondColor; //刻度颜色
private int outCircleColor; //外圆圈颜色
private int outCircleWidth; //外圆圈宽度
private int outCircleSpace; //外圆圈与刻度之间间隔
private ValueAnimator mValueAnimator;
private int totalDuration=60;
private int currentDuration=20;
private int dashDegree=2;
private Handler mHandler;
private Paint mPaint;
public MyDashCircle(Context context) {
this(context, null);
}
public MyDashCircle(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyDashCircle(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// 获取自定义属性
TypedArray arr = context.getTheme().obtainStyledAttributes(attrs,
R.styleable.DashCircle, defStyle, 0);
int n = arr.getIndexCount();
for (int i = 0; i < n; i++) {
int attr = arr.getIndex(i);
switch (attr) {
case R.styleable.DashCircle_circleRadiu:
circleRadiu = arr.getDimensionPixelSize(attr,
(int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, 100, context
.getResources().getDisplayMetrics()));
break;
case R.styleable.DashCircle_dashWidth:
dashWidth = arr.getDimensionPixelSize(attr,
(int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, 30, context
.getResources().getDisplayMetrics()));
break;
case R.styleable.DashCircle_firstColor:
firstColor = arr.getColor(attr, Color.WHITE);
break;
case R.styleable.DashCircle_secondColor:
secondColor = arr.getColor(attr, Color.BLUE);
break;
case R.styleable.DashCircle_outCircleColor:
outCircleColor = arr.getColor(attr, Color.YELLOW);
break;
}
}
arr.recycle(); // TypedArray 使用后需要释放
outCircleWidth=(int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,2,context.getResources().getDisplayMetrics());
outCircleSpace=(int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,10,context.getResources().getDisplayMetrics());
initPaint();
initAnimator();
animateValue();
// mHandler=new Handler(){
// @Override
// public void handleMessage(Message msg) {
// currentDuration++;
// invalidate();
// if(currentDuration<totalDuration){
// mHandler.sendEmptyMessageDelayed(0x11,1000);
// }
// }
// };
//
// mHandler.sendEmptyMessageDelayed(0x11,1000);
}
private void initPaint(){
mPaint=new Paint(Paint.ANTI_ALIAS_FLAG|Paint.DITHER_FLAG);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeJoin(Paint.Join.ROUND);
}
private void initAnimator(){
mValueAnimator=new ValueAnimator();
mValueAnimator.setInterpolator(new AccelerateInterpolator());
mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
currentDuration = (int) animation.getAnimatedValue();
invalidate();
}
});
}
private void animateValue(){
if(mValueAnimator!=null){
mValueAnimator.setDuration(60*1000);
mValueAnimator.setIntValues(0, totalDuration);
mValueAnimator.start();
}
}
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int width;
int height;
if (widthMode == MeasureSpec.EXACTLY) {
width = widthSize;
int maxCircleRadiu=(int)(width-getPaddingLeft()-getPaddingRight()-2*(outCircleWidth+outCircleSpace+dashWidth))/2;
if(circleRadiu>maxCircleRadiu){
circleRadiu=maxCircleRadiu;
}
} else {
width=(int)(getPaddingLeft()+getPaddingRight()+2*(circleRadiu+dashWidth+outCircleSpace+outCircleWidth)+0.5f);
}
if (heightMode == MeasureSpec.EXACTLY) {
height = heightSize;
int maxCircleRadiu=(int)(height-getPaddingTop()-getPaddingBottom()-2*(outCircleWidth+outCircleSpace+dashWidth))/2;
if(circleRadiu>maxCircleRadiu){
circleRadiu=maxCircleRadiu;
}
} else {
height=(int)(getPaddingTop()+getPaddingBottom()+2*(circleRadiu+dashWidth+outCircleSpace+outCircleWidth)+0.5f);
}
setMeasuredDimension(width, height);
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.GRAY);
canvas.translate(getMeasuredWidth() / 2, getMeasuredHeight() / 2);
mPaint.setColor(outCircleColor);
mPaint.setStrokeWidth(outCircleWidth);
//外圆
canvas.drawCircle(0, 0, circleRadiu + dashWidth + outCircleSpace, mPaint);
//当前进度刻度
mPaint.setStrokeWidth(2);
mPaint.setColor(secondColor);
int currentIndex=(int)(currentDuration*360/(totalDuration*dashDegree)+0.5);
for(int i=1;i<=currentIndex;i++){
canvas.drawLine(0,-circleRadiu,0,-(circleRadiu+dashWidth),mPaint);
canvas.rotate(dashDegree);
}
//余下进度刻度
mPaint.setColor(firstColor);
for(int i=currentIndex+1;i<=360/dashDegree;i++){
canvas.drawLine(0,-circleRadiu,0,-(circleRadiu+dashWidth),mPaint);
canvas.rotate(dashDegree);
}
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.yizhui.dashcircle.MainActivity">
<com.yizhui.dashcircle.widget.MyDashCircle
android:layout_width="500dp"
android:layout_height="500dp"
android:padding="10dp"
app:outCircleColor="#ff0000"
app:firstColor="#00ff00"
app:secondColor="#0000ff"
app:dashWidth="10dp"
app:circleRadiu="100dp"/>
</RelativeLayout>
attr.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="outCircleColor" format="color" ></attr>
<attr name="circleRadiu" format="dimension" ></attr>
<attr name="dashWidth" format="dimension" ></attr>
<attr name="firstColor" format="color"/>
<attr name="secondColor" format="color"/>
<declare-styleable name="DashCircle">
<attr name="outCircleColor"></attr>
<attr name="circleRadiu"></attr>
<attr name="dashWidth"></attr>
<attr name="firstColor"/>
<attr name="secondColor"/>
</declare-styleable>
</resources>

浙公网安备 33010602011771号