当前位置: 首页 > news >正文

开源 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 开发(十五)绘图定义控件--仪表盘

推荐链接:

开源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.效果图

一、代码分析

WaveView自定义View详细函数分析
1. 构造函数和初始化
init(AttributeSet attrs) - 核心初始化函数
 

private void init(AttributeSet attrs) {waveDataList = new ArrayList<>();  // 初始化波形数据列表// 设置深蓝色科幻风格背景setBackgroundColor(backgroundColor);// 初始化四种不同的画笔initAxisPaint();     // 坐标轴画笔initGridPaint();     // 网格画笔  initTextPaint();     // 文字画笔initGlowPaint();     // 发光效果画笔// 设置默认坐标轴尺寸xAxisSize = 800;     // X轴宽度yAxisSize = 400;     // Y轴高度// 启用硬件加速提升性能setLayerType(LAYER_TYPE_HARDWARE, null);
}


画笔初始化细节
坐标轴画笔:

颜色:半透明青色 Color.argb(180, 0, 255, 255)

线宽:3像素

样式:描边 Style.STROKE

抗锯齿:开启

网格画笔:

颜色:更透明的青色 Color.argb(80, 0, 255, 255)

线宽:1像素(比坐标轴细)

文字画笔:

字体大小:28sp

对齐方式:居中 Align.CENTER

发光画笔:

特殊效果:阴影层 setShadowLayer(15, 0, 0, Color.argb(150, 0, 255, 255))

阴影半径15像素,产生光晕效果

2. 数据管理函数
addWaveData(String name, int color) - 添加波形通道


public void addWaveData(String name, int color) {WaveData waveData = new WaveData(name, color);  // 创建波形数据对象waveDataList.add(waveData);                     // 添加到列表// 注意:这里没有调用invalidate(),因为只是添加通道还没有数据
}
addDataToWave(String name, float value) - 添加数据点
java
public void addDataToWave(String name, float value) {for (WaveData waveData : waveDataList) {if (waveData.getName().equals(name)) {waveData.addData(value);  // 添加数据// FIFO管理:超过200个点移除最旧的数据if (waveData.getData().size() > maxDataPoints) {waveData.getData().remove(0);  // 移除第一个元素}break;}}invalidate();  // 触发重绘
}


数据流管理:

查找对应名称的波形通道

添加新数据点

维护固定长度队列(200点)

自动触发界面更新

3. 绘制函数详细分析
onDraw(Canvas canvas) - 主绘制流程
 

@Override
protected void onDraw(Canvas canvas) {super.onDraw(canvas);  // 调用父类绘制(背景色)// 绘制顺序:从底层到顶层if (showGrid) {drawGrid(canvas);      // 1. 网格(最底层)}drawAxis(canvas);          // 2. 坐标轴drawWaves(canvas);         // 3. 波形数据(主要内容)drawLegend(canvas);        // 4. 图例(覆盖在波形上)drawBorder(canvas);        // 5. 边框(最顶层)
}
drawGrid(Canvas canvas) - 网格绘制
java
private void drawGrid(Canvas canvas) {float startX = 50;                    // 网格起始X坐标float startY = getHeight() - 50;      // 网格起始Y坐标(底部向上50px)float endX = startX + xAxisSize;      // 网格结束X坐标float endY = startY - yAxisSize;      // 网格结束Y坐标// 水平网格线:gridDensity+1条线(包含边界)for (int i = 0; i <= gridDensity; i++) {float y = startY - (i * yAxisSize / gridDensity);  // 等分Y轴canvas.drawLine(startX, y, endX, y, gridPaint);    // 绘制水平线}// 垂直网格线:2倍密度,更密的纵向网格for (int i = 0; i <= gridDensity * 2; i++) {float x = startX + (i * xAxisSize / (gridDensity * 2));canvas.drawLine(x, startY, x, endY, gridPaint);}
}


网格特点:

水平线:按gridDensity等分(默认10等分)

垂直线:双倍密度,更细的纵向分割

网格区域:固定位置,距离左边和底部各50像素

drawAxis(Canvas canvas) - 坐标轴绘制
 

private void drawAxis(Canvas canvas) {float startX = 50;                    // 坐标原点Xfloat startY = getHeight() - 50;      // 坐标原点Yfloat endX = startX + xAxisSize;      // X轴终点float endY = startY - yAxisSize;      // Y轴终点// 绘制X轴和Y轴主线canvas.drawLine(startX, startY, endX, startY, axisPaint);  // X轴canvas.drawLine(startX, startY, startX, endY, axisPaint);  // Y轴// 绘制箭头(简化版,只是延长线)drawArrow(canvas, endX, startY, endX + 15, startY);  // X轴箭头drawArrow(canvas, startX, endY, startX, endY - 15);  // Y轴箭头// X轴刻度(11个刻度:0-10)for (int i = 0; i <= 10; i++) {float x = startX + (i * xAxisSize / 10);canvas.drawLine(x, startY, x, startY - 8, axisPaint);  // 刻度线canvas.drawText(String.valueOf(i), x, startY + 25, textPaint);  // 刻度值}// Y轴刻度(6个刻度:0-5)for (int i = 0; i <= 5; i++) {float y = startY - (i * yAxisSize / 5);canvas.drawLine(startX, y, startX + 8, y, axisPaint);canvas.drawText(String.valueOf(i), startX - 20, y + 10, textPaint);}// 坐标轴标签(带旋转效果)canvas.drawText("时间 (s)", startX + xAxisSize / 2, startY + 50, textPaint);canvas.save();  // 保存画布状态canvas.rotate(-90, startX - 40, startY - yAxisSize / 2);  // 旋转-90度canvas.drawText("幅度 (V)", startX - 40, startY - yAxisSize / 2, textPaint);canvas.restore();  // 恢复画布状态
}


坐标轴特性:

固定刻度数量:X轴11个,Y轴6个

Y轴标签通过旋转实现垂直文字

使用save()/restore()保护画布状态

drawWaves(Canvas canvas) - 核心波形绘制
 

private void drawWaves(Canvas canvas) {if (waveDataList.isEmpty()) return;float startX = 50;                    // 波形起始Xfloat startY = getHeight() - 50;      // 波形起始Y(坐标原点)float xStep = xAxisSize / (maxDataPoints - 1);  // X轴步进(每个数据点间距)for (WaveData waveData : waveDataList) {List<Float> data = waveData.getData();if (data.size() < 2) continue;    // 至少需要2个点才能画线// 1. 绘制发光效果(底层)if (showGlowEffect) {drawGlowEffect(canvas, waveData, startX, startY, xStep);}// 2. 绘制渐变填充(中层)drawGradientFill(canvas, waveData, startX, startY, xStep);// 3. 绘制主波形线(上层)drawMainWaveLine(canvas, waveData, startX, startY, xStep);// 4. 绘制数据点(可选)if (data.size() < 50) {drawDataPoints(canvas, waveData, startX, startY, xStep);}}
}


发光效果绘制
 

// 简化版的发光效果实现
Path glowPath = new Path();
glowPath.moveTo(startX, startY - (data.get(0) * yAxisSize / 5));  // 移动到第一个点for (int i = 1; i < data.size(); i++) {float x = startX + (i * xStep);float y = startY - (data.get(i) * yAxisSize / 5);  // 数据映射到坐标glowPath.lineTo(x, y);  // 连线到下一个点
}// 使用半透明的宽线条产生发光效果
glowPaint.setAlpha(100);  // 半透明
glowPaint.setStrokeWidth(5);  // 比主线条粗
canvas.drawPath(glowPath, glowPaint);
渐变填充绘制
java
Path fillPath = new Path();
fillPath.moveTo(startX, startY);  // 从坐标原点开始
fillPath.lineTo(startX, startY - (data.get(0) * yAxisSize / 5));  // 到第一个数据点// 连接所有数据点
for (int i = 1; i < data.size(); i++) {float x = startX + (i * xStep);float y = startY - (data.get(i) * yAxisSize / 5);fillPath.lineTo(x, y);
}// 闭合路径:从最后一个点回到坐标原点
fillPath.lineTo(startX + (data.size() - 1) * xStep, startY);
fillPath.close();  // 形成闭合区域// 创建从上到下的渐变
LinearGradient gradient = new LinearGradient(0, startY - yAxisSize,  // 渐变起点(顶部)0, startY,              // 渐变终点(底部)Color.argb(80, r, g, b),  // 顶部颜色(较深)Color.argb(20, r, g, b),  // 底部颜色(较浅)Shader.TileMode.CLAMP
);


数据映射公式:

// 将数据值映射到屏幕坐标
float y = startY - (dataValue * yAxisSize / 5);
dataValue:原始数据值(0-5范围)yAxisSize / 5:每个单位对应的像素数startY - ...:因为屏幕坐标系Y轴向下,需要取反drawLegend(Canvas canvas) - 图例绘制
java
private void drawLegend(Canvas canvas) {float startX = 60 + xAxisSize;        // 图例在波形区域右侧float startY = getHeight() - 50 - yAxisSize + 30;  // 与波形顶部对齐// 绘制半透明背景Paint legendBgPaint = new Paint();legendBgPaint.setColor(Color.argb(150, 0, 30, 60));  // 深蓝色半透明背景canvas.drawRoundRect(startX - 10, startY - 10, startX + 180, startY + waveDataList.size() * 40 + 20, 10, 10, legendBgPaint);  // 圆角矩形// 绘制每个波形的图例项for (int i = 0; i < waveDataList.size(); i++) {WaveData waveData = waveDataList.get(i);// 颜色方块canvas.drawRect(startX, startY + (i * 40), startX + 20, startY + (i * 40) + 20, rectPaint);// 波形名称canvas.drawText(waveData.getName(), startX + 100, startY + (i * 40) + 15, textPaint);}
}


4. 辅助函数
配置函数族
java

public void setAxisSize(float xAxisSize, float yAxisSize) {this.xAxisSize = xAxisSize;this.yAxisSize = yAxisSize;invalidate();  // 尺寸改变后立即重绘
}public void setGridDensity(int density) {this.gridDensity = density;invalidate();  // 网格密度改变后重绘
}public void setShowGrid(boolean show) {this.showGrid = show;invalidate();  // 显示状态改变后重绘
}


设计模式:所有改变显示状态的函数都调用invalidate()触发界面更新。

5. 性能优化特性
硬件加速:setLayerType(LAYER_TYPE_HARDWARE, null)

数据量控制:固定200个数据点,避免内存无限增长

条件绘制:数据点少于50时才绘制点状标记

路径绘制:使用Path而非多次drawLine提高效率

6. 坐标系统总结
text
(0,0) ┌────────────────────────────────────────┐
      │          Wave View                     │
      │    ┌─────────────────┐                 │
      │    │                 │  图例区域       │
      │    │   波形区域      │ ┌──────┐        │
      │    │                 │ │信号1│        │
      │    │                 │ │信号2│        │
      │    └─────────────────┘ └──────┘        │
      │                                        │
      └────────────────────────────────────────┘ (width,height)
      
波形区域坐标:
起点:(50, height-50)
尺寸:800×400 像素
数据范围:X轴0-10秒,Y轴0-5伏特
这个自定义View设计完整,功能丰富,具有良好的可扩展性和性能优化。

二、所有源码

源码总共3部分

1.waveview.java源码

package com.example.wave;import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.view.View;import java.util.ArrayList;
import java.util.List;public class WaveView extends View {private List<WaveData> waveDataList;private Paint axisPaint;private Paint gridPaint;private Paint textPaint;private Paint glowPaint;private float xAxisSize;private float yAxisSize;private int maxDataPoints = 200;private int gridDensity = 10;private boolean showGrid = true;private boolean showGlowEffect = true;// 科幻风格颜色private int gridColor = Color.argb(80, 0, 255, 255); // 半透明青色网格private int axisColor = Color.argb(180, 0, 255, 255); // 青色坐标轴private int backgroundColor = Color.argb(255, 10, 20, 40); // 深蓝色背景private int textColor = Color.argb(200, 0, 255, 255); // 青色文字public WaveView(Context context) {super(context);init(null);}public WaveView(Context context, AttributeSet attrs) {super(context, attrs);init(attrs);}public WaveView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init(attrs);}private void init(AttributeSet attrs) {waveDataList = new ArrayList<>();// 设置背景色setBackgroundColor(backgroundColor);// 初始化坐标轴画笔axisPaint = new Paint();axisPaint.setColor(axisColor);axisPaint.setStrokeWidth(3);axisPaint.setStyle(Paint.Style.STROKE);axisPaint.setAntiAlias(true);// 初始化网格画笔gridPaint = new Paint();gridPaint.setColor(gridColor);gridPaint.setStrokeWidth(1);gridPaint.setStyle(Paint.Style.STROKE);gridPaint.setAntiAlias(true);// 初始化文字画笔textPaint = new Paint();textPaint.setColor(textColor);textPaint.setTextSize(28);textPaint.setAntiAlias(true);textPaint.setTextAlign(Paint.Align.CENTER);// 初始化发光效果画笔glowPaint = new Paint();glowPaint.setStrokeWidth(4);glowPaint.setStyle(Paint.Style.STROKE);glowPaint.setAntiAlias(true);glowPaint.setShadowLayer(15, 0, 0, Color.argb(150, 0, 255, 255));// 默认坐标轴大小xAxisSize = 800;yAxisSize = 400;// 启用硬件加速以获得更好的性能setLayerType(LAYER_TYPE_HARDWARE, null);}public void setAxisSize(float xAxisSize, float yAxisSize) {this.xAxisSize = xAxisSize;this.yAxisSize = yAxisSize;invalidate();}public void setGridDensity(int density) {this.gridDensity = density;invalidate();}public void setShowGrid(boolean show) {this.showGrid = show;invalidate();}public void setShowGlowEffect(boolean show) {this.showGlowEffect = show;invalidate();}public void addWaveData(String name, int color) {WaveData waveData = new WaveData(name, color);waveDataList.add(waveData);}public void addDataToWave(String name, float value) {for (WaveData waveData : waveDataList) {if (waveData.getName().equals(name)) {waveData.addData(value);if (waveData.getData().size() > maxDataPoints) {waveData.getData().remove(0);}break;}}invalidate();}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);// 绘制网格if (showGrid) {drawGrid(canvas);}// 绘制坐标轴drawAxis(canvas);// 绘制波形drawWaves(canvas);// 绘制图例drawLegend(canvas);// 绘制边框效果drawBorder(canvas);}private void drawGrid(Canvas canvas) {float startX = 50;float startY = getHeight() - 50;float endX = startX + xAxisSize;float endY = startY - yAxisSize;// 绘制水平网格线for (int i = 0; i <= gridDensity; i++) {float y = startY - (i * yAxisSize / gridDensity);canvas.drawLine(startX, y, endX, y, gridPaint);}// 绘制垂直网格线for (int i = 0; i <= gridDensity * 2; i++) {float x = startX + (i * xAxisSize / (gridDensity * 2));canvas.drawLine(x, startY, x, endY, gridPaint);}}private void drawAxis(Canvas canvas) {float startX = 50;float startY = getHeight() - 50;float endX = startX + xAxisSize;float endY = startY - yAxisSize;// 绘制X轴canvas.drawLine(startX, startY, endX, startY, axisPaint);// 绘制Y轴canvas.drawLine(startX, startY, startX, endY, axisPaint);// 绘制箭头drawArrow(canvas, endX, startY, endX + 15, startY); // X轴箭头drawArrow(canvas, startX, endY, startX, endY - 15); // Y轴箭头// 绘制刻度for (int i = 0; i <= 10; i++) {float x = startX + (i * xAxisSize / 10);canvas.drawLine(x, startY, x, startY - 8, axisPaint);canvas.drawText(String.valueOf(i), x, startY + 25, textPaint);}for (int i = 0; i <= 5; i++) {float y = startY - (i * yAxisSize / 5);canvas.drawLine(startX, y, startX + 8, y, axisPaint);canvas.drawText(String.valueOf(i), startX - 20, y + 10, textPaint);}// 绘制坐标轴标签canvas.drawText("时间 (s)", startX + xAxisSize / 2, startY + 50, textPaint);canvas.save();canvas.rotate(-90, startX - 40, startY - yAxisSize / 2);canvas.drawText("幅度 (V)", startX - 40, startY - yAxisSize / 2, textPaint);canvas.restore();}private void drawArrow(Canvas canvas, float x1, float y1, float x2, float y2) {canvas.drawLine(x1, y1, x2, y2, axisPaint);}private void drawWaves(Canvas canvas) {if (waveDataList.isEmpty()) return;float startX = 50;float startY = getHeight() - 50;float xStep = xAxisSize / (maxDataPoints - 1);for (WaveData waveData : waveDataList) {List<Float> data = waveData.getData();if (data.size() < 2) continue;// 绘制主波形线Paint mainPaint = new Paint();mainPaint.setColor(waveData.getColor());mainPaint.setStrokeWidth(3);mainPaint.setStyle(Paint.Style.STROKE);mainPaint.setAntiAlias(true);// 绘制发光效果if (showGlowEffect) {Paint glowPaint = new Paint();glowPaint.setColor(waveData.getColor());glowPaint.setStrokeWidth(5);glowPaint.setStyle(Paint.Style.STROKE);glowPaint.setAlpha(100);glowPaint.setAntiAlias(true);Path glowPath = new Path();glowPath.moveTo(startX, startY - (data.get(0) * yAxisSize / 5));for (int i = 1; i < data.size(); i++) {float x = startX + (i * xStep);float y = startY - (data.get(i) * yAxisSize / 5);glowPath.lineTo(x, y);}canvas.drawPath(glowPath, glowPaint);}// 绘制渐变填充效果Path fillPath = new Path();fillPath.moveTo(startX, startY);fillPath.lineTo(startX, startY - (data.get(0) * yAxisSize / 5));for (int i = 1; i < data.size(); i++) {float x = startX + (i * xStep);float y = startY - (data.get(i) * yAxisSize / 5);fillPath.lineTo(x, y);}fillPath.lineTo(startX + (data.size() - 1) * xStep, startY);fillPath.close();Paint fillPaint = new Paint();fillPaint.setStyle(Paint.Style.FILL);fillPaint.setShader(new LinearGradient(0, startY - yAxisSize,0, startY,Color.argb(80, Color.red(waveData.getColor()),Color.green(waveData.getColor()),Color.blue(waveData.getColor())),Color.argb(20, Color.red(waveData.getColor()),Color.green(waveData.getColor()),Color.blue(waveData.getColor())),Shader.TileMode.CLAMP));canvas.drawPath(fillPath, fillPaint);// 绘制主波形线Path mainPath = new Path();mainPath.moveTo(startX, startY - (data.get(0) * yAxisSize / 5));for (int i = 1; i < data.size(); i++) {float x = startX + (i * xStep);float y = startY - (data.get(i) * yAxisSize / 5);mainPath.lineTo(x, y);}canvas.drawPath(mainPath, mainPaint);// 绘制数据点(只在数据点较少时显示)if (data.size() < 50) {Paint pointPaint = new Paint();pointPaint.setColor(waveData.getColor());pointPaint.setStyle(Paint.Style.FILL);pointPaint.setAntiAlias(true);for (int i = 0; i < data.size(); i++) {float x = startX + (i * xStep);float y = startY - (data.get(i) * yAxisSize / 5);canvas.drawCircle(x, y, 4, pointPaint);canvas.drawCircle(x, y, 6, glowPaint);}}}}private void drawLegend(Canvas canvas) {float startX = 60 + xAxisSize;float startY = getHeight() - 50 - yAxisSize + 30;Paint legendBgPaint = new Paint();legendBgPaint.setColor(Color.argb(150, 0, 30, 60));legendBgPaint.setStyle(Paint.Style.FILL);legendBgPaint.setAntiAlias(true);// 绘制图例背景float legendWidth = 180;float legendHeight = waveDataList.size() * 40 + 20;canvas.drawRoundRect(startX - 10, startY - 10,startX + legendWidth, startY + legendHeight, 10, 10, legendBgPaint);for (int i = 0; i < waveDataList.size(); i++) {WaveData waveData = waveDataList.get(i);Paint rectPaint = new Paint();rectPaint.setColor(waveData.getColor());rectPaint.setStyle(Paint.Style.FILL);rectPaint.setAntiAlias(true);// 绘制图例颜色块canvas.drawRect(startX, startY + (i * 40),startX + 20, startY + (i * 40) + 20, rectPaint);// 绘制图例文字canvas.drawText(waveData.getName(), startX + 100, startY + (i * 40) + 15, textPaint);}}private void drawBorder(Canvas canvas) {Paint borderPaint = new Paint();borderPaint.setColor(Color.argb(100, 0, 255, 255));borderPaint.setStrokeWidth(2);borderPaint.setStyle(Paint.Style.STROKE);borderPaint.setAntiAlias(true);// 绘制外边框canvas.drawRect(5, 5, getWidth() - 5, getHeight() - 5, borderPaint);// 绘制内发光效果Paint innerGlowPaint = new Paint();innerGlowPaint.setColor(Color.argb(50, 0, 255, 255));innerGlowPaint.setStrokeWidth(1);innerGlowPaint.setStyle(Paint.Style.STROKE);innerGlowPaint.setAntiAlias(true);canvas.drawRect(8, 8, getWidth() - 8, getHeight() - 8, innerGlowPaint);}// 内部类,用于存储波形数据private static class WaveData {private String name;private int color;private List<Float> data;public WaveData(String name, int color) {this.name = name;this.color = color;this.data = new ArrayList<>();}public String getName() {return name;}public int getColor() {return color;}public List<Float> getData() {return data;}public void addData(float value) {data.add(value);}}
}

2.MainActivity.java源码

package com.example.wave;import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.view.WindowManager;
import android.widget.LinearLayout;import androidx.appcompat.app.AppCompatActivity;import java.util.Random;public class MainActivity extends AppCompatActivity {private WaveView waveView;private Handler handler;private Runnable updateRunnable;private int time = 0;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 全屏模式getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);setContentView(R.layout.activity_main);// 获取布局容器LinearLayout container = findViewById(R.id.container);// 创建WaveView实例waveView = new WaveView(this);// 设置科幻风格参数waveView.setShowGrid(true);waveView.setShowGlowEffect(true);waveView.setGridDensity(12);// 使用科幻风格的颜色int[] waveColors = {Color.argb(255, 0, 255, 255),   // 青色 - 科幻感Color.argb(255, 255, 0, 255),   // 洋红色 - 科幻感Color.argb(255, 0, 255, 0)      // 绿色 - 科幻感};// 设置波形图大小waveView.setAxisSize(1600, 500);// 添加波形数据系列waveView.addWaveData("正弦波", waveColors[0]);waveView.addWaveData("余弦波", waveColors[1]);waveView.addWaveData("噪声波", waveColors[2]);// 将WaveView添加到布局中container.addView(waveView);// 创建Handler用于定时更新handler = new Handler();updateRunnable = new Runnable() {@Overridepublic void run() {updateWaveData();handler.postDelayed(this, 1000); // 每秒更新一次}};}@Overrideprotected void onResume() {super.onResume();// 开始定时更新handler.post(updateRunnable);}@Overrideprotected void onPause() {super.onPause();// 停止定时更新handler.removeCallbacks(updateRunnable);}private void updateWaveData() {// 生成正弦波数据float sinValue = (float) Math.sin(time * 0.1);waveView.addDataToWave("正弦波", sinValue * 2 + 2.5f); // 调整幅度和偏移// 生成余弦波数据float cosValue = (float) Math.cos(time * 0.1);waveView.addDataToWave("余弦波", cosValue * 1.5f + 2.5f); // 调整幅度和偏移// 生成带噪声的数据Random random = new Random();float noiseValue = (float) (Math.sin(time * 0.1) + (random.nextFloat() - 0.5f));waveView.addDataToWave("噪声波", noiseValue + 2.5f); // 添加偏移time++;}
}

3.activity_main.xml源码

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:padding="16dp"><TextViewandroid:id="@+id/titleTextView"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="多波形显示"android:textSize="24sp"android:textStyle="bold"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent" /><LinearLayoutandroid:id="@+id/container"android:layout_width="0dp"android:layout_height="0dp"android:orientation="vertical"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toBottomOf="@+id/titleTextView" /></androidx.constraintlayout.widget.ConstraintLayout>

三、效果图

运行后,程序开始绘制3条曲线图。

http://www.dtcms.com/a/399005.html

相关文章:

  • seo网站设计费用网站过期会怎样解决
  • 网站机房建设目的温州机械网站建设
  • WLB公司内推|招联金融2026届校招|18薪
  • 平安产险深圳分公司在深圳莲花山公园 参与2025年金融教育宣传周启动仪式活动
  • 从root用户切换到某个普通用户突然报错“su: failed to execute /bin/bash: 资源暂时不可用”
  • 沧州网站建设制作设计优化浏览器提醒 WordPress
  • 网站风格什么意思快速优化系统
  • 陕西创程教育:点亮职业人生的明灯
  • AR智能巡检:工业培训的效率的革新
  • 栈实现队列方法与优化
  • 设计模式-建造者模式详解
  • 卫星产业全景图:从制造到应用的星辰大海
  • 青海西宁网站开发公司网站建设要哪些人?
  • (5)tauri 日志
  • 宿迁网站开发网站开发必备技能
  • 如何选择合适的服务器租用商?
  • 网站rar文件专业免费网站建设
  • MySQL在服务器和参数化方面的通用调优策略详解
  • PaddleOCR 本地部署与 MCP 服务调用指南(Mac Intel CPU)
  • 开源的自动化平台
  • python+django/flask哈利波特书影音互动科普网站
  • SRC-文件上传导致XSS
  • 襄阳做网站的用 net做网站
  • 中式建筑公司网站青岛装饰公司十强排名
  • CSS网页设计实战——车辆购物页面
  • PyTorch 神经网络模型构建与核心工具详解
  • PHP 线上环境 Composer 依赖包更新部署指南
  • SQLCipher数据库的引用、创建、打开
  • 【 设计模式 | 创建型模式 建造者模式 】
  • 飞虹网架建设官方网站网站建设类有哪些职位