liangzi1717 2017-10-11 02:00 采纳率: 0%
浏览 2056

android 自定义view调用invalidate有时候保留上次绘制的线

如题,本人自定义一个折线图,应为数据接口合不上就弄了一个适配器模式匹配数据,但是多次跟新数据重新设置适配器时候,有时发现折线图会出现上一次数据绘制的一根线,代码如下:

        @Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    getPaint().reset();
    /**
     * 外框线
     */
    // 设置颜色
    getPaint().setColor(substrateColor);
    // 设置宽度
    getPaint().setStrokeWidth(2);
    // 线的坐标点 (四个为一条线)
    float[] pts = {LEFTUPX, LEFTUPY - 20, LEFTUPX, LEFTDOWNY, LEFTUPX, LEFTDOWNY, RIGHTDOWNX + 20, LEFTDOWNY};
    // 画线
    canvas.drawLines(pts, getPaint());

    /**
     * 箭头
     */
    // 通过路径画三角形
    Path path = new Path();
    getPaint().setStyle(Paint.Style.FILL);// 设置为空心
    path.moveTo(LEFTUPX - 5, LEFTUPY - 20);// 此点为多边形的起点
    path.lineTo(LEFTUPX + 5, LEFTUPY - 20);
    path.lineTo(LEFTUPX, LEFTUPY - 35);
    path.close(); // 使这些点构成封闭的多边形
    canvas.drawPath(path, getPaint());
    // 第二个箭头
    path.moveTo(RIGHTDOWNX + 20, LEFTDOWNY - 5);// 此点为多边形的起点
    path.lineTo(RIGHTDOWNX + 20, LEFTDOWNY + 5);
    path.lineTo(RIGHTDOWNX + 35, LEFTDOWNY);
    canvas.drawPath(path, getPaint());

    /**
     *  中间虚线
     */
    float[] pts2 = new float[(updownlines + leftrightlines) * 4];
    // 计算位置y轴标题
    if (updownlines != 0) {
        for (int i = 0; i < updownlines; i++) {

            float x1 = LEFTUPX;
            float y1 = LEFTDOWNY - (i + 1) * UPDOWNSPACE;
            float x2 = RIGHTDOWNX;
            float y2 = LEFTDOWNY - (i + 1) * UPDOWNSPACE;
            pts2[i * 4 + 0] = x1;
            pts2[i * 4 + 1] = y1;
            pts2[i * 4 + 2] = x2;
            pts2[i * 4 + 3] = y2;
            getPaint().setColor(Color.BLACK);
            getPaint().setTextSize(25);
            if (showRule != null) {
                if (showRule.showVerticalTitle(i))
                    canvas.drawText(String.valueOf(verticalTitle[i]), x1 + 5, y1 + 10, getPaint(titleColor));
            } else {
                canvas.drawText(String.valueOf(i), x1 + 5, y1 + 10, getPaint(titleColor));
            }
        }
    }

    // 计算位置x轴上标题
    if (leftrightlines != 0) {
        for (int i = 0; i < leftrightlines; i++) {
            float x1 = LEFTUPX + (i + 1) * LEFTRIGHTSPACE;
            float y1 = LEFTUPY;
            float x2 = LEFTUPX + (i + 1) * LEFTRIGHTSPACE;
            float y2 = LEFTDOWNY;
            pts2[(i + updownlines) * 4 + 0] = x1;
            pts2[(i + updownlines) * 4 + 1] = y1;
            pts2[(i + updownlines) * 4 + 2] = x2;
            pts2[(i + updownlines) * 4 + 3] = y2;
            if (showRule != null) {
                if (showRule.showLandsTitle(i)) {
                    Paint pen = getPaint();
                    if (showRule.markLandsTitle(String.valueOf(lanspaceTitle[i]))) {
                        pen.setColor(markTitleColor);
                        Typeface font = Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD);
                        pen.setTypeface(font);

                    } else {
                        pen.setColor(titleColor);
                        Typeface font = Typeface.create(Typeface.SANS_SERIF, Typeface.NORMAL);
                        pen.setTypeface(font);
                    }
                    canvas.drawText(String.valueOf(lanspaceTitle[i]), x2 - 10, y2 + 30, pen);
                }
            } else {
                canvas.drawText(String.valueOf(i), x2 - 10, y2 + 30, getPaint(titleColor));
            }
        }
        if (showRule != null && !TextUtils.isEmpty(showRule.landsUnit())) {
            float[] widths = new float[1];
            float width = 0;
            for (int j = 0; j < (String.valueOf(lanspaceTitle[lanspaceTitle.length - 1])).length(); j++) {
                getPaint().getTextWidths(String.valueOf((String.valueOf(lanspaceTitle[lanspaceTitle.length - 1]).charAt(j))), widths);
                width += widths[0];
            }
            canvas.drawText(showRule.landsUnit(), LEFTUPX + (leftrightlines) * LEFTRIGHTSPACE + width, LEFTDOWNY + 30, getPaint(titleColor));
        }

    }

    getPaint().setColor(imaginaryLineColor);
    getPaint().setStrokeWidth(1);
    if (showRule != null && showRule.showImaginaryLine())
        canvas.drawLines(pts2, getPaint());
    getPaint().setStrokeWidth(2);
    if (showRule != null) {
             if (intervalTime == 0) {
                 number = 50;
                 count = dataSize - 1;
                 //一定要先画矮的那根线,否则会被遮盖
                 if (/*listY2.size() > 0*/list.size() > 0)
                         canvasDataLines(canvas, 1, firstLineColor, firstBelowColor);

                 if (list.size() > 0)
                        canvasDataLines(canvas, 0, secondLineColor, secondBelowColor);
                 isFinish = true;   
             } else {
                 if (list.size() > 0)
                     canvasDataLines(canvas, 1, firstLineColor, firstBelowColor);
                 if (list.size() > 0)
                     canvasDataLines(canvas, 0, secondLineColor, secondBelowColor);
                 handler.sendEmptyMessage(1);
             }
        }

        if (clickPoint != null) {
            Log.e("Click", "postInvalidate--->>>onDraw");
            //点击后的浮现效果出现
            selectedView.setPointf(clickPoint.getLine() == PointBean.THEFIRSTLINE ? clickPoint.getUppointF() : clickPoint.getDownPoint())
                    .setAlterBgColor(clickPoint.getLine() == PointBean.THEFIRSTLINE ? clickSecondLineBgColor : clickFirstLineBgColor)
                    .setFontColor(clickPoint.getLine() == PointBean.THEFIRSTLINE ? clickFirstLineFontColor : clickSecondLineFontColor)
                    .setCircleColor(clickPoint.getLine() == PointBean.THEFIRSTLINE ? clickSecondLineCircleColor : clickFirstLineCircleColor)
                    .setTextValue(clickPoint.getLine() == PointBean.THEFIRSTLINE ? clickPoint.getText() : clickPoint.getText2())
                    .setMargin(selectedView.getCrossBorder()?-50:30)
                    .draw(canvas);
            //如果需要这个浮现效果自动消失就用一个handler将clickPoint制空并且重新绘制就好了
        }


}

/**
 * 画折线
 *
 * @param canvas
 * @param listY
 * @param color
 * @param endColor
 */
private synchronized void canvasDataLines(Canvas canvas, int flag, int color, int endColor) {
    // 线的路径
    Path path2 = new Path();
    // 共几个转折点
    for (int i = 0; i < count; i++) {
        if (i == 0) {
            path2.moveTo(list.get(i).getX(), flag==0?list.get(i).getY1():list.get(i).getY2());
        } else {
            path2.lineTo(list.get(i).getX(), flag==0?list.get(i).getY1():list.get(i).getY2());
        }
    }
    // 上一个点  减去 下一个点的位置 计算中间点位置
    path2.lineTo(list.get(count - 1).getX() + (list.get(count).getX() - list.get(count - 1).getX()) / 50 * number,
            flag==0?list.get(count - 1).getY1():list.get(count - 1).getY2() + (flag==0?list.get(count).getY1():list.get(count).getY2() - flag==0?list.get(count - 1).getY1():list.get(count - 1).getY2()) / 50 * number);
    getPaint().setColor(color);
    getPaint().setStrokeWidth(2);
    getPaint().setStyle(Paint.Style.STROKE);// 设置为空心
    canvas.drawPath(path2, getPaint());

    path2.lineTo(list.get(count - 1).getX() + (list.get(count).getX() - list.get(count - 1).getX()) / 50 * number, LEFTDOWNY);
    path2.lineTo(list.get(0).getX(), LEFTDOWNY);
    path2.lineTo(list.get(0).getX(), flag==0?list.get(0).getY1():list.get(0).getY2());
    getPaint().setStyle(Paint.Style.FILL);// 设置为空心
    canvas.drawPath(path2, getShadeColorPaint(endColor,color));
    getPaint().reset();

}
  • 写回答

4条回答 默认 最新

  • Tauren2614 2017-10-11 03:13
    关注

    调用invalidate 的时候不是立即调用onDraw函数的,只是设置了一个flag,等待下一个绘制周期来的时候才会调用该View的onDraw函数
    看代码中存放数据的list并没有加锁,所以在快速更新数据快速调用刷新的时候存在onDraw函数执行的过程中数据发生变化的风险

    评论

报告相同问题?

悬赏问题

  • ¥20 Python安装cvxpy库出问题
  • ¥15 用前端向数据库插入数据,通过debug发现数据能走到后端,但是放行之后就会提示错误
  • ¥15 python天天向上类似问题,但没有清零
  • ¥30 3天&7天&&15天&销量如何统计同一行
  • ¥30 帮我写一段可以读取LD2450数据并计算距离的Arduino代码
  • ¥15 C#调用python代码(python带有库)
  • ¥15 矩阵加法的规则是两个矩阵中对应位置的数的绝对值进行加和
  • ¥15 活动选择题。最多可以参加几个项目?
  • ¥15 飞机曲面部件如机翼,壁板等具体的孔位模型
  • ¥15 vs2019中数据导出问题