【问题标题】:Item drawn in Custom view onDraw() keeps disappearing在自定义视图 onDraw() 中绘制的项目不断消失
【发布时间】:2019-11-07 20:49:51
【问题描述】:

我在 onDraw() 方法的自定义视图中绘制了 3 个东西:一个矢量可绘制对象、一条简单的线和一个三角形(由 4 个点和一个路径组成)。此自定义视图显示在选项卡中。

如果我滑动到另一个选项卡,我会看到系统调用 onDraw()。当我返回到持有我的自定义视图的选项卡时,矢量可绘制和简单线仍然可见,但三角形已经消失。如果我现在滑动到另一个选项卡,onDraw() 再次运行并返回到具有自定义视图的选项卡中,所有项目(包括三角形)现在都可见。当我来回滑动时,这种消失/出现继续发生。为什么我的三角形消失了?

更新 1(hacky 修复): 我尝试过实验并注意到,当我将三角形 Path 对象的创建移出 init() 方法并将其直接放入 onDraw() 方法时 - 然后一切正常,没有任何东西消失。但是,当我在 onDraw() 中创建此对象时,我现在收到“在绘制期间避免对象分配”警告;

更新 2(更好的修复?): 经过更多的实验,肯定是导致这个问题的路径。另一个解决方案 - 不会导致“在绘制期间避免对象分配”警告是:在 init() 中保留路径创建并删除代码行“myPath.setFillType(Path.FillType.EVEN_ODD)”。它解决了我的问题,但我不知道为什么。

    protected void onDraw(Canvas canvas) {

        super.onDraw(canvas);

        // Co-ordinates
        int width = getWidth();
        int halfWidth = width/2;
        int left = 0;
        int top = 0;
        int centreX = left + halfWidth;
        int centreY = top + halfWidth;
        int baseSize = Math.round((float)(halfWidth * 0.05));

        // Vector drawable - always draws fine!
        myVectorDrawable.setBounds(left, top, left + width, top + width);
        myVectorDrawable.draw(canvas);         

        // Simple line - always draws fine! 
        canvas.drawLine(left, top, 20, 20, paint);

        // Triangle - sometimes visible, sometimes disappears!
        Point myTriangleBottomMiddle = new Point(centreX, centreY);
        Point myTriangleBottomLeft = new Point(centreX, centreY + baseSize);
        Point myTriangleBottomRight = new Point(centreX, centreY - baseSize);
        Point myTriangleTopMiddle = new Point(centreX + halfWidth, centreY);
        myPath.moveTo(myTriangleBottomMiddle.x, myTriangleBottomMiddle.y);
        myPath.lineTo(myTriangleBottomLeft.x, mTriangleBottomLeft.y);
        myPath.lineTo(myTriangleTopMiddle.x, myTriangleTopMiddle.y);
        myPath.lineTo(myTriangleBottomRight.x, myTriangleBottomRight.y);
        mPath.close();
        canvas.drawPath(myPath, myPaint);

   }

在我设置东西的代码下方,以免加重 onDraw() 方法的负担。

private void init() {

    // Vector drawable
    myVectorDrawable = r.getDrawable(R.drawable.gauge_dial);

    // Triangle path - ** THIS BEING HERE SEEMS TO BE THE PROBLEM **
    myPath = new Path();
    myPath.setFillType(Path.FillType.EVEN_ODD);

    // Triangle Paint
    myPaint = new Paint();
    myPaint.setColor(r.getColor(R.color.black));
    myPaint.setStrokeWidth(2);
    myPaint.setAntiAlias(true);
    myPaint.setStyle(Paint.Style.FILL);

    // Simple line paint
    Paint paint = new Paint();
    paint.setColor(Color.BLACK);
}

【问题讨论】:

  • 看起来 centerX 和 centerY 的值是在您的代码中的其他位置设置的,它们的值是否不正确会导致三角形具有不同的坐标?也许全 0 可以解释它是不可见的
  • 嗨,泰勒,感谢您的帖子。我把 centerX/Y 留在外面以保持我的代码清晰,但我已经把它贴回上面了。它们基于自定义视图的宽度 - 不会改变。

标签: android android-custom-view ondraw


【解决方案1】:

在路径上添加对 reset() 的调用。

    // Triangle - sometimes visible, sometimes disappears!
    Point myTriangleBottomMiddle = new Point(centreX, centreY);
    Point myTriangleBottomLeft = new Point(centreX, centreY + baseSize);
    Point myTriangleBottomRight = new Point(centreX, centreY - baseSize);
    Point myTriangleTopMiddle = new Point(centreX + halfWidth, centreY);
    myPath.reset();
    myPath.moveTo(myTriangleBottomMiddle.x, myTriangleBottomMiddle.y);
    myPath.lineTo(myTriangleBottomLeft.x, mTriangleBottomLeft.y);
    myPath.lineTo(myTriangleTopMiddle.x, myTriangleTopMiddle.y);
    myPath.lineTo(myTriangleBottomRight.x, myTriangleBottomRight.y);
    mPath.close();
    canvas.drawPath(myPath, myPaint);

另外,我建议将可绘制矢量放到单独的视图中,这样就不会在每次需要为三角形设置动画时都重新绘制它(假设这将是一个动画量规表盘)。

【讨论】:

  • 谢谢克里斯。你是对的,在 onDraw() 中创建 Path 对象确实可以解决它 - 但这意味着我仍然收到“避免在绘图中分配对象”警告,这不是很好。
  • 见上面我的更新#2。另一种解决方案 - 但我不知道为什么?
  • 或者,您可以调用 myPath.reset();
  • 不错的一个!做 myPath.reset() 修复它!
  • 如果您将其添加为单独的答案,我可以勾选它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多