开源 java android app 开发(十五)自定义绘图控件--仪表盘

文章的目的为了记录使用java 进行android app 开发学习的经历。本职为嵌入式软件开发,公司安排开发app,临时学习,完成app的开发。开发流程和要点有些记忆模糊,赶紧记录,防止忘记。

相关链接:

开源 java android app 开发(一)开发环境的搭建-CSDN博客

开源 java android app 开发(二)工程文件结构-CSDN博客

开源 java android app 开发(三)GUI界面布局和常用组件-CSDN博客

开源 java android app 开发(四)GUI界面重要组件-CSDN博客

开源 java android app 开发(五)文件和数据库存储-CSDN博客

开源 java android app 开发(六)多媒体使用-CSDN博客

开源 java android app 开发(七)通讯之Tcp和Http-CSDN博客

开源 java android app 开发(八)通讯之Mqtt和Ble-CSDN博客

开源 java android app 开发(九)后台之线程和服务-CSDN博客

开源 java android app 开发(十)广播机制-CSDN博客

开源 java android app 开发(十一)调试、发布-CSDN博客

开源 java android app 开发(十二)封库.aar-CSDN博客

开源 java android app 开发(十三)自定义绘图控件--游戏摇杆

开源 java android app 开发(十四)自定义绘图控件--波形图

开源 java android app 开发(十五)自定义绘图控件--仪表盘

开源 java android app 开发(十六)自定义绘图控件--圆环

推荐链接:

开源C# .net mvc 开发(一)WEB搭建_c#部署web程序-CSDN博客

开源 C# .net mvc 开发(二)网站快速搭建_c#网站开发-CSDN博客

开源 C# .net mvc 开发(三)WEB内外网访问(VS发布、IIS配置网站、花生壳外网穿刺访问)_c# mvc 域名下不可訪問內網,內網下可以訪問域名-CSDN博客

开源 C# .net mvc 开发(四)工程结构、页面提交以及显示_c#工程结构-CSDN博客

开源 C# .net mvc 开发(五)常用代码快速开发_c# mvc开发-CSDN博客

本章节主要内容是:自定义的仪表盘控件的使用,随机指向速度。

1.代码分析

2.所有源码

3.效果图

一、代码分析

DashboardView 自定义仪表盘视图详细分析

  1. 类定义和常量声明

    public class DashboardView extends View {
    // 默认颜色值常量
    private static final int DEFAULT_DIAL_COLOR = Color.parseColor("#3F51B5");
    private static final int DEFAULT_NEEDLE_COLOR = Color.parseColor("#FF4081");
    private static final int DEFAULT_TEXT_COLOR = Color.parseColor("#212121");
    private static final int DEFAULT_BG_COLOR = Color.parseColor("#FFFFFF");

功能分析:

继承自View基类,实现自定义视图

定义4个默认颜色常量,使用Material Design配色方案

Color.parseColor()将十六进制颜色字符串转换为整型颜色值

  1. 成员变量定义

2.1 绘制对象

复制代码
private Paint dialPaint;        // 表盘圆弧画笔
private Paint needlePaint;      // 指针画笔  
private Paint textPaint;        // 文字画笔
private Paint bgPaint;          // 背景画笔

2.2 自定义属性

复制代码
private String title = "仪表盘";     // 标题文本
private int dialColor;              // 表盘颜色
private int needleColor;            // 指针颜色
private int textColor;              // 文字颜色
private int backgroundColor;        // 背景颜色

2.3 数据范围

复制代码
private float currentValue = 0;     // 当前显示值
private float minValue = 0;         // 最小值
private float maxValue = 100;       // 最大值
private float targetValue = 0;      // 动画目标值

2.4 动画控制

复制代码
private boolean isAnimating = false;                    // 动画状态标志
private static final long ANIMATION_DURATION = 500;     // 动画时长500ms
private long animationStartTime = 0;                    // 动画开始时间戳
  1. 构造函数

3.1 单参数构造函数

复制代码
public DashboardView(Context context) {
    super(context);
    init(null);  // 调用初始化方法,无属性集
}

功能: 用于代码动态创建视图时的构造函数

3.2 双参数构造函数

复制代码
public DashboardView(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
    init(attrs);  // 传入XML属性集
}

功能: 用于XML布局文件中引用的标准构造函数

3.3 三参数构造函数

复制代码
public DashboardView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init(attrs);  // 包含默认样式属性
}

功能: 支持样式属性的构造函数

  1. init() 初始化函数

    private void init(AttributeSet attrs) {
    // 获取自定义属性
    if (attrs != null) {
    TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.DashboardView);
    title = a.getString(R.styleable.DashboardView_title);
    dialColor = a.getColor(R.styleable.DashboardView_dialColor, DEFAULT_DIAL_COLOR);
    needleColor = a.getColor(R.styleable.DashboardView_needleColor, DEFAULT_NEEDLE_COLOR);
    textColor = a.getColor(R.styleable.DashboardView_textColor, DEFAULT_TEXT_COLOR);
    backgroundColor = a.getColor(R.styleable.DashboardView_backgroundColor, DEFAULT_BG_COLOR);
    a.recycle(); // 必须回收TypedArray
    } else {
    // 使用默认值
    dialColor = DEFAULT_DIAL_COLOR;
    // ... 其他颜色初始化
    }

    复制代码
     // 初始化表盘画笔
     dialPaint = new Paint(Paint.ANTI_ALIAS_FLAG);  // 启用抗锯齿
     dialPaint.setColor(dialColor);
     dialPaint.setStyle(Paint.Style.STROKE);        // 描边模式
     dialPaint.setStrokeWidth(10f);                 // 线宽10像素
     
     // 初始化指针画笔
     needlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
     needlePaint.setColor(needleColor);
     needlePaint.setStyle(Paint.Style.FILL_AND_STROKE);  // 填充和描边
     needlePaint.setStrokeWidth(5f);                // 线宽5像素
     
     // 初始化文字画笔
     textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
     textPaint.setColor(textColor);
     textPaint.setTextSize(40);                     // 文字大小40px
     textPaint.setTextAlign(Paint.Align.CENTER);    // 文字居中对齐
     
     // 初始化背景画笔
     bgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
     bgPaint.setColor(backgroundColor);
     bgPaint.setStyle(Paint.Style.FILL);            // 填充模式

    }

功能分析:

属性解析: 使用TypedArray读取XML中定义的属性值

资源回收: 必须调用recycle()释放资源

画笔配置: 为不同绘制元素创建专用的Paint对象

抗锯齿: 所有画笔都启用抗锯齿以获得平滑效果5. onDraw() 核心绘制函数

复制代码
@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);  // 调用父类绘制

    // 计算基本几何参数
    int width = getWidth();
    int height = getHeight();
    int centerX = width / 2;      // 中心点X坐标
    int centerY = height / 2;     // 中心点Y坐标  
    int radius = Math.min(width, height) / 2 - 20;  // 表盘半径(留出边距)

    // 1. 绘制背景圆形
    canvas.drawCircle(centerX, centerY, radius + 20, bgPaint);

    // 2. 绘制表盘圆弧
    RectF oval = new RectF(centerX - radius, centerY - radius, 
                          centerX + radius, centerY + radius);
    canvas.drawArc(oval, 150, 240, false, dialPaint);  // 从150°开始绘制240°圆弧

    // 3. 绘制刻度线和刻度值
    drawScale(canvas, centerX, centerY, radius);

    // 4. 绘制指针
    drawNeedle(canvas, centerX, centerY, radius);

    // 5. 绘制标题文字
    canvas.drawText(title, centerX, centerY + radius + 60, textPaint);

    // 6. 绘制当前数值(加大字号)
    textPaint.setTextSize(50);  // 临时调整字号
    canvas.drawText(String.format("%.1f", currentValue), centerX, centerY + 20, textPaint);
    textPaint.setTextSize(40);  // 恢复原字号

    // 7. 动画处理逻辑
    if (isAnimating) {
        long currentTime = System.currentTimeMillis();
        float elapsed = currentTime - animationStartTime;  // 已过去的时间

        if (elapsed < ANIMATION_DURATION) {
            float progress = elapsed / ANIMATION_DURATION;  // 动画进度(0-1)
            // 线性插值计算当前值
            currentValue = currentValue + (targetValue - currentValue) * progress;
            invalidate();  // 请求重绘,实现动画帧
        } else {
            currentValue = targetValue;  // 动画结束,直接跳到目标值
            isAnimating = false;         // 停止动画
        }
    }
}
  1. drawScale() 刻度绘制函数

    private void drawScale(Canvas canvas, int centerX, int centerY, int radius) {
    Paint scalePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    scalePaint.setColor(textColor);
    scalePaint.setTextSize(30);
    scalePaint.setTextAlign(Paint.Align.CENTER);

    复制代码
     // 绘制11个刻度(0-10,包含两端)
     for (int i = 0; i <= 10; i++) {
         // 计算刻度角度:起始150° + 每刻度24°(总240°范围)
         float angle = 150 + (i * 24);
         // 计算对应数值:最小值 + 等分比例
         float value = minValue + (maxValue - minValue) * i / 10;
    
         // 将角度转换为弧度
         double startAngleRad = Math.toRadians(angle);
         
         // 计算刻度线起点(向内偏移20px)
         int startX = centerX + (int) ((radius - 20) * Math.cos(startAngleRad));
         int startY = centerY + (int) ((radius - 20) * Math.sin(startAngleRad));
         
         // 计算刻度线终点(表盘边缘)
         int endX = centerX + (int) (radius * Math.cos(startAngleRad));
         int endY = centerY + (int) (radius * Math.sin(startAngleRad));
    
         // 绘制刻度线
         canvas.drawLine(startX, startY, endX, endY, scalePaint);
    
         // 计算刻度值文字位置(向内偏移50px)
         int textX = centerX + (int) ((radius - 50) * Math.cos(startAngleRad));
         int textY = centerY + (int) ((radius - 50) * Math.sin(startAngleRad)) + 10;
         
         // 绘制刻度数值(取整显示)
         canvas.drawText(String.valueOf((int)value), textX, textY, scalePaint);
     }

    }

  2. drawNeedle() 指针绘制函数

    private void drawNeedle(Canvas canvas, int centerX, int centerY, int radius) {
    // 计算指针角度:150°对应minValue,390°对应maxValue(实际是150°+240°)
    float angle = 150 + (currentValue - minValue) / (maxValue - minValue) * 240;
    double angleRad = Math.toRadians(angle); // 转换为弧度

    复制代码
     // 计算指针终点坐标(向内偏移30px)
     int endX = centerX + (int) ((radius - 30) * Math.cos(angleRad));
     int endY = centerY + (int) ((radius - 30) * Math.sin(angleRad));
    
     // 绘制指针线段(从中心到终点)
     canvas.drawLine(centerX, centerY, endX, endY, needlePaint);
    
     // 绘制中心圆点(半径10px)
     canvas.drawCircle(centerX, centerY, 10, needlePaint);

    }

  3. setValue() 数值设置函数(带动画)

    public void setValue(float value) {
    // 边界检查
    if (value < minValue) value = minValue;
    if (value > maxValue) value = maxValue;

    复制代码
     // 设置动画参数
     this.targetValue = value;          // 目标值
     this.isAnimating = true;           // 启动动画标志
     this.animationStartTime = System.currentTimeMillis();  // 记录开始时间
     
     invalidate();  // 触发重绘,启动动画

    }

  4. 其他设置函数

    // 设置数值范围
    public void setRange(float min, float max) {
    this.minValue = min;
    this.maxValue = max;
    invalidate(); // 重绘视图
    }

    // 设置标题
    public void setTitle(String title) {
    this.title = title;
    invalidate();
    }

    // 颜色设置函数(都会更新对应画笔颜色并重绘)
    public void setDialColor(int color) {
    this.dialColor = color;
    dialPaint.setColor(color);
    invalidate();
    }

    // 获取当前值
    public float getCurrentValue() {
    return currentValue;
    }

  5. 关键设计特点

10.1 动画实现机制

线性插值: 使用currentValue + (targetValue - currentValue) * progress计算过渡值

时间控制: 基于系统时间戳计算动画进度

连续重绘: 通过invalidate()在动画期间持续刷新视图

10.2 几何计算

角度映射: 将数值线性映射到150°-390°的角度范围

坐标转换: 使用三角函数计算圆周上的点坐标

自适应尺寸: 基于视图实际尺寸计算绘制参数

10.3 绘制层次

背景圆形

表盘圆弧

刻度线和数值

指针和中心点

标题和当前值文字

这个自定义视图实现了完整的仪表盘功能,具有良好的可定制性和平滑的动画效果

二、所有源码

文件结构,

DashboardView.java

MainActivity.java

activity_main.xml

attrs.xml

colors.xml

1.DashboardView.java源码

复制代码
package com.example.dashboard;


import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
import androidx.annotation.Nullable;

public class DashboardView extends View {
    // 默认颜色值
    private static final int DEFAULT_DIAL_COLOR = Color.parseColor("#3F51B5");
    private static final int DEFAULT_NEEDLE_COLOR = Color.parseColor("#FF4081");
    private static final int DEFAULT_TEXT_COLOR = Color.parseColor("#212121");
    private static final int DEFAULT_BG_COLOR = Color.parseColor("#FFFFFF");

    // 绘制相关对象
    private Paint dialPaint;
    private Paint needlePaint;
    private Paint textPaint;
    private Paint bgPaint;

    // 自定义属性
    private String title = "仪表盘";
    private int dialColor;
    private int needleColor;
    private int textColor;
    private int backgroundColor;

    // 数据相关
    private float currentValue = 0;
    private float minValue = 0;
    private float maxValue = 100;
    private float targetValue = 0;

    // 动画相关
    private boolean isAnimating = false;
    private static final long ANIMATION_DURATION = 500; // 动画持续时间(ms)
    private long animationStartTime = 0;

    public DashboardView(Context context) {
        super(context);
        init(null);
    }

    public DashboardView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(attrs);
    }

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

    private void init(AttributeSet attrs) {
        // 获取自定义属性
        if (attrs != null) {
            TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.DashboardView);
            title = a.getString(R.styleable.DashboardView_title);
            dialColor = a.getColor(R.styleable.DashboardView_dialColor, DEFAULT_DIAL_COLOR);
            needleColor = a.getColor(R.styleable.DashboardView_needleColor, DEFAULT_NEEDLE_COLOR);
            textColor = a.getColor(R.styleable.DashboardView_textColor, DEFAULT_TEXT_COLOR);
            backgroundColor = a.getColor(R.styleable.DashboardView_backgroundColor, DEFAULT_BG_COLOR);
            a.recycle();
        } else {
            dialColor = DEFAULT_DIAL_COLOR;
            needleColor = DEFAULT_NEEDLE_COLOR;
            textColor = DEFAULT_TEXT_COLOR;
            backgroundColor = DEFAULT_BG_COLOR;
        }

        // 初始化表盘画笔
        dialPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        dialPaint.setColor(dialColor);
        dialPaint.setStyle(Paint.Style.STROKE);
        dialPaint.setStrokeWidth(10f);

        // 初始化指针画笔
        needlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        needlePaint.setColor(needleColor);
        needlePaint.setStyle(Paint.Style.FILL_AND_STROKE);
        needlePaint.setStrokeWidth(5f);

        // 初始化文字画笔
        textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        textPaint.setColor(textColor);
        textPaint.setTextSize(40);
        textPaint.setTextAlign(Paint.Align.CENTER);

        // 初始化背景画笔
        bgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        bgPaint.setColor(backgroundColor);
        bgPaint.setStyle(Paint.Style.FILL);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        int width = getWidth();
        int height = getHeight();
        int centerX = width / 2;
        int centerY = height / 2;
        int radius = Math.min(width, height) / 2 - 20;

        // 绘制背景
        canvas.drawCircle(centerX, centerY, radius + 20, bgPaint);

        // 绘制表盘
        RectF oval = new RectF(centerX - radius, centerY - radius, centerX + radius, centerY + radius);
        canvas.drawArc(oval, 150, 240, false, dialPaint);

        // 绘制刻度
        drawScale(canvas, centerX, centerY, radius);

        // 绘制指针
        drawNeedle(canvas, centerX, centerY, radius);

        // 绘制标题
        canvas.drawText(title, centerX, centerY + radius + 60, textPaint);

        // 绘制当前值
        textPaint.setTextSize(50);
        canvas.drawText(String.format("%.1f", currentValue), centerX, centerY + 20, textPaint);
        textPaint.setTextSize(40);

        // 如果需要动画,继续重绘
        if (isAnimating) {
            long currentTime = System.currentTimeMillis();
            float elapsed = currentTime - animationStartTime;

            if (elapsed < ANIMATION_DURATION) {
                float progress = elapsed / ANIMATION_DURATION;
                currentValue = currentValue + (targetValue - currentValue) * progress;
                invalidate();
            } else {
                currentValue = targetValue;
                isAnimating = false;
            }
        }
    }

    private void drawScale(Canvas canvas, int centerX, int centerY, int radius) {
        Paint scalePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        scalePaint.setColor(textColor);
        scalePaint.setTextSize(30);
        scalePaint.setTextAlign(Paint.Align.CENTER);

        for (int i = 0; i <= 10; i++) {
            float angle = 150 + (i * 24);
            float value = minValue + (maxValue - minValue) * i / 10;

            // 计算刻度起点和终点
            double startAngleRad = Math.toRadians(angle);
            int startX = centerX + (int) ((radius - 20) * Math.cos(startAngleRad));
            int startY = centerY + (int) ((radius - 20) * Math.sin(startAngleRad));
            int endX = centerX + (int) (radius * Math.cos(startAngleRad));
            int endY = centerY + (int) (radius * Math.sin(startAngleRad));

            // 绘制刻度线
            canvas.drawLine(startX, startY, endX, endY, scalePaint);

            // 绘制刻度值
            int textX = centerX + (int) ((radius - 50) * Math.cos(startAngleRad));
            int textY = centerY + (int) ((radius - 50) * Math.sin(startAngleRad)) + 10;
            canvas.drawText(String.valueOf((int)value), textX, textY, scalePaint);
        }
    }

    private void drawNeedle(Canvas canvas, int centerX, int centerY, int radius) {
        // 计算指针角度 (150°到390°对应minValue到maxValue)
        float angle = 150 + (currentValue - minValue) / (maxValue - minValue) * 240;
        double angleRad = Math.toRadians(angle);

        // 计算指针终点
        int endX = centerX + (int) ((radius - 30) * Math.cos(angleRad));
        int endY = centerY + (int) ((radius - 30) * Math.sin(angleRad));

        // 绘制指针
        canvas.drawLine(centerX, centerY, endX, endY, needlePaint);

        // 绘制中心圆点
        canvas.drawCircle(centerX, centerY, 10, needlePaint);
    }

    // 设置当前值(带动画效果)
    public void setValue(float value) {
        if (value < minValue) value = minValue;
        if (value > maxValue) value = maxValue;

        this.targetValue = value;
        this.isAnimating = true;
        this.animationStartTime = System.currentTimeMillis();
        invalidate();
    }

    // 设置数值范围
    public void setRange(float min, float max) {
        this.minValue = min;
        this.maxValue = max;
        invalidate();
    }

    // 设置标题
    public void setTitle(String title) {
        this.title = title;
        invalidate();
    }

    // 设置表盘颜色
    public void setDialColor(int color) {
        this.dialColor = color;
        dialPaint.setColor(color);
        invalidate();
    }

    // 设置指针颜色
    public void setNeedleColor(int color) {
        this.needleColor = color;
        needlePaint.setColor(color);
        invalidate();
    }

    // 设置文字颜色
    public void setTextColor(int color) {
        this.textColor = color;
        textPaint.setColor(color);
        invalidate();
    }

    // 设置背景颜色
    public void setBackgroundColor(int color) {
        this.backgroundColor = color;
        bgPaint.setColor(color);
        invalidate();
    }

    public float getCurrentValue() {
        return currentValue;
    }
}

2.MainActivity.java源码

复制代码
package com.example.dashboard;



import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Handler;
import android.widget.TextView;
import java.util.Random;

public class MainActivity extends AppCompatActivity {
    private DashboardView dashboard;
    private TextView valueText;
    private Handler handler = new Handler();
    private Random random = new Random();
    private float minValue = 0;
    private float maxValue = 100;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        dashboard = findViewById(R.id.dashboard);
        valueText = findViewById(R.id.valueText);

        // 设置仪表盘属性
        dashboard.setTitle("速度仪表盘");
        dashboard.setDialColor(getResources().getColor(R.color.dialColor));
        dashboard.setNeedleColor(getResources().getColor(R.color.needleColor));
        dashboard.setTextColor(getResources().getColor(R.color.textColor));
        dashboard.setBackgroundColor(getResources().getColor(R.color.backgroundColor));
        dashboard.setRange(minValue, maxValue);

        // 开始定时更新数据
        startDataUpdates();
    }

    private void startDataUpdates() {
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                // 生成随机值
                float value = minValue + random.nextFloat() * (maxValue - minValue);

                // 更新仪表盘
                dashboard.setValue(value);

                // 更新文本显示
                valueText.setText(String.format("当前值: %.1f", value));

                // 1秒后再次更新
                handler.postDelayed(this, 1000);
            }
        }, 1000);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 移除所有回调,防止内存泄漏
        handler.removeCallbacksAndMessages(null);
    }
}

3.activity_main.xml源码

复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center"
    android:padding="16dp"
    tools:context=".MainActivity">

    <com.example.dashboard.DashboardView
        android:id="@+id/dashboard"
        android:layout_width="300dp"
        android:layout_height="300dp"
        app:title="速度仪表盘"
        app:dialColor="#3F51B5"
        app:needleColor="#FF4081"
        app:textColor="#212121"
        app:backgroundColor="#FFFFFF" />

    <TextView
        android:id="@+id/valueText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:text="当前值: 0.0"
        android:textSize="18sp" />

</LinearLayout>

4.attrs.xml源码用于主活动设置控件的属性

复制代码
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="DashboardView">
        <attr name="title" format="string" />
        <attr name="dialColor" format="color" />
        <attr name="needleColor" format="color" />
        <attr name="textColor" format="color" />
        <attr name="backgroundColor" format="color" />
    </declare-styleable>
</resources>

5.colors.xml源码用途添加的各种颜色

复制代码
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#008577</color>
    <color name="colorPrimaryDark">#00574B</color>
    <color name="colorAccent">#D81B60</color>


    <color name="purple_200">#FFBB86FC</color>
    <color name="purple_500">#FF6200EE</color>
    <color name="purple_700">#FF3700B3</color>
    <color name="teal_200">#FF03DAC5</color>
    <color name="teal_700">#FF018786</color>
    <color name="black">#FF000000</color>
    <color name="white">#FFFFFFFF</color>

    <!-- 仪表盘自定义颜色 -->
    <color name="dialColor">#3F51B5</color>
    <color name="needleColor">#FF4081</color>
    <color name="textColor">#212121</color>
    <color name="backgroundColor">#FFFFFF</color>

</resources>

三、效果演示

主活动随机写入数据,指针指向仪表盘的相应位置。

相关推荐
FrankYoou2 小时前
Spring Boot 自动配置之 TaskExecutor
java·spring boot
爱读源码的大都督2 小时前
Spring AI Alibaba JManus底层实现剖析
java·人工智能·后端
jzlhll1232 小时前
deepseek Kotlin Flow 全面详解
android·kotlin·flow
间彧2 小时前
ReentrantLock与ReadWriteLock在性能和使用场景上有什么区别?
java
Lbwnb丶2 小时前
p6spy 打印完整sql
java·数据库·sql
间彧2 小时前
公平锁与非公平锁的选择策略与场景分析
java
渣哥2 小时前
锁升级到底能不能“退烧”?synchronized 释放后状态解析
java
ZHANG13HAO2 小时前
Android 13 完整实现 USB 网卡支持与网络优先级配置(USB>WiFi>4G)
android·网络
间彧2 小时前
Java ReentrantLock详解与应用实战
java