股票图基本知识
了解股票图如何绘制,首先应该了解股票图的业务逻辑是怎样的,这篇文章是仿雪球股票写的,建议大家下载雪球股票软件体验一下.在写这个股票图之前,我对股票是一无所知(原谅我穷买不起股票),
所以花了一点时间了解了一下股票图的基本信息,如果知道股票图是如何解读的,可以跳过这节.
股票图的种类特别多,不同的种类的股票图也不一样,例如股票有港股,美股,上证,深圳,创业板等等.然后上证又有:分时,日K,月K等等.
复杂程度完全可以直接绕晕人,没错,我就是看不懂所以不敢买.
股票图的种类之多,本文也没有一一编写,这里主要是仿照了雪球股票之上证指数的:分时图,以及日K图.
也就是股票的两大图种:分时图,以及蜡烛图.
分时图
分时图有股票当天的涨跌情况,以及一些最高点,最低点,比分比,
长按分时图,可以定位当时手指按下的时间所对应的股票点是多少点,并且可以左右滑动
股票的开盘时间是早上09:30-11:30,下午是13:00-15:00.
蜡烛图
蜡烛图和分时图类似,先除去那三条折线.分时图是把涨跌情况用折线表示,而蜡烛图是用一个矩形加一条竖线表示,和一根蜡烛一样,所以形象的称它为蜡烛图,
其中竖线的最高点代表当日最高涨到了多少点,最低表示最低跌到了多少点.
矩形的顶端,表示当日开盘是多少点,底端,表示收盘是多少点.
颜色红,代表收盘后,相对于昨天,涨了,颜色绿,则表示跌了.
三条折线分别代表了MA线,MA是“移动平均线”的简称,后面的数字:5、10、20…..是时间周期。MA5即5天收盘股票的平均点,其他的类推.博主这个例子没有实现MA线,作为大家的补充练手
日K图每个月一个间隔.
下面就分时图,蜡烛图,分别讲解其布局,绘制,触摸反馈
分时图布局
布局无论是xml引用layout编写,亦或是java直接new出来,或者是使用canvas直接绘制,最重要的不是应该使用
RelativeLayout还是LinearLayout,而是应该剖析它的层次与结构.
层次
根据上面的基本介绍,分时图的可以分为以下几个层次:
第1层:横线,竖线,以及底部时间(底部时间没有其他的元素,可以处于任意一层)
第2层:折线,以及阴影部分
第3层:文字,包括最高点,最低点,百分比分时图的结构相对简单,在基本介绍上已经说明其基本信息.
股票的开盘时间是早上09:30-11:30,下午是13:00-15:00,所以其分上午,下午两部分.
中间的虚线是昨天收盘的股票点,以此为基准线,计算折线图的位置.
绘制
布局分析好之后,就开始绘制这些基本信息.普通View的绘制,是写好xml或者java代码,然后交给每个view自己绘制,这里我们自己控制其绘制.
绘制的步骤,其实就是布局中所说的层次,绘制的规则,则是布局中的结构.换句话说,这个结构,规则,就是数学中的公式,步骤就是我们解题的思路.
详细绘制步骤开始.
自定义一个View,覆写其四个构造方法(注意最好四个构造方法都覆写,这样就可以通过多种途径新建这个View),覆写onDraw()方法,画图的时候就是在这个方法进行绘制的.
publicclassKLineViewextendsView{
publicKLineView(Context context){
super(context);
init();
}
publicKLineView(Context context, AttributeSet attrs){
super(context, attrs);
init();
}
publicKLineView(Context context, AttributeSet attrs, intdefStyleAttr){
super(context, attrs, defStyleAttr);
init();
}
@Re(api = Build.VERSION_CODES.LOLLIPOP)
publicKLineView(Context context, AttributeSet attrs, intdefStyleAttr, intdefStyleRes){
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
@Override
protectedvoidonDraw(Canvas canvas){
super.onDraw(canvas);
}
}
一般还需要初始化一些信息.为了让自己能看到每一步的绘制效果,编写一个添加测试数据方法,初始化的时候执行该方法即可.
/**
* canvas paint
*/
privatePaint mPaint;
privatevoidinit(){
mPaint = newPaint();
createTestData();
}
/**
* create the test data
*/
privatevoidcreateTestData(){
baseData = 3120.50f;
try{
times = newArrayList();
prices = newArrayList();
@SuppressLint( "SimpleDateFormat") SimpleDateFormat dateFormat = newSimpleDateFormat
( "yyyy-MM-dd HH:mm:ss");
Date date = dateFormat.parse( "2017-01-01 09:30:00");
for( inti = 0; i
if(i == 120) {
date = dateFormat.parse( "2017-01-01 13:00:00");
}
date.setTime(date.getTime() + 60* 1000);
times.add(formatTime(dateFormat.format(date)));
floattmp;
if(i == 0) tmp = ( float) (baseData + 5- Math.random() * 10);
elsetmp = ( float) (prices.get(i - 1) + 5- Math.random() * 10);
tmp = formatPrice(tmp);
if(tmp > maxPrice) {
maxPrice = tmp;
}
if(tmp
minPrice = tmp;
}
prices.add(tmp);
}
// for (String str : times) {
// Log.e("time", str);
// }
// for (Float item : prices) {
// Log.e("time", item + "");
// }
} catch(ParseException e) {
e.printStackTrace();
}
}
绘制线.
使用MarkMan量取,分时图在720*1280分辨率下,高度是是410,则我们可以把其高度分成410份.
它一共有5条横线,从上到下,每条线距离顶部的距离依次为:10,30,190,360,380.其中第3条为虚线.还有一条竖线,水平居中.
依次画出每一条线.
@Override
protectedvoidonDraw(Canvas canvas){
super.onDraw(canvas);
intviewHeight = getHeight();
intviewWidth = getWidth();
floatitem = viewHeight / 410f;
/**
* draw lines
*/
drawLines(canvas, viewWidth, item);
}
/**
* draw lines
*
from top to bottom, it have 5 horizontal lines,
*
1 vertical line in the horizontal center.
*
*
* @paramcanvas canvas
* @paramviewWidth the view's width
* @paramitem the view's height pided into 410
*/
privatevoiddrawLines(Canvas canvas, intviewWidth, floatitem){
mPaint.setColor(Color.parseColor( "#AAAAAA"));
mPaint.setStrokeWidth( 0f);
canvas.drawLine( 0, item * 10, viewWidth, item * 10, mPaint);
canvas.drawLine( 0, item * 30, viewWidth, item * 30, mPaint);
drawDashEffect(canvas, 0, item * 190, viewWidth, item * 190);
canvas.drawLine( 0, item * 360, viewWidth, item * 360, mPaint);
canvas.drawLine( 0, item * 380, viewWidth, item * 380, mPaint);
canvas.drawLine(viewWidth / 2.0f, item * 10, viewWidth / 2.0f, item * 380, mPaint);
}
/**
* draw a doted line
*
* @paramcanvas canvas
* @paramx startX
* @paramy startY
* @paramendX endX
* @paramendY endY
*/
privatevoiddrawDashEffect(Canvas canvas, floatx, floaty, floatendX, floatendY){
PathEffect effects = newDashPathEffect( newfloat[]{ 8, 8, 8, 8}, 1);
Paint p = newPaint(Paint.ANTI_ALIAS_FLAG);
p.setColor(Color.parseColor( "#AAAAAA"));
p.setPathEffect(effects);
p.setStyle(Paint.Style.STROKE);
Path path = newPath();
path.moveTo(x, y);
path.lineTo(endX, endY);
canvas.drawPath(path, p);
}
绘制时间.
时间的最简单,三个时间是固定的,位置也是固定的.
需要注意的是,绘制文字的x,y坐标,x=文字的左边,y=文字的baseline,文字的baseline默认等于-mPaint.getFontMetrics().top
想了解更多关于文字绘制的细节,请移步到这篇文章StyleTextView
@Override
protectedvoidonDraw(Canvas canvas){
super.onDraw(canvas);
intviewHeight = getHeight();
intviewWidth = getWidth();
floatitem = viewHeight / 410f;
/**
* draw time
*/
drawTimes(canvas, viewWidth, item);
}
/**
* draw times
*
* draw text method:
*
params: 1:content, 2:x, 3: the baseline
*
Note:the baseline == -mPaint.getFontMetrics().top in default
*
More information, please
* click this
*
* @paramcanvas canvas
* @paramviewWidth view's width
* @paramitem the view's height pided into 410
*/
privatevoiddrawTimes(Canvas canvas, intviewWidth, floatitem){
mPaint.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8f,
getResources().getDisplayMetrics()));
mPaint.setColor(Color.parseColor( "#999999"));
floattextWidth = mPaint.measureText( "09:30");
canvas.drawText( "09:30", item * 10, -mPaint.getFontMetrics().top + item * 380, mPaint);
canvas.drawText( "11:30", viewWidth / 2.0f- textWidth / 2.0f, -mPaint.getFontMetrics()
.top + item * 380, mPaint);
canvas.drawText( "15:00", viewWidth - textWidth - item * 10, -mPaint.getFontMetrics().top
+ item * 380, mPaint);
}
绘制折线,以及折线的阴影面积.
转到canvas上来说,其实就是绘制路径,在前面绘制横线的时候,绘制虚线其实就是绘制路径.
注意绘制阴影的时候,要把画笔设置为实心的,这样才会有阴影的效果,同时路径path要多连接几个点,包括右下角,左下角,表明折线下方,第五条横线上方,就是阴影部分.
@Override
protectedvoidonDraw(Canvas canvas){
super.onDraw(canvas);
intviewHeight = getHeight();
intviewWidth = getWidth();
floatitem = viewHeight / 410f;
/**
* draw broken line and shadow graph
*/
drawBrokenLine(canvas, viewWidth, item, "#504F76DB", Paint.Style.FILL);
drawBrokenLine(canvas, viewWidth, item, "#4F76DB", Paint.Style.STROKE);
}
/**
* draw broken line
*
* @paramcanvas canvas
* @paramviewWidth view's width
* @paramitem the view's height pided into 410
* @paramcolor paint color
* @paramstyle paint style,FILL: draw shadow, STROKE:draw line
*/
privatevoiddrawBrokenLine(Canvas canvas, intviewWidth, floatitem, String color, Paint
.Style style){
Path path = newPath();
Paint paint = newPaint();
floatxItem = viewWidth / 2.0f/ 120f;
// get biggest difference value, it will be calculated proportion
floatyCount = maxPrice - baseData > baseData - minPrice ? maxPrice - baseData : baseData
- minPrice;
//get one item height
floatyItem = 330* item / yCount / 2.0f;
//set path start point,item * 195 is baseData's y point.
path.moveTo( 0, item * 195);
//set other points
for( inti = 0; i
path.lineTo(xItem * (i + 1), item * 195+ yItem * (baseData - prices.get(i)));
}
//if draw shadow, we should add 3 points to draw a complete graphics.
//if draw lines, we should let lines bold.
if(Paint.Style.FILL == style) {
path.lineTo(viewWidth, item * 380);
path.lineTo( 0, item * 380);
path.lineTo( 0, item * 195);
path.close();
} else{
paint.setStrokeWidth( 2f);
}
paint.setColor(Color.parseColor(color));
paint.setAntiAlias( true);
paint.setStyle(style);
canvas.drawPath(path, paint);
}
绘制最高点,最低点,以及百分比.
有了绘制时间的经验,我们知道x,y分别代表的是文字的左下角,baseline,直接绘制即可.
绘制最低点的时候需要注意,最低点距离第四条横线的距离,应该与第二条线距离最高点的距离一致.放大雪球股票的图,发现其K线图,以及后面要绘制的蜡烛图,这
两个距离都不相等,虽然无伤大雅.但是如果我们能做到,那就更好不过.
设计或者产品出来一个交互,一个需求,你做不到,没什么关系,因为别人也做不到.但是假设别人做不到,但是你做到了,那么很明显,你就强于别人
在前面绘制文字的时候提到过这篇文章StyleTextView,发布到郭霖的公众号后,有部分同学说,为什么这么麻烦搞这么多,感觉不需要这么复杂.
实际上如果只是单纯做一个需求,确实不需要多复杂的代码,直接绘制是最简单的,但是绘制也涉及到留白的问题,在一个要求不是特别精确的View,一两个像素的差距,确实可有可无,甚至有同学直接根据
实际运行出来的效果图,调整空白大小.
但是你为什么调整空白大小,为什么要这么调,调了以后其他的机型适配吗?如果在一个很大的View上,字体大小很大,此时能保证也能满足正常视觉吗?
故有时候追求一些细节,对自己的代码,以及技术,都是一种负责任的态度.
@Override
protectedvoidonDraw(Canvas canvas){
super.onDraw(canvas);
intviewHeight = getHeight();
intviewWidth = getWidth();
floatitem = viewHeight / 410f;
/**
* draw max, min price and percent
*/
drawPriceAndPercent(canvas, viewWidth, item);
}
/**
* draw price and percent
*
* draw text method:
*
params: 1:content, 2:x, 3: the baseline
*
Note:the baseline == -mPaint.getFontMetrics().top in default
*
More information, please
* click this
*
* @paramcanvas canvas
* @paramviewWidth view's width
* @paramitem the view's height pided into 410
*/
privatevoiddrawPriceAndPercent(Canvas canvas, intviewWidth, floatitem){
// get biggest difference value, it will be calculated proportion
floatyCount = maxPrice - baseData > baseData - minPrice ? maxPrice - baseData : baseData
- minPrice;
mPaint.setStrokeWidth( 2f);
mPaint.setColor(Color.RED);
//draw max price
canvas.drawText(yCount + baseData + "", item * 10, -mPaint.getFontMetrics().top + item *
30, mPaint);
String percentStr = formatPrice(yCount * 100/ baseData) + "%";
floattextWidth = mPaint.measureText(percentStr);
//draw max percent
canvas.drawText(percentStr, viewWidth - textWidth - item * 10, -mPaint.getFontMetrics()
.top + item * 30, mPaint);
mPaint.setColor(Color.parseColor( "#008000"));
//draw min price
canvas.drawText(baseData - yCount + "", item * 10, item * 360- (mPaint.getFontMetrics()
.descent - mPaint.getFontMetrics().ascent - mPaint.getTextSize() + mPaint
.getFontMetrics().ascent - mPaint.getFontMetrics().top), mPaint);
percentStr = "-"+ percentStr;
textWidth = mPaint.measureText(percentStr);
//draw min percent
canvas.drawText(percentStr, viewWidth - textWidth - item * 10, item * 360- (mPaint
.getFontMetrics().descent - mPaint.getFontMetrics().ascent -
mPaint.getTextSize() + mPaint.getFontMetrics().ascent - mPaint.getFontMetrics()
.top), mPaint);
}
至此,绘制基本已经结束了,直接运行,就能看到一个基本K线图,但是还差K线图的交互,也就是长按K线图的交互,这其实就是一个触摸反馈的过程
触摸
网上有很多的触摸文章教程,这里就不展开篇幅讲解了,这里直接使用手势识别类:GestureDetector
但是实际使用发现,假设手指长按了,就不能再接收到
手指的移动事件,看GestureDetector发现,如果它判断是长按就直接break了,同时发现它也没有发送手指离开屏幕的事件,这都不是我想要的,所以我就把它源码直接复制出来了,删掉了一些用不到的事件,并
添加了手指离开事件.第二个手指按下,离开事件.
booleanonDown2(MotionEvent e);
booleanonUp2(MotionEvent e);
booleanonUp(MotionEvent e);
添加手势触摸监听,首先在init初始化GestureDetector,并在onTouch中拦截触摸事件
篇幅所限,代码略。
分时图总结
至此,分时图的布局,绘制,触摸反馈都已经完整,如果再加上设置数据的方法,就可以作为一个基本的分时图使用了.
蜡烛图布局层次
第1层:横竖刻度线
第2层:股票点,时间
第3层:蜡烛,以及MA线(MA其实就是绘制折线,这个Demo中没有绘制)蜡烛图的结构相对复杂,首先是,数据是从右往左的呈现的,最右边是最新的数据,越往左时间越久.
其次,蜡烛图没有昨天收盘的时候的股票点,也就是它没有基准线,它的涨跌情况都是与前一天对比.所有它的刻度范围是不固定的,需要根据
当前呈现的数据,动态计算它的最高点和最低点
绘制开始
创建类,并初始化,并构建测试数据方便调试
篇幅所限,代码略。
绘制横竖线,并绘制刻度,时间
蜡烛图的高度与分时图一致,总体高度410,第1条线距离顶部是10,View可绘制高度是370.
在绘制刻度之前,要先计算出当前展示的数据的最小值,最大值,以及刻度的比例,才能根据比例来绘制刻度.
/**
* calculate min and max y,the scale y.
*/
privatevoidgetYData(){
//计算最大值与最小值
maxPrice = 0;
minPrice = Float.MAX_VALUE;
for( inti = startIndex; i
if(candles.get(i).start > maxPrice) maxPrice = candles.get(i).start;
if(candles.get(i).start
if(candles.get(i).end > maxPrice) maxPrice = candles.get(i).end;
if(candles.get(i).end
if(candles.get(i).max > maxPrice) maxPrice = candles.get(i).max;
if(candles.get(i).max
if(candles.get(i).min > maxPrice) maxPrice = candles.get(i).min;
if(candles.get(i).min
}
//根据最大值最小值的,来计算刻度的最高点,最低点
yScale = 1;
intdiff = ( int) (maxPrice - minPrice);
if(diff / 100000>= 1) {
yScale = 100000;
minY = ( int) minPrice / 100000* 100000;
maxY = (( int) maxPrice / 100000+ 1) * 100000;
} elseif(diff / 10000>= 1) {
yScale = 10000;
minY = ( int) minPrice / 10000* 10000;
maxY = (( int) maxPrice / 10000+ 1) * 10000;
} elseif(diff / 1000>= 1) {
yScale = 1000;
minY = ( int) minPrice / 1000* 1000;
maxY = (( int) maxPrice / 1000+ 1) * 1000;
} elseif(diff / 100>= 1) {
yScale = 100;
minY = ( int) minPrice / 100* 100;
maxY = (( int) maxPrice / 100+ 1) * 100;
} elseif(diff / 10>= 1) {
yScale = 10;
minY = ( int) minPrice / 10* 10;
maxY = (( int) maxPrice / 10+ 1) * 10;
}
Log.e( "siyehua", maxPrice + " "+ minPrice + " "+ maxY + " "+ minY + " "+
yScale + " "+ " ");
}
计算好Y轴刻度后,则开始绘制
@Override
protectedvoidonDraw(Canvas canvas){
super.onDraw(canvas);
intviewHeight = getHeight();
intviewWidth = getWidth();
floatitemW = ( float) viewWidth / count;
floatitemH = viewHeight / 410f;
drawLinesAndText(canvas, viewWidth, viewHeight, itemW, itemH);
}
/**
* draw lines and text
*
* @paramcanvas canvas
* @paramviewWidth the view's width
* @paramviewHeight the view's height
* @paramitemW the view's wight pided into count
* @paramitemH the view's height pided into 410
*/
privatevoiddrawLinesAndText(Canvas canvas, intviewWidth, intviewHeight, floatitemW,
floatitemH){
mPaint.setColor(Color.parseColor( "#AAAAAA"));
mPaint.setStrokeWidth( 0f);
mPaint.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8f,
getResources().getDisplayMetrics()));
/**
* draw x lines and price text
*/
getYData();
intlineCount = (maxY - minY) / yScale;
if(lineCount > 5) { //假设线条超过5条,则把刻度大小翻倍
yScale *= 2;
lineCount = (maxY - minY) / yScale;
}
//draw first line
canvas.drawLine( 0, itemH * 10, viewWidth, itemH * 10, mPaint);
floatpercent = 370/ ( float) lineCount;
for( inti = 1; i
//draw prices
String content = minY + (lineCount - i) * yScale + "";
canvas.drawText(content, itemH * 10, itemH * ( 10+ percent * i) - mPaint
.getFontMetrics().bottom, mPaint);
//draw middle lines
canvas.drawLine( 0, itemH * ( 10+ percent * i), viewWidth, itemH * ( 10+ percent * i),
mPaint);
}
//draw last line
canvas.drawLine( 0, itemH * 380, viewWidth, itemH * 380, mPaint);
/**
* draw y lines and time
*/
String tmpMonth = candles.get(startIndex).time.substring( 5, 7);
for( inti = startIndex + 1; i
//假设明天的时间与今天不一样,说明一个月的间隔到了,则绘制一条竖线
if(!tmpMonth.equals(candles.get(i + 1).time.substring( 5, 7))) {
tmpMonth = candles.get(i + 1).time.substring( 5, 7);
String timeStr = candles.get(i).time.substring( 0, 7);
//注意数据是从右到左呈现的,所有要从右边开始计算坐标
floattmp = itemW * (count + startIndex - i) - itemW / 2;
//draw times
floattimeWidth = mPaint.measureText(timeStr);
canvas.drawText(timeStr, tmp - timeWidth / 2, itemH * 380+ -mPaint
.getFontMetrics().top, mPaint);
//draw liens
canvas.drawLine(tmp, itemH * 10, tmp, itemH * 380, mPaint);
}
}
}
绘制蜡烛
绘制好线与文字,就可以绘制蜡烛了.蜡烛图在View的视觉上占了很大的份量,但是绘制的时候,实际上很简单,当刻度计算好后,只需要绘制一条线,以及一个实心的矩形即可.
篇幅所限,代码略。
绘制其他元素
雪球股票的蜡烛图,还有三条折线,以及左上角的文字提示.这些在分时图已经讲解了如何绘制了,只需要依样画葫芦即可.
因为蜡烛图的复杂不在于它的绘制,而在于它的触摸反馈,所以这里把更多的精力花在触摸反馈的处理上.
触摸初始化触摸类
篇幅所限,代码略。
单根手指触摸/**
* show touch line
*/
privatevoidshowTouchLine(floattouchX){
floatitemX = ( float) getWidth() / count;
if(longPressFlag) { //长按,与分时图一个效果,先获取触摸的index,再刷新界面
for( inti = 1; i = touchX) {
touchIndex = i + 1;
break;
}
}
if(touchMoveListener != null&& touchIndex >= 0) {
touchMoveListener.change(candles.get(count + startIndex - touchIndex).time
.substring( 0, 10), candles.get(count + startIndex - touchIndex).end + "",
formatPrice((candles.get(count + startIndex - touchIndex).end - candles
.get(count + startIndex - touchIndex + 1).end) / candles.get
(count + startIndex - touchIndex + 1).end * 100) + "%", "4613"+
".93万");
}
} else{ //左右滑动,左右滑动,View不需要滑动,只需要修改startIndex的值,即达到滑动的效果
intnumber = ( int) ((touchX - downX) / itemX);
// Log.e("number", number + "");
startIndex = downIndex + number;
if(startIndex
if(startIndex > candles.size() - count - 1) startIndex = candles.size() - count - 1;
}
postInvalidate();
}
/**
* draw lines and text
*
* @paramcanvas canvas
* @paramviewWidth the view's width
* @paramviewHeight the view's height
* @paramitemW the view's wight pided into count
* @paramitemH the view's height pided into 410
*/
privatevoiddrawTouchLines(Canvas canvas, intviewWidth, intviewHeight, floatitemW, float
itemH){
if(longPressFlag) { //长按
floatx = itemW * touchIndex - itemW / 2;
floaty;
floata = ((maxY - candles.get(count + startIndex - touchIndex).start) / (maxY -
minY) * 370+ 10) * itemH;
floatb = ((maxY - candles.get(count + startIndex - touchIndex).end) / (maxY - minY)
* 370+ 10) * itemH;
if(candles.get(count + startIndex - touchIndex).end
- touchIndex + 1).end) {
y = a > b ? a : b;
} elsey = a
//draw the lines
mPaint.setColor(Color.parseColor( "#999999"));
canvas.drawLine( 0, y, viewWidth, y, mPaint);
canvas.drawLine(x, itemH * 10, x, itemH * 380, mPaint);
//draw the point
// mPaint.setColor(Color.parseColor("#FFC125"));
// mPaint.setStrokeWidth(10f);
// canvas.drawPoint(x, y, mPaint);
}
}
多根手指缩放
屏幕默认分为60根蜡烛,缩放后,只需要修改默认的蜡烛数目即可.
privatevoidscaleCandle(floatmoveDistance){
if(moveDistance > getWidth() / 30) {
if(count == 20) count = 10;
elseif(count == 10) return;
elsecount -= 20;
} elseif(moveDistance
if(count == 240) return;
elsecount += 20;
}
postInvalidate();
}
蜡烛图总结
蜡烛图的需求,功能基本上已经实现,除了三条折线没有绘制.只需要再添加设置数据方法,该类便可直接使用.
总结
本文从布局,绘制,触摸,三个方面讲解了分时图,蜡烛图的一步步实现过程.其实股票图的业务上还有很多是没有讲解到的,例如大家应该都有注意到截图中
下面有柱状图,其实这个应该也是图的一部分,还有一些高亮显示等问题.
但其实基本的原理都是不变的,一个View的三个方面都有详细的讲解到,涉及到更多业务逻辑,无非也就是在这个基础上,绘制自己业务想要的效果,万变不离其宗,只要掌握好方法,再复杂的图也信手捏来.
之所以要画这两个图,是因为之前有人问博主有没有别人写好的能直接用的股票图,搜了好久没发现有比较成熟的Android股票图绘制,有的都必须在项目的基础上改造,而且BUG也比较多
就目前来讲,Android暂时还没有一个较为成熟的股票图项目可以依赖,而使用半成熟的项目,本身就会遇到许多bug,与其花精力去修改别人的bug,不如自己编写一个.
博主本人公司并没有涉及到股票图的绘制,个人对股票也不是很熟悉,以上所有的讲解都是个人理解,难免会有错误,欢迎大家留言交流指正. |