版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
【移动应用开发技术】怎么在Android中绘制一个曲线图
这期内容当中在下将会给大家带来有关怎么在Android中绘制一个曲线图,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。使用方式//
初始化数据表格相关
with(mTableView)
{
//
配置坐标系
setupCoordinator("日",
"人",
/*这里是横坐标的值*/0f,
5f,
10f,
15f,
20f,
25f,
30f)
//
添加曲线,
确保纵坐标的数值位数相等
addWave(ContextCompat.getColor(this@MainActivity,
R.color.colorYellow),
false,
0f,
10f,
30f,
54f,
30f,
100f,
10f)
addWave(ContextCompat.getColor(this@MainActivity,
R.color.colorGreen),
false,
0f,
30f,
20f,
20f,
46f,
25f,
5f)
addWave(ContextCompat.getColor(this@MainActivity,
R.color.colorPink),
false,
0f,
30f,
20f,
50f,
46f,
30f,
30f)
addWave(Color.parseColor("#8596dee9"),
true,
0f,
15f,
10f,
10f,
40f,
20f,
5f)
}实现思路横坐标是固定的,纵坐标需要跟随曲线传入的数值去动态的调整绘制坐标轴:纵横交错的网格根据用户传入坐标数值去绘制坐标轴上的数值给X轴和Y轴添加单位信息根据用户传入的具体的数值绘制曲线(这里不采用Bezier,不容易精确的控制顶点的位置)绘制填充效果添加属性动画代码实现/**
*
Created
by
FrankChoo
on
2017/12/29.
*
Email:
frankchoochina@
*
Version:
1.0
*
Description:
表格自定义View
*/
public
class
TableView
extends
View
{
private
List<WaveConfigData>
mWaves;//
数值集合
//
坐标轴的数值
private
int
mCoordinateYCount
=
8;
private
float[]
mCoordinateXValues;//
外界传入
private
float[]
mCoordinateYValues;//
动态计算
//
坐标的单位
private
String
mXUnit;
private
String
mYUnit;
//
所有曲线中所有数据中的最大值
private
float
mGlobalMaxValue;//
用于确认是否需要调整坐标系
private
Paint
mCoordinatorPaint;
private
Paint
mTextPaint;
private
Paint
mWrapPaint;
//
坐标轴上描述性文字的空间大小
private
int
mTopUnitHeight;//
顶部Y轴单位高度
private
int
mBottomTextHeight;
private
int
mLeftTextWidth;
//
网格尺寸
private
int
mGridWidth,
mGridHeight;
private
float
mAnimProgress;
public
TableView(Context
context)
{
this(context,
null);
}
public
TableView(Context
context,
@Nullable
AttributeSet
attrs)
{
this(context,
attrs,
0);
}
public
TableView(Context
context,
@Nullable
AttributeSet
attrs,
int
defStyleAttr)
{
super(context,
attrs,
defStyleAttr);
init();
post(new
Runnable()
{
@Override
public
void
run()
{
showAnimator();
}
});
}
private
void
init()
{
//
初始化数据集合的容器
mWaves
=
new
ArrayList<>();
//
坐标系的单位
mBottomTextHeight
=
dp2px(40);//
X轴底部字体的高度
mLeftTextWidth
=
mBottomTextHeight;//
Y轴左边字体的宽度
mTopUnitHeight
=
dp2px(30);//
顶部Y轴的单位
//
初始化坐标轴Paint
mCoordinatorPaint
=
new
Paint(Paint.ANTI_ALIAS_FLAG
|
Paint.DITHER_FLAG);
mCoordinatorPaint.setColor(Color.LTGRAY);
//
初始化文本Paint
mTextPaint
=
new
Paint(Paint.ANTI_ALIAS_FLAG
|
Paint.DITHER_FLAG);
mTextPaint.setColor(Color.GRAY);
mTextPaint.setTextSize(sp2px(12));
//
初始化曲线Paint
mWrapPaint
=
new
Paint(Paint.ANTI_ALIAS_FLAG
|
Paint.DITHER_FLAG);
mWrapPaint.setPathEffect(new
CornerPathEffect(200f));
}
/**
*
配置坐标轴信息
*
*
@param
xUnit
X
轴的单位
*
@param
yUnit
Y
轴的单位
*
@param
coordinateXValues
X
坐标轴上的数值
*/
public
void
setupCoordinator(String
xUnit,
String
yUnit,
float...
coordinateXValues)
{
mXUnit
=
xUnit;
mYUnit
=
yUnit;
mCoordinateXValues
=
coordinateXValues;
}
/**
*
添加一条曲线,
确保与横坐标的数值对应
*
*
@param
color
*
@param
isCoverRegion
*
@param
values
*/
public
void
addWave(int
color,
boolean
isCoverRegion,
float...
values)
{
mWaves.add(new
WaveConfigData(color,
isCoverRegion,
values));
//
根据value的值去计算纵坐标的数值
float
maxValue
=
0;
for
(float
value
:
values)
{
maxValue
=
Math.max(maxValue,
value);
}
if
(maxValue
<
mGlobalMaxValue)
return;
mGlobalMaxValue
=
maxValue;
//
保证网格的数值都为
5
的倍数
float
gridValue
=
mGlobalMaxValue
/
(mCoordinateYCount
-
1);
if
(gridValue
%
5
!=
0)
{
gridValue
+=
5
-
(gridValue
%
5);
}
//
给纵坐标的数值赋值
mCoordinateYValues
=
new
float[mCoordinateYCount];
for
(int
i
=
0;
i
<
mCoordinateYCount;
i++)
{
mCoordinateYValues[i]
=
i
*
gridValue;
}
invalidate();
}
@Override
protected
void
onDraw(Canvas
canvas)
{
drawCoordinate(canvas);
drawWrap(canvas);
}
public
void
showAnimator()
{
ValueAnimator
animator
=
ValueAnimator.ofFloat(0f,
1f).setDuration(1000);
animator.addUpdateListener(new
ValueAnimator.AnimatorUpdateListener()
{
@Override
public
void
onAnimationUpdate(ValueAnimator
animation)
{
mAnimProgress
=
(float)
animation.getAnimatedValue();
invalidate();
}
});
animator.start();
}
/**
*
绘制坐标系
*/
private
void
drawCoordinate(Canvas
canvas)
{
Point
start
=
new
Point();
Point
stop
=
new
Point();
//
1.
绘制横轴线和纵坐标单位
int
xLineCount
=
mCoordinateYValues.length;
mGridHeight
=
(getHeight()
-
getPaddingTop()
-
getPaddingBottom()
-
mBottomTextHeight
-
mTopUnitHeight)
/
(xLineCount
-
1);
for
(int
i
=
0;
i
<
xLineCount;
i++)
{
start.x
=
getPaddingLeft()
+
mLeftTextWidth;
start.y
=
getHeight()
-
getPaddingBottom()
-
mBottomTextHeight
-
mGridHeight
*
i;
stop.x
=
getRight()
-
getPaddingRight();
stop.y
=
start.y;
//
绘制横轴线
canvas.drawLine(start.x,
start.y,
stop.x,
stop.y,
mCoordinatorPaint);
//
绘制纵坐标单位
if
(i
==
0)
continue;
String
drawText
=
String.valueOf((int)
mCoordinateYValues[i]);
Paint.FontMetricsInt
fontMetrics
=
mTextPaint.getFontMetricsInt();
float
offsetY
=
((fontMetrics.bottom
-
fontMetrics.top)
/
2
+
fontMetrics.bottom)
/
2;
float
baseLine
=
start.y
+
offsetY;
float
left
=
getPaddingLeft()
+
mLeftTextWidth
/
2
-
mTextPaint.measureText(drawText)
/
2;
canvas.drawText(drawText,
left,
baseLine,
mTextPaint);
//
绘制Y轴单位
if
(i
==
xLineCount
-
1)
{
drawText
=
mYUnit;
baseLine
=
getPaddingTop()
+
mTopUnitHeight
/
2;
canvas.drawText(drawText,
left,
baseLine,
mTextPaint);
}
}
//
2.
绘制纵轴线和横坐标单位
int
yLineCount
=
mCoordinateXValues.length;
mGridWidth
=
(getWidth()
-
getPaddingLeft()
-
getPaddingRight()
-
mLeftTextWidth)
/
(yLineCount
-
1);
for
(int
i
=
0;
i
<
yLineCount;
i++)
{
start.x
=
getPaddingTop()
+
mLeftTextWidth
+
mGridWidth
*
i;
start.y
=
getPaddingTop()
+
mTopUnitHeight;
stop.x
=
start.x;
stop.y
=
getHeight()
-
mBottomTextHeight
-
getPaddingBottom();
//
绘制纵轴线
canvas.drawLine(start.x,
start.y,
stop.x,
stop.y,
mCoordinatorPaint);
//
绘制横坐标单位
String
drawText
=
String.valueOf((int)
mCoordinateXValues[i]);
Paint.FontMetricsInt
fontMetrics
=
mTextPaint.getFontMetricsInt();
float
offsetY
=
((fontMetrics.bottom
-
fontMetrics.top)
/
2
+
fontMetrics.bottom)
/
2;
float
baseLine
=
getHeight()
-
getPaddingBottom()
-
mBottomTextHeight
/
2
+
offsetY;
float
left
=
start.x
-
mTextPaint.measureText(drawText)
/
2;
//
绘制X轴单位
if
(i
==
0)
{
drawText
=
mXUnit;
left
=
getPaddingLeft()
+
mLeftTextWidth
/
2
-
mTextPaint.measureText(drawText)
/
2;
}
canvas.drawText(drawText,
left,
baseLine,
mTextPaint);
}
}
/**
*
绘制曲线
*/
private
void
drawWrap(Canvas
canvas)
{
canvas.clipRect(new
RectF(
mLeftTextWidth,
getPaddingTop()
+
mTopUnitHeight,
(getRight()
-
getPaddingRight())
*
mAnimProgress,
getHeight()
-
getPaddingBottom()
-
mBottomTextHeight)
);
float
yHeight
=
mGridHeight
*
(mCoordinateYCount
-
1);
for
(WaveConfigData
wave
:
mWaves)
{
Path
path
=
new
Path();
path.moveTo(0,
getHeight());
float
maxY
=
mCoordinateYValues[mCoordinateYCount
-
1];//
Y轴坐标的最大值
for
(int
index
=
1;
index
<
wave.values.length;
index++)
{
path.lineTo(
mLeftTextWidth
+
mGridWidth
*
index,
getHeight()
-
getPaddingBottom()
-
mBottomTextHeight
-
yHeight
*
(wave.values[index]
/
maxY)
);
}
if
(wave.isCoverRegion)
{
mWrapPaint.setStyle(Paint.Style.FILL);
path.lineTo(getRight(
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年古色古香游合同
- 2025年作品著作权使用许可协议
- 2025年度木工工艺研发与推广分包合同4篇
- 二零二五版房屋装修设计、施工及监理合同2篇
- 2025年中国连锁经营行业市场深度调查评估及投资方向研究报告
- 二零二五版离婚协议书针对存款账户的专项管理协议3篇
- 2025年度私人借款与信用评估机构合作协议
- 2025年度二零二五年度车牌借用与保险理赔合作协议
- 2025年度航空行业竞业协议敬业精神承诺合同
- 二零二五年度网约车平台车主与驾驶员合作协议书
- 教师招聘(教育理论基础)考试题库(含答案)
- 2024年秋季学期学校办公室工作总结
- 铺大棚膜合同模板
- 长亭送别完整版本
- 智能养老院视频监控技术方案
- 你比我猜题库课件
- 无人驾驶航空器安全操作理论复习测试附答案
- 建筑工地春节留守人员安全技术交底
- 默纳克-NICE1000技术交流-V1.0
- 蝴蝶兰的简介
- 老年人心理健康量表(含评分)
评论
0/150
提交评论