android 实现淘宝收益图的折线
实现的效果我一会贴上,我先说下原理,我们知道要实现在canvas上画线,不就是要搞一个paint嘛,然后首先肯定要设置下paint的属性,那么画文字呢,不就是Textpaint吗,
对,就是这么简单,接下来怎么画,折线图主要分为X轴和y轴,x轴表示日期,y表示收益,好,说道这里,大家应该知道怎么去做了,下面直接贴代码,
这个方法是,画x,y坐标系的,以及上面的日期和收益了
private void drawCoordinate(Canvas canvas) {
//坐标系画笔
Paint coordinatePaint = new Paint();
coordinatePaint.setAntiAlias(true);
coordinatePaint.setStrokeWidth(1);
coordinatePaint.setColor(getResources().getColor(R.color.c5));
//坐标系文字画笔
TextPaint coordinateTextPaint = new TextPaint();
coordinateTextPaint.setAntiAlias(true);
coordinateTextPaint.setTextSize(scaleTextSize);
coordinateTextPaint.setAntiAlias(true);
coordinateTextPaint.setColor(scaleTextColor);
coordinateTextPaint.setTextAlign(Align.CENTER);
//水平的刻度线
float verticalScaleStep = getVerticalScaleStep();
coordinateTextPaint.setTextAlign(Align.RIGHT);
float textHeight = getTextHeight(coordinateTextPaint, "8");
for (int i = 0; i < maxVerticalScaleValue; i++) {
float y = getHeight() - bottomPadding - (verticalScaleStep * i);
canvas.drawLine(leftPadding, y, getWidth() - rightPadding, y, coordinatePaint);
canvas.drawText(i + "", leftPadding - 13, y + textHeight / 2, coordinateTextPaint);
}
//垂直的刻度线
float horizontalScaleStep = getHorizontalScaleStep();
for (int i = 0; i < line.getSize(); i++) {
float x = leftPadding + (horizontalScaleStep * i);
if (i == 0) {
canvas.drawLine(x, topPadding, x, getHeight() - bottomPadding, coordinatePaint);
}
coordinateTextPaint.setColor(mTouchIndex == i ? verticalLineColor : scaleTextColor);
coordinateTextPaint.setTextAlign(i == 0 ? Align.LEFT : Align.CENTER);
canvas.drawText(line.getPoint(i).getX(), x, getHeight() - bottomPadding + textHeight + 10, coordinateTextPaint);
}
}
但是产品有个需求啊,就是点击当前日期可以查看我的收益,并且在交汇点上展示出来
private void drawCurve(Canvas canvas) {
Paint curvePaint = new Paint();//曲线画笔
curvePaint.setColor(curveColor);
curvePaint.setAntiAlias(true);
curvePaint.setStrokeWidth(curveStrokeWidth);
float horizontalScaleStep = getHorizontalScaleStep();
float lastXPixels = 0, newYPixels = 0;
float lastYPixels = 0, newXPixels = 0;
float useHeight = getHeight() - bottomPadding - topPadding;
for (int i = 0; i < line.getSize(); i++) {
float yPercent = line.getPoint(i).getY() / maxVerticalScaleValue;
if (i == 0) {
lastXPixels = leftPadding + i * horizontalScaleStep;
lastYPixels = getHeight() - bottomPadding - useHeight * yPercent;
} else {
newXPixels = leftPadding + i * horizontalScaleStep;
newYPixels = getHeight() - bottomPadding - useHeight * yPercent;
canvas.drawLine(lastXPixels, lastYPixels, newXPixels, newYPixels, curvePaint);
lastXPixels = newXPixels;
lastYPixels = newYPixels;
}
line.getPoint(i).fLineX = lastXPixels;
line.getPoint(i).fLineY = lastYPixels;
}
}
点击交汇点,有文字提示说明,
private void drawTipRect(Canvas canvas) {
if (mTouchIndex == -1) return;
LinePoint point = line.getPoint(mTouchIndex);
float x = point.fLineX;
float y = point.fLineY;
// 描绘竖线
Paint paint = new TextPaint();
PathEffect effects = new DashPathEffect(new float[]{5, 5, 5, 5}, 1);
paint.setPathEffect(effects);
paint.setAntiAlias(true);
paint.setStrokeWidth(verticalLineStrokeWidth);
paint.setColor(verticalLineColor);
canvas.drawLine(x, topPadding, x, getHeight() - bottomPadding, paint);
//描绘交汇圆点
paint.setPathEffect(null);
paint.setStyle(Paint.Style.FILL_AND_STROKE);
paint.setColor(Color.WHITE);
canvas.drawCircle(x, y, circleRadius, paint);
paint.setStyle(Paint.Style.STROKE);
paint.setColor(circleColor);
paint.setStrokeWidth(circleStrokeWidth);
canvas.drawCircle(x, y, circleRadius, paint);
float midY = (topPadding + getHeight() - bottomPadding) / 2;
float midX = (leftPadding + getWidth() - rightPadding) / 2;
//描绘圆角矩形
TextPaint textPaint = new TextPaint();
textPaint.setTextSize(tipTextSize);
textPaint.setTextAlign(Align.CENTER);
textPaint.setColor(tipTextColor);
textPaint.setAntiAlias(true);
String label = tipPrefix + point.getY();
float textWidth = textPaint.measureText(label) + 15;
float textHeight = getTextHeight(textPaint, label) + 8;
float hMargin = 10;//水平间距
float vMargin = 8;//垂直间距
float w = textWidth + hMargin * 2;//宽
float h = textHeight + vMargin * 2;//高
RectF rect = new RectF();
if (x > midX) {
rect.right = x - hMargin;
rect.left = x - w;
} else {
rect.left = x + hMargin;
rect.right = x + w;
}
if (y > midY) {
rect.top = y - h;
rect.bottom = y - vMargin;
} else {
rect.bottom = y + h;
rect.top = y + vMargin;
}
Paint roundRectPaint = new Paint();
roundRectPaint.setColor(tipRectColor);
roundRectPaint.setStyle(Paint.Style.FILL);
roundRectPaint.setAntiAlias(true);
canvas.drawRoundRect(rect, 3, 3, roundRectPaint);
// 描绘圆角矩形中间的文字
float roundTextX = (rect.left + rect.right) / 2;
float roundTextY = (rect.top + rect.bottom + getTextHeight(textPaint, label)) / 2;
canvas.drawText(label, roundTextX, roundTextY, textPaint);
}
好了核心的代码就这么多了,由于我们把它当做的是控件再用,那么我们在初始化的时候,肯定会引入一些自定义的样式表,
private void initViews(AttributeSet attrs, int defStyle) {
TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.LineGraph, defStyle, 0);
scaleTextSize = typedArray.getDimension(R.styleable.LineGraph_scale_text_size, 20);
scaleTextColor = typedArray.getColor(R.styleable.LineGraph_scale_text_color, getResources().getColor(R.color.c5));
tipRectColor = typedArray.getColor(R.styleable.LineGraph_tip_rect_color, getResources().getColor(R.color.c8));
tipTextSize = typedArray.getDimension(R.styleable.LineGraph_tip_text_size, 22);
tipTextColor = typedArray.getColor(R.styleable.LineGraph_tip_text_color, getResources().getColor(R.color.c12));
curveStrokeWidth = typedArray.getDimension(R.styleable.LineGraph_curve_stroke_width, 4);
curveColor = typedArray.getColor(R.styleable.LineGraph_curve_color, getResources().getColor(R.color.c8));
verticalLineStrokeWidth = typedArray.getDimension(R.styleable.LineGraph_vertical_line_stroke_width, 2);
verticalLineColor = typedArray.getColor(R.styleable.LineGraph_vertical_line_color, getResources().getColor(R.color.c8));
circleStrokeWidth = typedArray.getDimensionPixelSize(R.styleable.LineGraph_circle_stroke_width, 3);
circleColor = typedArray.getColor(R.styleable.LineGraph_circle_color, getResources().getColor(R.color.c8));
circleRadius = typedArray.getDimensionPixelSize(R.styleable.LineGraph_circle_radius, 7);
typedArray.recycle();
bottomPadding = dip2px(getContext(), 20);
topPadding = dip2px(getContext(), 10);
leftPadding = dip2px(getContext(), 20);
rightPadding = dip2px(getContext(), 10);
}
样式表文件我就不多说了,行如下面的格式,
<declare-styleable name="LineGraph">
<attr name="scale_text_size" format="dimension" />
<attr name="scale_text_color" format="color" />
<attr name="tip_text_size" format="dimension" />
<attr name="tip_text_color" format="color" />
<attr name="tip_rect_color" format="color" />
<attr name="curve_stroke_width" format="dimension" />
<attr name="curve_color" format="color" />
<attr name="vertical_line_stroke_width" format="dimension" />
<attr name="vertical_line_color" format="color" />
<attr name="circle_stroke_width" format="dimension" />
<attr name="circle_color" format="color" />
<attr name="circle_radius" format="dimension" />
</declare-styleable>
最后贴上个效果图,有需要的联系我吧,欢迎留言
git下载地址:https://github.com/xiangzhihong/lineview
android 实现淘宝收益图的折线的更多相关文章
- Android仿淘宝购物车demo
夏的热情渐渐退去,秋如期而至,丰收的季节,小编继续着实习之路,走着走着,就走到了购物车,逛过淘宝或者是京东的小伙伴都知道购物车里面的宝贝可不止一件,对于爱购物的姑娘来说,购物车里面的商品恐怕是爆满,添 ...
- Android之淘宝商品列表长按遮罩效果
先来看看淘宝.唯品会长按商品的效果,以及简单Demo的效果: 首先分析一下场景: 长按条目时,弹出遮罩的效果遮挡在原来的条目布局上: 页面滑动或点击其他的条目,上一个正在遮罩的条目遮罩消 ...
- Android仿淘宝继续上拉进入商品详情页的效果,使用双Fragment动画切换;
仿淘宝继续上拉进入商品详情页的效果,双Fragment实现: 动画效果: slide_above_in.xml <?xml version="1.0" encoding=&q ...
- Android -- 仿淘宝广告条滚动
1,在赶项目的时候我们经常会实现下面这个功能,及添加滚动条广告广播,先看一下淘宝的效果 2,这次实现效果主要使用Android自带的ViewFlipper控件,先来看一下我们的它的基本属性和基本方法吧 ...
- Android仿淘宝头条滚动广告条
之前我使用TextView+Handler+动画,实现了一个简单的仿淘宝广告条的滚动,https://download.csdn.net/download/qq_35605213/9660825: 无 ...
- Android 仿淘宝头条竖直跑马灯式新闻标题及“分页思想
在淘宝App的首页中间位置,有一块小小的地方在不知疲倦地循坏滚动着头条标题(见下图的红框区域),这样的设计无疑能够在有限的手机屏幕上展示更丰富的内容.而实现这一功能需要用到的控件就是我在上一篇文章中提 ...
- Android 仿淘宝属性标签页
直接看效果图相信这样的效果很多,我之前在网上找了很久没找到自己想要的! <?xml version="1.0" encoding="utf-8"?> ...
- Android画柱状图,圆形图和折线图的demo
效果图如下: demo下载地址:http://files.cnblogs.com/hsx514/wireframe.zip
- jquery实现淘宝动态图展示商品
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...
随机推荐
- 通过JNDI从服务器容器中获取资源_Spring JNDI+Mysql+Tomcat
通过JNDI从服务器容器中获取DataSource资源 (由容器管理,不要关闭它,容器自己会处理)上一篇我们使用的是dbcp,这里使用JNDI: 使用JNDI连接数据: 在Spring可以注释 < ...
- Android之触摸手势检测GestureDetector使用详解
在Android中,当用户触摸屏幕的时候,会产生许多手势,例如down,up,scroll,filing,onSingleTapConfirmed(单击),onDoubleTap(双击)等等. 一般情 ...
- Java学习之参数传递详解
Java中的参数传递问题: 基本类型:形式参数的改变对实际参数没有影响.在参数传递过程中,形参和实参占用了两个完全不同的内存空间. 引用类型:形式参数的改变直接影响实际参数.在参数传递的过程中,形参和 ...
- UE4联机烘焙
联机烘焙就是为了利用多台电脑解决烘焙效率的问题 1.UE4的烘焙工具在安装目录下的\Engine\Binaries\DotNET,比如我这里是E:\UnrealEngine-release\Engin ...
- TCP的发送系列 — 发送缓存的管理(二)
主要内容:从TCP层面判断发送缓存的申请是否合法,进程因缺少发送缓存而进行睡眠等待. 因为有发送缓存可写事件而被唤醒. 内核版本:3.15.2 我的博客:http://blog.csdn.net/zh ...
- HDFS HA: 高可靠性分布式存储系统解决方案的历史演进
1. HDFS 简介 HDFS,为Hadoop这个分布式计算框架提供高性能.高可靠.高可扩展的存储服务.HDFS的系统架构是典型的主/从架构,早期的架构包括一个主节点NameNode和多个从节点Da ...
- javascript setinterval 正确的语法
前几天我用setinterval 写了一个小程序,这个setinterval是用来干什么的我就不解释了. 写的方法在其它的浏览器里都能用,后来测试组的同事拿去一测就出了问题.因为她们爱用360,还有I ...
- 检查一个二叉树是否平衡的算法分析与C++实现
今天面试一个实习生,就想既然是未出校园,那就出一个比较基础的题吧,没想到答的并不如人意,对于树的操作完全不熟悉,因此此题算是未作答.原来我想看一下他分析问题的思路,优化代码的能力.接下来会把最近半年我 ...
- javascript之DOM编程通过html元素的标签属性找节点
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- (NO.00003)iOS游戏简单的机器人投射游戏成形记(七)
因为到目前为止我都是在iOS模拟器中测试,但即便如此,也觉得按住手臂旋转时,手臂转动起来比较费劲,很难停止在玩家期望的位置上.因为手臂完全通过物理引擎的计算来移动,它有自身的惯性影响,所以很难控制. ...