1

我有一个应用程序,其中我使用适配器类在 3x3 GridView 中显示九个视图。在 GridView 的单元格中包含的九个视图中的每一个中,我使用 Canvas 和 Paint 对象来显示二维线图形;这些线图随后通过调用每个视图的 invalidate() 方法进行修改和重新显示。

当在 Adapter 类的重写 getView() 方法中创建视图时,所有九个视图中的线图都正确显示,但是当我尝试修改并随后重新显示线图时,除了一个视图之外,所有视图都成功刷新网格左上角的视图,它继续显示原始线条图。我已经通过我的代码来确定第一个视图肯定是无效的,而且确实如此,所以我很困惑为什么在第一个视图上调用 invalidate() 方法不会导致它被重绘,而对所有剩余视图的相同调用会导致它们成功重绘。我还记录了对视图的 onDraw 方法的调用,这表明每次都会调用第一个视图的 onDraw 方法,所以我很确定这个问题不是由应用程序代码中的任何错误引起的。

修改和刷新九个视图的代码如下:

void updateViews(int parentTestCanvas) {

    TestCanvasView testCanvas = testCanvass[parentTestCanvas];
    double[] parentGenome = testCanvas.getGenome();

    // Assign the parent genome to the testCanvass in the array
    // The inherited genome will be subject to mutation in all cases except the first testCanvas
    for(int testCanvasItem = 0; testCanvasItem < TestCanvasApp.geneCount; testCanvasItem++) {

        testCanvas = testCanvass[testCanvasItem];
        testCanvas.setGenome(parentGenome);

        // Invalidate the testCanvas view to force it to be redrawn using the new genome
        testCanvas.invalidate();
    }


}

TestCanvasView类中的onDraw方法如下:

protected void onDraw(Canvas canvas) {

    float xOrigin = getMeasuredWidth() / 2;
    float yOrigin = getMeasuredHeight() / 2;

    canvas.drawPaint(cellPaint);

    canvas.translate(xOrigin, yOrigin);
    drawBranch(canvas, linePaint, 0, 0, this.length, this.direction, this.xInc, this.yInc, this.scale);
    Log.d("TestCanvasView", "Drawing testCanvas " + mCellIndex);
}

private void drawBranch(Canvas canvas, Paint linePaint, double startX,
        double startY, double branchLen, int branchDir, double[] xInc,
        double[] yInc, double scale) {

    branchDir = (branchDir + 8) % 8;

    double newX = startX + branchLen * xInc[branchDir];
    double newY = startY + branchLen * yInc[branchDir];

    canvas.drawLine((float) (startX / scale), (float) (-startY / scale),
            (float) (newX / scale), (float) (-newY / scale), linePaint);

    if (branchLen > 1) {
        drawBranch(canvas, linePaint, newX, newY, branchLen - 1, branchDir + 1, xInc, yInc, scale);
        drawBranch(canvas, linePaint, newX, newY, branchLen - 1, branchDir - 1, xInc, yInc, scale);
    }

}

任何人都知道为什么第一个视图没有被重绘?

4

2 回答 2

2

好的,终于明白了——事实证明,TestCanvasAdapter 类中的 getView 方法为 testCanvass[0] 调用了两次,但对所有其他元素只调用了一次。我天真地假设 Adapter 类的 getView 方法会为数组中的每个元素只调用一次,但这篇文章证实了 getView 可能会因为各种晦涩的原因被多次调用,这些原因对于没有经验的 Android 开发人员来说不太可能很明显,比如我。一旦我理解了这一点,我就可以轻松地添加下面的逻辑来检查 testCanvass[position] 不为空,然后在 TestCanvasAdapter.getView 方法中分配视图引用,从而解决了问题。

            // Add the newly created TestCanvasView object to the array on the TestCanvasApp object
        if (position >= 0 && position < TestCanvasApp.viewCount 
                && mTestCanvasApp.testCanvass[position] == null) {
                    mTestCanvasApp.testCanvass[position] = testCanvasView;
        }

非常感谢 Romain Guy 不厌其烦地回复了这个问题。

于 2011-01-25T15:08:11.267 回答
0

如果调用了第一个视图的 onDraw() 方法,则无效工作。如果视图不与剪切矩形相交,则不会调用 onDraw()。您可以通过打开开发工具应用程序(在模拟器上,但您也可以将其安装在手机上)并在开发设置屏幕中打开“显示屏幕更新”来验证这一点。它将闪烁屏幕中无效/重绘的区域。

于 2011-01-21T18:31:24.133 回答