自定义View实现仪表盘(账户安全)

转载请注明出处:http://blog.csdn.net/magic_jss/article/details/52348392;
群里聊天一哥们发的一个自定义View感觉很perfection,于是就根据他发的图写了个类似的效果。一个仪表盘,描述用户的账号安全等级。希望能够帮助到需要类似效果的猿/媛们,如果存在什么问题恳请指正!

效果图:
自定义View实现仪表盘(账户安全)_第1张图片

模拟器上运行效果可能有点差,真机上就比较清晰了。

1、自定义View

废话少说,直接上码;

/**
 * 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!

2、xml文件

<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>

未添加自定义属性,若有相关需求可自行添加。

3、Activity中使用

/**
 * 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!

你可能感兴趣的:(▸Android,-【编程语言】)