实现的效果我一会贴上,我先说下原理,我们知道要实现在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 实现淘宝收益图的折线的更多相关文章

  1. Android仿淘宝购物车demo

    夏的热情渐渐退去,秋如期而至,丰收的季节,小编继续着实习之路,走着走着,就走到了购物车,逛过淘宝或者是京东的小伙伴都知道购物车里面的宝贝可不止一件,对于爱购物的姑娘来说,购物车里面的商品恐怕是爆满,添 ...

  2. Android之淘宝商品列表长按遮罩效果

    先来看看淘宝.唯品会长按商品的效果,以及简单Demo的效果:        首先分析一下场景: 长按条目时,弹出遮罩的效果遮挡在原来的条目布局上: 页面滑动或点击其他的条目,上一个正在遮罩的条目遮罩消 ...

  3. Android仿淘宝继续上拉进入商品详情页的效果,使用双Fragment动画切换;

    仿淘宝继续上拉进入商品详情页的效果,双Fragment实现: 动画效果: slide_above_in.xml <?xml version="1.0" encoding=&q ...

  4. Android -- 仿淘宝广告条滚动

    1,在赶项目的时候我们经常会实现下面这个功能,及添加滚动条广告广播,先看一下淘宝的效果 2,这次实现效果主要使用Android自带的ViewFlipper控件,先来看一下我们的它的基本属性和基本方法吧 ...

  5. Android仿淘宝头条滚动广告条

    之前我使用TextView+Handler+动画,实现了一个简单的仿淘宝广告条的滚动,https://download.csdn.net/download/qq_35605213/9660825: 无 ...

  6. Android 仿淘宝头条竖直跑马灯式新闻标题及“分页思想

    在淘宝App的首页中间位置,有一块小小的地方在不知疲倦地循坏滚动着头条标题(见下图的红框区域),这样的设计无疑能够在有限的手机屏幕上展示更丰富的内容.而实现这一功能需要用到的控件就是我在上一篇文章中提 ...

  7. Android 仿淘宝属性标签页

    直接看效果图相信这样的效果很多,我之前在网上找了很久没找到自己想要的! <?xml version="1.0" encoding="utf-8"?> ...

  8. Android画柱状图,圆形图和折线图的demo

    效果图如下: demo下载地址:http://files.cnblogs.com/hsx514/wireframe.zip

  9. jquery实现淘宝动态图展示商品

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

随机推荐

  1. Linux for sougou ping yin (http://pinyin.sogou.com/linux/help.php)

    安装指南 Ubuntu / Ubuntu Kylin 14.04 LTS 版本 只需双击下载的 deb 软件包,即可直接安装搜狗输入法. Ubuntu 12.04 LTS 版本 由于 Ubuntu 1 ...

  2. springMVC源码分析--拦截器HandlerExecutionChain(三)

    上一篇博客springMVC源码分析--HandlerInterceptor拦截器调用过程(二)中我们介绍了HandlerInterceptor的执行调用地方,最终HandlerInterceptor ...

  3. Android实现自动更新功能

    Android实现自动更新功能 Android自动更新的功能可以使用第三方的SDK来实现,但是类似友盟,就不支持x86手机的自动更新,科大讯飞,弹窗是全局的,小米手机就会默认把弹窗权限关掉不允许弹出提 ...

  4. Android获取当前网络状态

    Android获取当前网络状态 效果图 有网络 没有网络 源码 下载地址(Android Studio工程):http://download.csdn.net/detail/q4878802/9052 ...

  5. 抽屉效果的实现(DrawerLayout和SlidingMenu的对比)

    在做谷歌电子市场的时候用的是DrawerLayout实现的抽屉效果,在新闻客户端的时候用的是开源框架SlidingMenu来实现的,总的来说,各有个的优点,侧滑(开源框架)实现的效果更好,但是Draw ...

  6. 01_数据库连接池,数据源,ResultSetMetaData,jdbc优化

     一.数据库连接池 1. 什么是连接池 传统的开发模式下,Servlet处理用户的请求,找Dao查询数据,dao会创建与数据库之间的连接,完成数据查询后会关闭数据库的链接. 这样的方式会导致用户每 ...

  7. 18 Ui美化 剪切动画clip

    输入0 - 10000 让图片根据数值显示部分图片 在工程文件的res/drawable/新建clip文件 <?xml version="1.0" encoding=&quo ...

  8. ENVI自带的非监督分类测试情况

    最近写了两个关于遥感图像的简单的非监督分类算法KMEAN和ISODATA,发现结果和ENVI的一直有差异,而且还蛮大的,找了好久也没有找到原因.于是用PS自己绘制了一个简单的图像用于测试.如图1所示, ...

  9. 05 Activity生命周期

    生命周期:一个Activity从创建到销毁经过的全部方法 1.onCreate() 创建一个Activity的时候执行的方法 2.onStart()Activity可以被看见到时候无法交互(没有焦点) ...

  10. 【转载】2015 Objective-C 三大新特性 | 干货

    Overview 自 WWDC 2015 推出和开源 Swift 2.0 后,大家对 Swift 的热情又一次高涨起来,在羡慕创业公司的朋友们大谈 Swift 新特性的同时,也有很多像我一样工作上依然 ...