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

时间: 2024-09-25 19:31:16

android 实现淘宝收益图的折线的相关文章

Android仿淘宝view滑动至屏幕顶部会一直停留在顶部的位置_Android

在刚刚完成的项目中,在一个页面中,用户体验师提出引用户操作的入住按钮要一直保留在页面当中,不管页面能滚动多长都得停留在页面的可视区域.最终实现效果如下图所示:   如图中的红色框中的view始终会停留在页面中,如果滑动至页面的顶部,会一直保留在顶部. 下面来说下具体的实现思路: 思路:其实整个页面当中一共有两个视觉效果一样的View,通过滑动的位置来进行View的隐藏和显示来达到这种效果.整个页面的在上下滑动的过程中可以总结为两个状态,状态A(如图1所示),view2在可视区域内时,view1不

Android 仿淘宝商品属性标签页_Android

需求 1.动态加载属性,如尺码,颜色,款式等 由于每件商品的属性是不确定的,有的商品的属性是颜色和尺码,有的是口味,有的是大小,所以这些属性不能直接写死到页面上. 2.动态加载属性下的标签 每个属性下的标签个数也不是一定的,比如有的商品的尺码是是S,M,XL,有的是均码,也就是每种属性的具体的内容是不一定的. 技术点 自定义ViewGroup,使其中的TextView可以依据内容长短自动换行,如下图所示 实现 布局 通过ListView来显示商品所有属性,每种属性作为ListView的Item.

Android仿淘宝头条基于TextView实现上下滚动通知效果

最近有个项目需要实现通知栏的上下滚动效果,仿淘宝头条的那种. 我从网上看了一些代码,把完整的效果做了出来.如图所示: 具体代码片段如下: 1.在res文件夹下新建anmin文件夹,在这个文件夹里创建两个文件 (1).anim_marquee_in.xml进入时动画 <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/ap

Android 仿淘宝、京东商品详情页向上拖动查看图文详情控件DEMO详解_Android

一.淘宝商品详情页效果 我们的效果 二.实现思路      使用两个scrollView,两个scrollView 竖直排列,通过自定义viewGroup来控制两个scrollView的竖直排列,以及滑动事件的处理.如下图 三.具体实现 1.继承viewGroup自定义布局View 重写onMeasure()和onLayout方法,在onLayout方法中完成对两个子ScrollView的竖直排列布局,代码如下: 布局文件: <RelativeLayout xmlns:android="h

Android实现淘宝选中商品尺寸的按钮组实例

话不多说,先上个效果图: 现在我们就来说说里面的一些原理把! 一.原理: 1.其实这里我们用到的是一个ViewGroup控件组,把这些按钮加进去就有这种效果了!不过这里要继承ViewGroup(命名为:GoodsViewGroup)重写里面的一些方法. 2.主要的方法有: GoodsViewGroup按钮组的控件大小 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) 里面的按钮每个的位置坐标 protect

Android 仿淘宝商品属性标签页

需求 1.动态加载属性,如尺码,颜色,款式等 由于每件商品的属性是不确定的,有的商品的属性是颜色和尺码,有的是口味,有的是大小,所以这些属性不能直接写死到页面上. 2.动态加载属性下的标签 每个属性下的标签个数也不是一定的,比如有的商品的尺码是是S,M,XL,有的是均码,也就是每种属性的具体的内容是不一定的. 技术点 自定义ViewGroup,使其中的TextView可以依据内容长短自动换行,如下图所示 实现 布局 通过ListView来显示商品所有属性,每种属性作为ListView的Item.

android仿淘宝刮刮卡功能实现

去年淘宝和天猫的活动搞的有声有色的,其中有一个游戏还是很受大家欢迎的,那就是红包刮刮卡,自己也挺迷的,一刮起来就停不下来,有没有? 最近自己也在学习android入门,正好前些日子在搜索一个功能示例的时候,找到一个哥们分享的一篇介绍刮刮卡的文章,文章很简单,基本没有废话,直接贴了如何通过自定义view来实现刮刮卡的示例代码,链接如下: http://www.cnblogs.com/xinye/p/3616095.html   后来又借着给大家分享android开发入门知识的机会,以这个示例为主要

Android仿淘宝商品拖动查看详情及标题栏渐变功能_Android

绪论 最近一直比较忙,也没抽出时间来写博客,也不得不说是自己犯了懒癌,人要是一懒就什么事都不想做了,如果不能坚持下来的话,那么估计就废了,��.最近自己攒了好多东西,接下来的时间我会慢慢都分享出来的.好了废话不多说了,下面我们开始正题: 今天要分享的是淘宝的详情页,之前在淘宝上买东西的时候看到淘宝的详情页效果比较不错,所以今天就来仿一下它的效果吧,可能没有淘宝的好,希望见谅啊. 先上效果图: 这是淘宝的:   我自己做的:   怎么样效果还差不多吧?GIF图效果看的不太清楚,见谅. 下面我们来看

Android仿淘宝购物车demo

       夏的热情渐渐退去,秋如期而至,丰收的季节,小编继续着实习之路,走着走着,就走到了购物车,逛过淘宝或者是京东的小伙伴都知道购物车里面的宝贝可不止一件,对于爱购物的姑娘来说,购物车里面的商品恐怕是爆满,添加不进去了,以前逛淘宝的时候,小编没有想过要怎么样实现购物车,就知道在哪儿一个劲儿的逛,但是现在不一样了,小编做为一个开发者,想的就是该如何实现,捣鼓了两天的时间,用listview来实现,已经有模有样了,现在小编就来简单的总结一下实现购物车的心路历程,帮助有需要的小伙伴,欢迎小伙伴们