版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
【移动应用开发技术】怎么在Android中通过自定义控件实现一个折线图
这篇文章给大家介绍怎么在Android中通过自定义控件实现一个折线图,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。Android是一种基于Linux内核的自由及开放源代码的操作系统,主要使用于移动设备,如智能手机和平板电脑,由美国Google公司和开放手机联盟领导及开发。首先是控件绘图区域的划分,控件左边取一小部分(控件总宽度的八分之一)绘制表头,右边剩余的部分绘制表格确定表格的行列数,首先绘制一个三行八列的网格,设置好行列的坐标后开始绘制/*绘制三条横线*/
for(int
i=0;i<3;i++){
canvas.drawLine(textWide,
mLineYs[i],
totalWidth,
mLineYs[i],
mPaintLine);
}
/*绘制八条竖线*/
for(int
i=0;i<8;i++){
canvas.drawLine(mLineXs[i],
0,
mLineXs[i],
totalHeight,
mPaintLine);
}网格绘制完成后,开始绘制折线图根据输入的节点数据,分别绘制两条折线通过canvas的drawLine方法依次连接两点即可在每个数据节点处绘制一个小圆,突出显示/*绘制第一条折线的路径*/
for
(int
i
=
0;
i
<
mPerformance_1.length
-
1;
i++)
{
/*折线图的折线的画笔设置粗一点*/
mPaintLine.setStrokeWidth(5);
/*计算当前节点的坐标值*/
float
prePointX
=mLineXs[i];
float
prePointY
=mLineYs[2]
-
(mLineYs[2]
-
mLineYs[mPerformance_1[i].type])
*
animCurrentValue;
/*计算下一个节点的坐标值*/
float
nextPointX=mLineXs[i
+
1];
float
nextPointY=mLineYs[2]
-
(mLineYs[2]
-
mLineYs[mPerformance_1[i
+
1].type])
*
animCurrentValue;
/*连接当前坐标和下一个坐标,绘制线段*/
canvas.drawLine(prePointX,
prePointY,
nextPointX,
nextPointY,
mPaintLine1);
/*当前节点坐标处绘制小圆*/
canvas.drawCircle(prePointX,
prePointY,
mSmallDotRadius,
mPointPaint);
}两条折线重合的地方,需要特殊考虑,比如希望两条折线重合的地方折线变为白色设置下两条折线的画笔即可mPaintLine2.setXfermode(new
PorterDuffXfermode(PorterDuff.Mode.SCREEN));
mPaintLine1.setXfermode(new
PorterDuffXfermode(PorterDuff.Mode.SCREEN));测试代码及效果;final
Random
random=new
Random();
final
LineChartView
myView=(LineChartView)findViewById(R.id.custom_view);
final
LineChartView.Performance[]
performances1=new
LineChartView.Performance[8];
final
LineChartView.Performance[]
performances2=new
LineChartView.Performance[8];
myView.setOnClickListener(new
View.OnClickListener(){
@Override
public
void
onClick(View
v){
for(int
i=0;i<performances1.length;i++){
switch
(random.nextInt(2016)%3){
case
0:
performances1[i]=
LineChartView.Performance.WIN;
break;
case
1:
performances1[i]=
LineChartView.Performance.DRAW;
break;
case
2:
performances1[i]=
LineChartView.Performance.LOSE;
break;
default:
performances1[i]=
LineChartView.Performance.LOSE;
break;
}
switch
(random.nextInt(2016)%3){
case
0:
performances2[i]=
LineChartView.Performance.WIN;
break;
case
1:
performances2[i]=
LineChartView.Performance.DRAW;
break;
case
2:
performances2[i]=
LineChartView.Performance.LOSE;
break;
default:
performances1[i]=
LineChartView.Performance.LOSE;
break;
}
}
myView.setPerformances(performances1,performances2);
}
});完整代码如下:public
class
LineChartView
extends
View
{
private
Context
context;
/*动画插值器*/
DecelerateInterpolator
mDecelerateInterpolator
=
new
DecelerateInterpolator();
/*动画刷新的次数*/
private
int
mDuration
=
10;
/*当前动画进度值*/
private
int
mCurrentTime
=
0;
private
Performance[]
mPerformance_1,
mPerformance_2;
/*两条折线的颜色*/
private
int
mLineColor1,
mLineColor2;
/*绘制表头文字画笔*/
private
Paint
mPaintText
=
new
Paint();
/*绘制表格的画笔*/
private
Paint
mPaintLine
=
new
Paint();
/*第一条折线的画笔*/
private
Paint
mPaintLine1
=new
Paint();
/*第二条折线的画笔*/
private
Paint
mPaintLine2
=new
Paint();
/*坐标点的小圆点画笔*/
private
Paint
mPointPaint
=
new
Paint();
private
float
mSmallDotRadius
=
4;
private
TypedValue
typedValue;
private
int
mPaintClolor;
/*Handler刷新界面产生动画效果*/
private
Handler
mHandler
=
new
Handler();
private
Runnable
mAnimation
=
new
Runnable()
{
@Override
public
void
run()
{
if
(mCurrentTime
<
mDuration)
{
mCurrentTime++;
LineChartView.this.invalidate();
}
}
};
public
LineChartView(Context
context)
{
super(context);
this.context=context;
init();
}
public
LineChartView(Context
context,
AttributeSet
attrs)
{
super(context,
attrs);
this.context=context;
init();
}
public
LineChartView(Context
context,
AttributeSet
attrs,
int
defStyleAttr)
{
super(context,
attrs,
defStyleAttr);
this.context=context;
init();
}
public
enum
Performance
{
WIN(0),
DRAW(1),
LOSE(2);
public
int
type;
Performance(int
type)
{
this.type
=
type;
}
}
public
void
setPerformances(Performance[]
performance1,
Performance[]
performance2)
{
if
(performance1
==
null)
{
performance1
=
new
Performance[0];
}
if
(performance2
==
null)
{
performance2
=
new
Performance[0];
}
mPerformance_1
=
Arrays.copyOf(performance1,
performance1.length
>
8
?
8
:
performance1.length);
mPerformance_2
=
Arrays.copyOf(performance2,
performance2.length
>
8
?
8
:
performance2.length);
if
(isShown())
{
mCurrentTime
=
0;
this.invalidate();
}
}
/**
*
设置折线1的颜色
*
*
@param
mLineColor1
*/
public
void
setLineColor1(int
mLineColor1)
{
this.mLineColor1
=
mLineColor1;
}
/**
*
设置折线2的颜色
*
*
@param
mLineColor2
*/
public
void
setLineColor2(int
mLineColor2)
{
this.mLineColor2
=
mLineColor2;
}
private
void
init()
{
mLineColor1=Color.BLUE;
mLineColor2
=
Color.GREEN;
typedValue=new
TypedValue();
context.getTheme().resolveAttribute(R.attr.title_bar,typedValue,true);
mPaintClolor
=getResources().getColor(typedValue.resourceId);
final
LineChartView.Performance[]
performances1=new
LineChartView.Performance[8];
final
LineChartView.Performance[]
performances2=new
LineChartView.Performance[8];
final
Random
random=new
Random();
for(int
i=0;i<performances1.length;i++){
switch
(random.nextInt(2016)%3){
case
0:
performances1[i]=
LineChartView.Performance.WIN;
break;
case
1:
performances1[i]=
LineChartView.Performance.DRAW;
break;
case
2:
performances1[i]=
LineChartView.Performance.LOSE;
break;
default:
performances1[i]=
LineChartView.Performance.LOSE;
break;
}
switch
(random.nextInt(2016)%3){
case
0:
performances2[i]=
LineChartView.Performance.WIN;
break;
case
1:
performances2[i]=
LineChartView.Performance.DRAW;
break;
case
2:
performances2[i]=
LineChartView.Performance.LOSE;
break;
default:
performances1[i]=
LineChartView.Performance.LOSE;
break;
}
}
setPerformances(performances1,performances2);
}
/**
*
@param
canvas
*/
@Override
protected
void
onDraw(Canvas
canvas)
{
super.onDraw(canvas);
/*获取控件总宽高*/
float
totalWidth
=
getWidth();
float
totalHeight
=
getHeight();
/*左边取总宽度的八分之一绘制表格头部*/
float
textWide
=
totalWidth
/
8;
/*左边留一点空白*/
float
left_offset
=
10;
/*折线图的总宽度等于控件的总宽度减去表头和留白*/
float
chartWide
=
totalWidth
-
textWide
-
left_offset;
/*一共三行,设置每一行的垂直坐标*/
float[]
mLineYs
=
new
float[]{totalHeight
/
8,
totalHeight
/
2,
totalHeight
*
7
/
8};
/*一共八列,设置每一列的水平坐标*/
float[]
mLineXs
=
new
float[]{
textWide
+
left_offset
+
chartWide
*
0
/
8,
textWide
+
left_offset
+
chartWide
*
1
/
8,
textWide
+
left_offset
+
chartWide
*
2
/
8,
textWide
+
left_offset
+
chartWide
*
3
/
8,
textWide
+
left_offset
+
chartWide
*
4
/
8,
textWide
+
left_offset
+
chartWide
*
5
/
8,
textWide
+
left_offset
+
chartWide
*
6
/
8,
textWide
+
left_offset
+
chartWide
*
7
/
8,
};
/*绘制表头文字*/
mPaintText.setStyle(Paint.Style.FILL);
mPaintText.setColor(mPaintClolor);
mPaintText.setAlpha(226);
mPaintText.setTextSize(28);
/*从中间开始绘制*/
mPaintText.setTextAlign(Paint.Align.CENTER);
/*测量文字大小,并计算偏移量*/
Paint.FontMetrics
fontMetrics
=
mPaintText.getFontMetrics();
float
textBaseLineOffset
=
(fontMetrics.bottom
-
fontMetrics.top)
/
2
-
fontMetrics.bottom;
canvas.drawText("胜场",
textWide
/
2,
mLineYs[0]
+
textBaseLineOffset,
mPaintText);
canvas.drawText("平局",
textWide
/
2,
mLineYs[1]
+
textBaseLineOffset,
mPaintText);
canvas.drawText("负场",
textWide
/
2,
mLineYs[2]
+
textBaseLineOffset,
mPaintText);
/*绘制表格画笔设置*/
mPaintLine.setStyle(Paint.Style.STROKE);
mPaintLine.setAntiAlias(true);
mPaintLine.setColor(mPaintClolor);
mPaintLine.setAlpha(80);
mPaintLine.setStrokeWidth(1);
/*开始绘制表格*/
/*绘制三条横线*/
for(int
i=0;i<3;i++){
canvas.drawLine(textWide,
mLineYs[i],
totalWidth,
mLineYs[i],
mPaintLine);
}
/*绘制八条竖线*/
for(int
i=0;i<8;i++){
canvas.drawLine(mLineXs[i],
0,
mLineXs[i],
totalHeight,
mPaintLine);
}
/*折线图画笔设置*/
mPaintLine1.setStyle(Paint.Style.STROKE);
/*设置透明度,取值范围为0~255,数值越小越透明,0表示完全透明*/
mPaintLine1.setAlpha(0);
mPaintLine1.setAntiAlias(true);
mPaintLine1.setColor(mLineColor1);
mPaintLine1.setStrokeWidth(5);
mPaintLine2.setStyle(Paint.Style.STROKE);
/*设置透明度,取值范围为0~255,数值越小越透明,0表示完全透明*/
mPaintLine2.setAlpha(0);
mPaintLine2.setAntiAlias(true);
mPaintLine2.setColor(mLineColor2);
mPaintLine2.setStrokeWidth(5);
if
(typedValue.resourceId==R.color.white){
/*PorterDuff.Mode.SCREEN
上下层都显示。*/
mPaintLine2.setXfermode(new
PorterDuffXfermode(PorterDuff.Mode.SCREEN));
mPaintLine1.setXfermode(new
PorterDuffXfermode(PorterDuff.Mode.SCREEN));
}else
{
/*PorterDuff.Mode.DARKEN
上下层都显示。变暗*/
mPaintLine2.setXfermode(new
PorterDuffXfermode(PorterDuff.Mode.DARKEN));
mPaintLine1.setXfermode(new
PorterDuffXfermode(PorterDuff.Mode.DARKEN));
}
/*画节点处的小圆点的画笔设置*/
mPointPaint.setStyle(Paint.Style.STROKE);
mPointPaint.setAntiAlias(true);
mPointPaint.setColor(mPaintClolor);
/*计算当前动画进度对应的数值*/
float
animCurrentValue
=
mDecelerateInterpolator.getInterpolation(1.0f
*
mCurrentTime
/
mDuration);
mPaintLine.setColor(mLineColor1);
/*绘制第一条折线的路径*/
for
(int
i
=
0;
i
<
mPerformance_1.length
-
1;
i++)
{
/*折线图的折线的画笔设置粗一点*/
mPaintLine.setStrokeWidth(5);
/*计算当前节点的坐标值*/
float
prePointX
=mLineXs[i];
float
prePointY
=mLineYs[2]
-
(mLineYs[2]
-
mLineYs[mPerformance_1[i].type])
*
animCurrentValue;
/*计算下一个节点的坐标值*/
float
nextPointX=mLineXs[i
+
1];
float
nextPointY=mLineYs[2]
-
(mLineYs[2]
-
mLineYs[mPerformance_1[i
+
1].type])
*
animCurrentValue;
/*连接当前坐标和下一个坐标,绘制线段*/
canvas.drawLine(prePointX,
prePointY,
nextPointX,
nextPointY,
mPaintLine1);
/*当前节点坐标处绘制小圆*/
canvas.drawCircle(prePointX,
prePointY,
mSmallDotRadius,
mPointPaint);
}
/*第一个折线图的最后一个节点的坐标*/
float
lastPointX=mLineXs[mPerformance_1.length
-
1];
float
lastPointY=
mLineYs[2]
-
(mLineYs[2]
-
mLineYs[mPerformance_1[mPerformance_1.length
-
1].type])
*
animCurrentValue;
/*绘制最后一个节点的外围小圆*/
canvas.drawCirc
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
评论
0/150
提交评论