1

アダプター クラスを使用して 3x3 GridView 内に 9 つのビューを表示するアプリがあります。GridView のセルに含まれる 9 つのビューのそれぞれで、Canvas オブジェクトと Paint オブジェクトを使用して 2 次元の線のグラフィックを表示します。これらの線のグラフィックは、その後、各ビューの invalidate() メソッドを呼び出すことによって変更され、再表示されます。

Adapter クラスのオーバーライドされた getView() メソッドでビューが作成されると、9 つのビューすべての線のグラフィックが正しく表示されますが、後で線のグラフィックを変更して再表示しようとすると、最初のビューを除いてすべてのビューが正常に更新されます。グリッドの左上隅に表示され、元の線画が引き続き表示されます。最初のビューが確実に無効化されていることを確認するためにコードをステップ実行しました。そのため、最初のビューで invalidate() メソッドを呼び出しても再描画されない理由について困惑しています。 、残りのすべてのビューで同じ呼び出しを行うと、正常に再描画されます。ビューの onDraw メソッドの呼び出しもログに記録しました。これは、最初のビューの onDraw メソッドが毎回呼び出されることを示しているため、この問題がアプリケーション コードのバグによって引き起こされたものではないと確信しています。

9 つのビューを変更および更新するコードは次のとおりです。

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

OK、やっとこれの真相にたどり着きました - TestCanvasAdapter クラスの getView メソッドは、 testCanvass[0] に対して2 回呼び出されましたが、他のすべての要素に対しては 1 回しか呼び出されなかったことがわかりました。Adapter クラスの getView メソッドは、配列内の各要素に対して 1 回だけ呼び出されると単純に想定していましたが、この投稿では、 getView がさまざまなあいまいな理由で複数回呼び出される可能性があることを確認しています。自分。これを理解すると、TestCanvass[position] メソッド内でビュー参照を割り当てる前に、testCanvass[position] が null でないことを確認するロジックを簡単に追加でき、問題が解決しました。

            // 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() は呼び出されません。これを確認するには、Dev Tools アプリ (エミュレーター上ですが、電話にもインストールできます) を開き、開発設定画面で [画面の更新を表示] をオンにします。無効化/再描画される画面の領域をフラッシュします。

于 2011-01-21T18:31:24.133 に答える