转载请注明出处:http://blog.csdn.net/magic_jss/article/details/52348392;
群里聊天一哥们发的一个自定义View感觉很perfection,于是就根据他发的图写了个类似的效果。一个仪表盘,描述用户的账号安全等级。希望能够帮助到需要类似效果的猿/媛们,如果存在什么问题恳请指正!
模拟器上运行效果可能有点差,真机上就比较清晰了。
废话少说,直接上码;
/**
* Created by magic on 2016年7月28日.账户安全 仪表盘view
*/
@SuppressLint({ "DrawAllocation", "ResourceAsColor" })
public class DashBoardView extends View {
private Context context;
// 圆
private Paint mPaint;
// 弧
private Paint mPaintArc;
// 弧的外接矩形
private RectF rectFArc, rectFArc2;
// text
private Paint mPaintText;
// line
private Paint mPaintLine;
// 指针路径
private Path path;
// 宽、高
private float width, height;
private float radius, arcWidth, arcWidth2, arcStrokeWidth, pointerLength,
lineLength;
// 设置旋转角度
public float degrees = 0;
private float paddingLeft, paddingTop, paddingRight, paddingBottom;
// 底部描述文字
private String desc;
public DashBoardView(Context context) {
super(context);
this.context = context;
init();
}
public DashBoardView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
init();
}
public DashBoardView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.context = context;
init();
}
private void init() {
mPaint = new Paint();
mPaint.setColor(context.getResources().getColor(R.color.zs));
mPaint.setStyle(Paint.Style.FILL);
mPaint.setAntiAlias(true);
mPaintArc = new Paint();
mPaintArc.setStyle(Paint.Style.STROKE);
mPaintArc.setAntiAlias(true);
mPaintLine = new Paint();
mPaintLine.setColor(context.getResources().getColor(R.color.zs));
mPaintLine.setStyle(Paint.Style.FILL);
mPaintLine.setAntiAlias(true);
path = new Path();
mPaintText = new Paint();
mPaintText.setColor(context.getResources().getColor(R.color.zs));
mPaintText.setAntiAlias(true);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int wMode = MeasureSpec.getMode(widthMeasureSpec);
int wSize = MeasureSpec.getSize(widthMeasureSpec);
int hMode = MeasureSpec.getMode(heightMeasureSpec);
int hSize = MeasureSpec.getSize(heightMeasureSpec);
// 处理宽高为 wrap_content的情况
if (wMode == MeasureSpec.AT_MOST && hMode == MeasureSpec.AT_MOST) {
setMeasuredDimension(200, 200);
} else if (wMode == MeasureSpec.AT_MOST) {
setMeasuredDimension(200, hSize);
} else if (hMode == MeasureSpec.AT_MOST) {
setMeasuredDimension(wSize, 200);
}
// 获取padding
paddingLeft = getPaddingLeft();
paddingTop = getPaddingTop();
paddingRight = getPaddingRight();
paddingBottom = getPaddingBottom();
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
this.width = w - paddingLeft - paddingRight;
this.height = h - paddingTop - paddingBottom;// 640 850 360-360
if (width <= height) {
arcWidth = width / 2;
} else {
arcWidth = height / 2;
}
arcStrokeWidth = (10 / 180f) * arcWidth;
radius = 15 / 180f * arcWidth;
pointerLength = 110 / 180f * arcWidth;
lineLength = 15 / 180f * arcWidth;
mPaintArc.setStrokeWidth(arcStrokeWidth);
arcWidth2 = arcWidth - mPaintArc.getStrokeWidth();
mPaintLine.setStrokeWidth(2 / 180f * arcWidth);
mPaintText.setTextSize(20 / 180f * arcWidth);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.translate(width / 2 + paddingLeft, height / 2 + paddingTop);
canvas.drawCircle(0, 0, radius, mPaint);
rectFArc = new RectF(-arcWidth, -arcWidth, arcWidth, arcWidth);
rectFArc2 = new RectF(-arcWidth2, -arcWidth2, arcWidth2, arcWidth2);
mPaintArc.setColor(context.getResources().getColor(R.color.mainTextBlack));
canvas.drawArc(rectFArc, 165, 210, false, mPaintArc);
mPaintArc.setColor(context.getResources().getColor(R.color.hs));
canvas.drawArc(rectFArc2, 165, 70, false, mPaintArc);
mPaintArc.setColor(context.getResources().getColor(R.color.zs));
canvas.drawArc(rectFArc2, 235, 70, false, mPaintArc);
mPaintArc.setColor(context.getResources().getColor(R.color.ls));
canvas.drawArc(rectFArc2, 305, 70, false, mPaintArc);
float startXLine = -(arcWidth2 - (1 / 2) * arcStrokeWidth);
float stopXLine = -(arcWidth2 - (1 / 2) * arcStrokeWidth - lineLength);
float startXText = -mPaintText.measureText("中") / 2;
float stopXText = -(arcWidth2 - (1 / 2) * mPaintArc.getStrokeWidth() - (2.5f) * lineLength);
canvas.drawLine(0, startXLine, 0, stopXLine, mPaintLine);
mPaintText.setColor(context.getResources().getColor(R.color.zs));
canvas.drawText("中", startXText, stopXText, mPaintText);
mPaintLine.setColor(context.getResources().getColor(R.color.hs));
for (int i = 0; i <= 2; i++) {
canvas.rotate(-35);
if (i == 1) {
mPaintText.setColor(context.getResources().getColor(R.color.hs));
canvas.drawText("低", startXText, stopXText, mPaintText);
}
canvas.drawLine(0, startXLine, 0, stopXLine, mPaintLine);
}
canvas.rotate(105);
mPaintLine.setColor(context.getResources().getColor(R.color.ls));
for (int i = 0; i <= 2; i++) {
canvas.rotate(35);
if (i == 1) {
mPaintText.setColor(context.getResources().getColor(R.color.ls));
canvas.drawText("高", startXText, stopXText, mPaintText);
}
canvas.drawLine(0, startXLine, 0, stopXLine, mPaintLine);
}
canvas.rotate(-105);
mPaintText.setColor(context.getResources().getColor(R.color.mainTextBlack));
canvas.drawText(desc, -mPaintText.measureText(desc) / 2, pointerLength,mPaintText);
// 画笔坐标系旋转
canvas.rotate(-105 + degrees);
// 绘制指针
mPaintLine.setColor(context.getResources().getColor(R.color.zs));
path.moveTo(radius / 2, 0);
path.lineTo(0, -pointerLength);
path.lineTo(-radius / 2, 0);
canvas.drawPath(path, mPaintLine);
}
/**
* 设置旋转角度
*/
public void setDegrees(float degrees) {
this.degrees = degrees;
invalidate();
}
/**
* 获取旋转角度
*/
public float getDegrees() {
return this.degrees;
}
/**
* 设置底部描述
*/
public void setTextDesc(String desc){
this.desc=desc;
invalidate();
}
}
直接继承View需要处理宽高为包含内容,存在padding的情况。其中,根据在某个定值的情况下动态计算中心圆半径、指针长度、环形StrokeWidth等等,代码比较简单,直接看注释就OK!
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:magic="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<com.mars.customview.DashBoardView
android:id="@+id/dashBoardView"
android:layout_width="match_parent"
android:layout_height="300dp"
android:padding="50dp" />
</LinearLayout>
未添加自定义属性,若有相关需求可自行添加。
/**
* Created by magic on 2016年7月28日.
*/
public class MainActivity extends Activity {
DashBoardView dashBoardView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
dashBoardView = (DashBoardView) findViewById(R.id.dashBoardView);
// 账户安全 仪表盘
ObjectAnimator animator = ObjectAnimator.ofFloat(dashBoardView,"degrees", 175);
animator.setDuration(3000);
// 设置插值器
animator.setInterpolator(new DecelerateInterpolator());
animator.start();
dashBoardView.setTextDesc("你的账户等级 高");
}
}
整个Demo下载地址:http://download.csdn.net/detail/magic_jss/9616384;
END!