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

三、效果演示

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

相关推荐
万岳软件开发小城14 分钟前
AI数字人系统源码+AI数字人小程序开发:2025年热门AI项目
人工智能·开源·软件开发·app开发·ai数字人小程序·ai数字人系统源码
notillusion15 分钟前
KWW#71843
java·php·程序优化
limingade34 分钟前
手机转SIP-手机做中继网关-落地线路对接软交换呼叫中心
android·智能手机·手机转sip·手机做sip中继网关·sip中继
RainbowC040 分钟前
GapBuffer高效标记管理算法
android·算法
Deschen44 分钟前
设计模式-抽象工厂模式
java·设计模式·抽象工厂模式
齐木卡卡西在敲代码1 小时前
java流式编程学习
java
ʚ希希ɞ ྀ1 小时前
SpringBoot的学习
java·spring boot·学习
notillusion1 小时前
TRX#22597
java·php·程序优化
程序员码歌1 小时前
豆包Seedream4.0深度体验:p图美化与文生图创作
android·前端·后端