Почему моя ViewGroup отображается неправильно, когда на экране есть панель действий?

Я крутил свои колеса, пытаясь понять, почему моя реализация ViewGroup работает со сбоями с тех пор, как я начал пытаться добавить ActionBar в свою активность.

У меня есть пользовательская ViewGroup, которая выкладывает набор представлений на основе соотношений, связанных с текущей шириной и высотой представления. ViewGroup реализует алгоритм компоновки, немного похожий на абсолютную компоновку, но вместо абсолютных координат он принимает координаты относительно ширины и высоты ViewGroup.

Я в значительной степени игнорирую проход макета onMeasure, потому что я просто скажу дочерним представлениям, каковы будут их размеры.

OnLayout делает что-то вроде следующего:

@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom)
{
    if (isInEditMode()) return;

    int height = getHeight();
    int width = getWidth();

    for (int i = 0; i < getChildCount(); i++)
    {
        View child = getChildAt(i);
        ImageCell cell = cells.get(i);

        int l = (int)(cell.getX0() * width);
        int t = (int)(height - (cell.getY1() * height));
        int r = (int)(cell.getX1() * width);
        int b = (int)(height - (cell.getY0() * height));

        child.layout(l, t, r, b);

        child.setBackgroundColor(0xFFFF0000);
    }
}

К сожалению, представления, которые установлены как дочерние элементы моей пользовательской ViewGroup, не рисуют себя должным образом. Эти виды представляют собой простые виды растровых изображений, но к растровым изображениям может применяться масштабирование и перемещение. Мой View onDraw() написан примерно так:

@Override
public void onDraw(Canvas canvas) 
{

    if (canvasMatrix == null) 
    {
        canvasMatrix = new Matrix();
    }

    canvasMatrix.reset();
    canvasMatrix.setScale(scaleX, scaleY);
    canvasMatrix.postTranslate(getLeft() + translationX, getTop() + translationY);
    canvas.setMatrix(canvasMatrix);

    synchronized (renderBuffer) 
    {
        /**
         * We need to offset the renderBuffer, the scaling is done by the matrix
         * on the canvas.
         */

         canvas.drawBitmap(renderBuffer, offsetX, offsetY, null);

    }
}

Я настраиваю матрицу, которая будет применять масштабирование и перевод к холсту на основе масштаба и перевода изображений, которые необходимо отобразить. Затем изображения рисуются на холсте с указанным смещением по осям x и y.

Кажется, что происходит то, что растровое изображение закрашивается под ActionBar, оставляя большой запас пространства в нижней части экрана, который не закрашивается. Если я добавлю постоянный коэффициент к offsetY, растровое изображение можно заставить рисовать в правильном месте на экране (в зависимости от поворота устройства). Но я не уверен, где этот постоянный коэффициент должен быть рассчитан.

Я очень мало понимаю в рисовании Android. Я ожидал, что Canvas будет относиться к местоположению представления на экране, так что если я рисую в (0,0), краска появится в начале представления, а не в начале экрана.

Пример проблемы со странной картиной

Так что это изображение является примером того, что я вижу. Красная область внизу — это часть дочернего представления, не закрашенная drawBitmap.

Любая идея, что я делаю неправильно здесь? Все рисуется нормально, если представление полноэкранное, но с ActionBar мне не даются координаты, включающие размер ActionBar, поэтому я, кажется, рисую под ним.


person Neal Sanche    schedule 13.12.2011    source источник


Ответы (1)


Ваша проблема здесь: canvas.setMatrix(canvasMatrix);

Вызывая этот метод, вы уничтожаете все преобразование, примененное к Canvas. Существует один Canvas для всего окна, поэтому вы удаляете преобразование, применяемое для смещения на высоту ActionBar.

Вы также должны всегда вызывать метод Measure() для представлений. Некоторые представления ожидают, что этот вызов будет работать правильно.

person Romain Guy    schedule 14.12.2011
comment
Спасибо, Ромен. Сейчас я переписал свой код, чтобы убедиться, что я не удаляю исходную матрицу, вместо этого я добавляю соответствующий масштаб и переводы в существующую матрицу. Это определенно решает мою проблему. - person Neal Sanche; 14.12.2011
comment
Я также позабочусь о том, чтобы принять меры ко всем моим дочерним представлениям, как указано. - person Neal Sanche; 14.12.2011
comment
Если вы хотите узнать больше о настраиваемых макетах, посмотрите мой доклад на тему: переговоры .com/#id=2191&st=5 - person Romain Guy; 14.12.2011
comment
Ладно, так и сделаю. До сих пор мой макет работал, но дополнительные знания по этому вопросу всегда полезны. - person Neal Sanche; 22.12.2011