实现一个速度仪表盘的控件

推荐个音乐下载app【佳语音乐下载】
https://gitlab.com/gaopinqiang/checkversion/raw/master/Music_Download.apk

开发有时会用到仪表盘(例如测速,类似汽车仪表盘),这里我们自定义个View来实现这个功能,还支持指针动画,避免过于生硬。

先给个效果图:
在这里插入图片描述

下面是具体的实现代码(在真机上测试通过):
DashboardView.java

package com.example.dashboardView;

import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.SweepGradient;
import android.os.Build;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;

import com.example.testgesturedetector.R;


/**
 * 自定义测速仪表盘
 * 直接继承View需要处理wrap_content 时onMeasure方法的宽高
 */
public class DashboardView extends View {
   

    /** 定义一些缺省值 */
    private int mRadius; // 扇形半径
    private int mStartAngle = 150; // 起始角度,180-30度(左边平行夹角30度)
    private int mSweepAngle = 240; // 绘制角度,360+30度 = 150+240度
    private int mMin = 0; // 最小值
    private int mMax = 100; // 最大值
    private int mSection = 8; // 值域(mMax-mMin)等分份数
    private int mPortion = 5; // 一个mSection等分份数
    private String mHeaderText = ""; // 表头 Mbps
    private int mVelocity = mMin; // 实时速度
    private int mStrokeWidth; // 画笔宽度
    private int mLength1; // 长刻度的相对圆弧的长度
    private int mLength2; // 刻度读数顶部的相对圆弧的长度
    private int mPLRadius; // 指针长半径
    private int mPSRadius; // 指针短半径

    private int mPadding;
    private float mCenterX, mCenterY; // 圆心坐标
    private Paint mPaint;
    private RectF mRectFArc;
    private Path mPath;
    private RectF mRectFInnerArc;
    private Rect mRectText;
    private String[] mTexts;
    private int[] mColors;

    private Context mContext;

    public DashboardView(Context context) {
   
        this(context, null);
        mContext = context;
    }

    public DashboardView(Context context, AttributeSet attrs) {
   
        this(context, attrs, 0);
        mContext = context;
    }

    public DashboardView(Context context, AttributeSet attrs, int defStyleAttr) {
   
        super(context, attrs, defStyleAttr);
        mContext = context;
        init();
    }

    @TargetApi(Build.VERSION_CODES.M)
    private void init() {
   
        mStrokeWidth = dp2px(3);
        mLength1 = dp2px(8) + mStrokeWidth;
        mLength2 = mLength1 + dp2px(4);

        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setStrokeCap(Paint.Cap.ROUND);

        mRectFArc = new RectF();
        mPath = new Path();
        mRectFInnerArc = new RectF();
        mRectText = new Rect();

        mTexts = new String[mSection + 1]; // 需要显示mSection + 1个刻度读数
        for (int i = 0; i < mTexts.length; i++) {
   
            int n = (mMax - mMin) / mSection;
            mTexts[i] = String.valueOf(mMin + i * n);
        }

        // TODO: 2020/4/20  重置刻度盘
        mTexts[0] = "0M";
        mTexts[1] = "1M";
        mTexts[2] = "2M";
        mTexts[3] = "5M";
        mTexts[4] = "10M";
        mTexts[5] = "20M";
        mTexts[6] = "50M";
        mTexts[7] = "80M";
        mTexts[8] = "100M";

        mColors = new int[]{
   
                mContext.getColor(R.color.color_green),
                mContext.getColor(R.color.color_yellow),
                mContext.getColor(R.color.color_red)
        };
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
   
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        mPadding = Math.max(
                Math.max(getPaddingLeft(), getPaddingTop()),
                Math.max(getPaddingRight(), getPaddingBottom())
        );
        setPadding(mPadding, mPadding, mPadding, mPadding);

        int width = resolveSize(dp2px(260), widthMeasureSpec);
        mRadius = (width - mPadding * 2 - mStrokeWidth * 2) / 2;

        // 由起始角度确定的高度
        float[] point1 = getCoordinatePoint(mRadius, mStartAngle);
        // 由结束角度确定的高度
        float[] point2 = getCoordinatePoint(mRadius, mStartAngle + mSweepAngle);
        int height = (int) Math.max(point1[1] + mRadius + mStrokeWidth * 2,
                point2[1] + mRadius + mStrokeWidth * 2);

        // TODO: 2020/4/20 需要处理高度
//        setMeasuredDimension(width, height + getPaddingTop() + getPaddingBottom());
        setMeasuredDimension(width, width);

        mCenterX = mCenterY = getMeasuredWidth() / 2f;
        mRectFArc.set(
                getPaddingLeft() + mStrokeWidth,
                getPaddingTop() + mStrokeWidth,
                getMeasuredWidth() - getPaddingRight() - mStrokeWidth,
                getMeasuredWidth() - getPaddingBottom() - mStrokeWidth
        );

        mPaint.setTextSize(sp2px(16));
        mPaint.getTextBounds("0"
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值