心血来潮,想到去年独立开发的一个项目XX操盘,其中有关于个股的走势行情图是完全基于自定义view实现的,本文分析一下大致流程及部分实现代码;具体的自定义控件步骤想必大家比我还清楚的,不作详解
分时图
效果图如下(分时图暂未录制动图,闪电动图在最后哦~~~)
实现步骤:
1.自定义相关属性:attrs.xml中声明
<declare-styleable name="MinView">
<attr name="pathColor" format="reference|color"/>
<attr name="textDColor" format="reference|color"/>
<attr name="lineColorr" format="reference|color"/>
<attr name="fillPathColorr" format="reference|color"/>
<attr name="textSizz" format="dimension"/>
</declare-styleable>
2.布局中引用 com.domain.my.MinView
3.获取属性 constructor method
4.测量view设置大小
/**
* 根据测量模式得到view的宽和高
* @param widthMeasureSpec
* @param heightMeasureSpec
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
measuredWidth = getMeasuredWidth();
measuredHeight = getMeasuredHeight();
int widhtSpecMode = MeasureSpec.getMode(widthMeasureSpec);
int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
mChartLeftMargin = getLeft() + getPaddingLeft();
mChartRightMargin = getPaddingRight();
if (widhtSpecMode == MeasureSpec.EXACTLY) {
mViewWidth = measuredWidth - mChartRightMargin - mChartLeftMargin;//view的宽度
}
if (heightSpecMode == MeasureSpec.EXACTLY) {
mViewHeight = measuredHeight - getPaddingBottom() - getPaddingTop() - mTextHeight;//view的高度
mBottomTextTop = mChartHeight + mTextMargin;
}
}
5. 绘制onDraw(Canvas canvas)
//1,绘制view背景
canvas.drawRect(0, 0, measuredWidth, measuredHeight, mPaintBg);
//2,画坐标虚线
drawDashLine(canvas);
//3,画右侧文字
drawRText(canvas);
//4,绘制走势路径
if (futures != null && futures.size() > 0)
drawPath(canvas);
/**
* 画坐标横线
* @param canvas
*/
private void drawDashLine(Canvas canvas) {
startY = mTextMargin;
mPath.reset();
if (datas == null)
throw new RuntimeException("data is null");
for (int index = 0; index < mLineNum; index++) {
mPath.moveTo(0, startY);
mPath.lineTo(0 + mLineWidth, startY);
startY += mLineSpaceX;
}
canvas.drawPath(mPath, mAxisPaint);
}
/**
* 画右侧坐标上的文字,需注意初始化无数据默认为0.0
* @param canvas
*/
private void drawRText(Canvas canvas) {
startY = mTextMargin;
for (int index = 0; index < mLineNum; index++) {
if (datas == null)
break;
if (futures != null && futures.size() > 0)
canvas.drawText(datas.get(index), mChartWidth - mTextWidth, startY + mTextHeight / 2, mTextPaint);
else
canvas.drawText(datas.get(index), mChartWidth - mTextWidth, startY + mTextHeight / 2, mTextPaint);
startY += mLineSpaceX;
}
}
/**
* 走势图实现,通过path绘制数据路径
*/
private void drawPath(Canvas canvas) {
mPath1.reset();//重置路径,避免path数据过多消耗过多内存
mPath2.reset();
mLastX = 0;
mLastY = getActualY(futures.get(0).getCurrent());
mPath1.moveTo(mLastX, mLastY);
mPath2.moveTo(mLastX, mChartHeight);
mPath2.lineTo(mLastX, mLastY);
for (int i = 0; i < futures.size(); i++) {
toY = getActualY(futures.get(i).getCurrent());
mPath1.lineTo(mLastX, toY);
mPath2.lineTo(mLastX, toY);
mLastX = i * mAxisIndex;
}
canvas.drawPath(mPath1, mPathPaint);//明线路径
canvas.drawPath(mPath2, mFillPaint);//闭合区域与坐标轴的背景
}
以上就是绘制分时图的核心代码,其中关于使用到的行情数据不便提供,其他的有关画笔变量的初始化及自定义属性获取,控件的使用设置等都比较容易,可以自行体验。
需注意使用path在绘制大量数据的时候很容易内存泄露,导致绘制卡顿,处理方式代码中已给出,注意即可。
闪电图电流走动一般的效果
- 闪电图经
- 闪电图动图
闪电图的实现方式同分时图,就不上重复代码了,区别在于闪电走势到画布最后需要有动态的移位效果,用到了画布的canvas.translate(-translateX, 0);画布向左移动才有上图的效果,可自行学习实现。
END—-
K线图原理同上,与分时图不同,K线绘制的是一个个小矩形(包括底部交易量),后续可补上。