Расширение RelativeLayout и переопределение dispatchDraw () для создания масштабируемой ViewGroup

Я видел, как несколько людей спрашивали, как увеличить масштаб всей ViewGroup (например, RelativeLayout) за один раз. На данный момент мне нужно этого добиться. Для меня наиболее очевидным подходом было бы сохранить коэффициент масштабирования как единственную переменную; и в каждом из методов onDraw () дочерних представлений этот масштабный коэффициент будет применяться к холсту до рисования графики.

Однако, прежде чем это сделать, я попытался проявить смекалку (ха - обычно плохая идея) и расширить RelativeLayout до класса ZoomableRelativeLayout. Моя идея состоит в том, что любое масштабное преобразование может быть применено только один раз к Canvas в переопределенной функции dispatchDraw (), так что не будет абсолютно никакой необходимости отдельно применять масштабирование в любом из дочерних представлений.

Вот что я сделал в своем ZoomableRelativeLayout. Это простое расширение RelativeLayout с переопределением dispatchDraw ():

protected void dispatchDraw(Canvas canvas){         
    canvas.save(Canvas.MATRIX_SAVE_FLAG);       
    canvas.scale(mScaleFactor, mScaleFactor);
    super.dispatchDraw(canvas);     
    canvas.restore();       
}

mScaleFactor управляется ScaleListener того же класса.

Это действительно работает. Я могу ущипнуть, чтобы увеличить масштаб ZoomableRelativeLayout, и все виды, удерживаемые внутри, правильно масштабируются вместе.

Только вот проблема. Некоторые из этих дочерних представлений являются анимированными, поэтому я периодически вызываю для них invalidate (). Когда масштаб равен 1, эти дочерние представления периодически перерисовываются идеально. Когда масштаб отличается от 1, эти анимированные дочерние представления обновляются только в части их области просмотра - или не обновляются вообще - в зависимости от масштаба масштабирования.

Изначально я думал, что когда вызывается метод invalidate () отдельного дочернего представления, он, возможно, перерисовывается системой индивидуально, а не передается Canvas из dispatchDraw () родительского RelativeLayout, что означает, что дочернее представление заканчивается обновляется без применения масштаба масштабирования. Но как ни странно, элементы дочерних представлений, которые перерисовываются на экране, имеют правильный масштаб масштабирования. Это почти как если бы область, которую система решает фактически обновить в резервном растровом изображении, осталась немасштабированной - если это имеет смысл. Другими словами, если у меня есть один анимированный дочерний вид, и я постепенно увеличиваю масштаб все дальше и дальше от исходного масштаба 1, и если мы поместим воображаемый прямоугольник в область, где находится этот дочерний вид, когда масштаб масштабирования равен 1 , то вызовы invalidate () вызывают только обновление графики в этом воображаемом блоке. Но графика для обновления сделана в правильном масштабе. Если вы увеличите масштаб до такой степени, что дочерний вид теперь полностью переместился с того места, где он был с масштабом 1, то никакая его часть не обновляется. Я приведу еще один пример: представьте, что мой дочерний вид - это шар, который оживает, переключаясь между желтым и красным. Если я немного увеличу масштаб, чтобы мяч двигался вправо и вниз, в определенный момент вы просто увидите, как верхняя левая четверть мяча оживляет цвета.

Если я постоянно увеличиваю и уменьшаю масштаб, я вижу, что дочерние представления анимируются правильно и полностью. Это потому, что перерисовывается вся ViewGroup.

Надеюсь, это имеет смысл; Я попытался объяснить как можно лучше. Я немного проиграл со своей стратегией масштабируемой ViewGroup? Есть ли другой способ?

Спасибо,

Trev

24
задан Swati Garg 17 October 2018 в 07:23
поделиться