При вызове метода invalidate для массива Views первый View не перерисовывается - PullRequest
1 голос
/ 21 января 2011

У меня есть приложение, в котором я отображаю девять видов в GridView 3x3, используя класс адаптера. В каждом из девяти видов, содержащихся в ячейках GridView, я использую объекты Canvas и Paint для отображения двухмерной линейной графики; эти линейные графики впоследствии модифицируются и повторно отображаются путем вызова метода invalidate () для каждого представления.

Линейная графика во всех девяти представлениях отображается правильно, когда представления создаются в переопределенном методе 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();
    }


}

Метод onDraw в классе TestCanvasView выглядит следующим образом:

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);
    }

}

У кого-нибудь есть идеи относительно того, почему первое представление не перерисовывается?

Ответы [ 2 ]

2 голосов
/ 25 января 2011

ОК, наконец, дошло до сути - оказывается, что метод getView в классе TestCanvasAdapter был вызван дважды для testCanvass [0], но только один раз для всех остальных элементов.Я наивно предполагал, что метод getView класса Adapter будет вызываться ровно один раз для каждого элемента в массиве, но этот пост подтверждает, что 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 за то, что он ответил на этот вопрос.

0 голосов
/ 21 января 2011

Если вызывается метод onDraw () первого представления, то работает инвалидность. onDraw () не вызывается, если представление не пересекается с отсеченным прямоугольником. Вы можете убедиться в этом, открыв приложение Dev Tools (на эмуляторе, но вы также можете установить его на телефоне) и на экране настроек разработки включите «Показать обновления экрана». Будут мигать области экрана, которые становятся недействительными / перерисовываются.

...