Урок 146. Рисование. Canvas-преобразования. Методы save и restore.
Канва имеет свою матрицу, которая будет срабатывать для любого объекта, который вы собираетесь нарисовать. Методы настройки этой матрицы нам уже известны из Урока 144:
- translate (перемещение)- scale (изменение размера)- rotate (поворот)- skew (наклон)
У канвы эти методы являются pre-методами. Т.е. помещают преобразование в начало матрицы, сохраняя остальные.
Рассмотрим это на примере.
ПреобразованияProject name: P1461_CanvasTransform Build Target: Android 2.3.3 Application name: CanvasTransform Package name: ru.startandroid.develop.p1461canvastransform Create Activity: MainActivity
MainActivity.java:
Рисуем черным цветом path с прямоугольником. Затем настраиваем матрицу на поворот на 30 градусов относительно точки (0,0) (т.к. не указана иная) и на перемещение на 500 вправо. Т.к. используем методы pre, то сначала будет перемещение, потом поворот. Преобразуем path и выводим синим цветом.
Попробуем сделать то же самое, с помощью канвы.
Перепишем onDraw:
Сначала выводим прямоугольник rectf черным цветом. Затем настраиваем матрицу канвы. Задаем те же преобразования, в том же порядке. Т.к. эти методы являются аналогами pre-методов, то сначала выполнится перемещение, затем поворот.
Матрица канвы настроена, теперь все объекты, которые мы будем рисовать на канве, будут преобразованы согласно ее матрице. Нарисуем тот же прямоугольник rectf зеленым цветом.
Заметьте, что мы никак не преобразуем rectf. Он остается с теми же координатами. Канва сама преобразует его при рисовании.
Зеленый прямоугольник находится там же, где в прошлый раз был синий. Т.е. преобразования с помощью отдельной матрицы идентичны преобразованиям матрицы канвы.
Сохранение и возврат состоянияМы можем запоминать состояние матрицы канвы и потом восстанавливать его.
Рассмотрим это на примерах. Перепишем DrawView:
Нарисуем пару квадратов, первый - зеленым цветом, а второй - синим.
Без всяких преобразований они выглядят так:
Перепишем onDraw:
Несколько раз настраиваем перемещение на 100 вправо и каждый раз рисуем первый квадрат зеленым цветом. Затем сбрасываем матрицу канвы методом restore в изначальное состояние. И рисуем второй квадрат синим цветом.
Видим, что первый (зеленый) квадрат рисовался со смещением согласно настройкам канвы, а метод restore все эти настройки преобразования сбросил и второй (синий) квадрат был нарисован без преобразований.
Можно настроить канву так, что метод restore будет сбрасывать ее настройки не в изначальное, а в промежуточное, сохраненное нами, состояние.
Перепишем onDraw:
Снова несколько раз настраиваем перемещение на 100 вправо и каждый раз рисуем первый квадрат зеленым цветом. Затем для канвы выполняем метод save. Он запомнит текущие настройки матрицы. Далее еще пару раз перемещаем вправо на 100 и рисуем первый квадрат, но уже красным цветом, чтобы визуально отличить вывод до и после сохранения канвы.
Затем выполняем метод restore, который сбросит канву в состояние, которые было сохранено методом save. И рисуем второй квадрат синим цветом.
Видим, что второй (синий) квадрат нарисован с тем состоянием канвы, которое было сохранено методом save. Метод restore вернул нас к нему из текущего состояния.
Сохранение методом save не затирает предыдущее сохраненное состояние. Т.е. вы можете несколько раз вызывать save и все эти состояния будут хранится в некоем стеке. А методом restore состояния из этого стека вытаскивать.
Перепишем onDraw:
Мы несколько раз применяем перемещение на 100, рисуя первый квадрат. При этом периодически сохраняем состояние матрицы методом save, при этом меняя цвет для более удобного визуального восприятия.
Далее, мы несколько раз вызываем метод restore, который возвращает канву в сохраненные ранее состояния и рисуем второй квадрат. В итоге мы приходим к изначальному состоянию канвы.
Метод save возвращает нам int значение. Это значение мы можем передать в метод restoreToCount и матрица вернется к указанному состоянию, минуя остальные.
Перепишем onDraw:
Мы запоминаем состояние в самом начале и сохраняем значение метода save в переменную initSave. Далее мы выполняем перемещения, несколько раз сохраняем канву, и один раз пишем значение сохранения в needSave.
Затем мы возвращаемся к сохраненным состояниям, используя метод restoreToCount и переменные initSave и needSave.
В прошлом примере мы методом restore перебирали все сохраненные состояния. А здесь метод restoreToCount позволил нам вернуться сразу к необходимому состоянию.
И напоследок еще три метода канвы
setMatrix(Matrix matrix) – меняет матрицу канвы на указанную матрицу
getMatrix() – позволяет получить копию матрицы канвы
concat(Matrix matrix) – добавляем в начало текущей матрицы преобразования из указанной матрицы
На следующем уроке:
Присоединяйтесь к нам в Telegram:
- в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.
- в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование
- ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня
- новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме