文章的目的为了记录使用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.效果图
一、代码分析
WaveView自定义View详细函数分析
- 构造函数和初始化
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像素,产生光晕效果
- 数据管理函数
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点)
自动触发界面更新
- 绘制函数详细分析
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; // 坐标原点X
float startY = getHeight() - 50; // 坐标原点Y
float 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; // 波形起始X
float 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);
}
}
- 辅助函数
配置函数族
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()触发界面更新。
- 性能优化特性
硬件加速:setLayerType(LAYER_TYPE_HARDWARE, null)
数据量控制:固定200个数据点,避免内存无限增长
条件绘制:数据点少于50时才绘制点状标记
路径绘制:使用Path而非多次drawLine提高效率
- 坐标系统总结
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();
}
@Override
protected 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;
@Override
protected 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() {
@Override
public void run() {
updateWaveData();
handler.postDelayed(this, 1000); // 每秒更新一次
}
};
}
@Override
protected void onResume() {
super.onResume();
// 开始定时更新
handler.post(updateRunnable);
}
@Override
protected 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">
<TextView
android: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" />
<LinearLayout
android: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条曲线图。
