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

原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/5844.html

(0)
上一篇 2021年7月17日
下一篇 2021年7月17日

相关推荐

发表回复

登录后才能评论