В предыдущем параграфе мы рассмотрели нюансы RenderObject, а ещё ранее — анимирование. В этом и двух последующих параграфах мы объединим эти концепции: посмотрим, как можно частично обновлять интерфейс с помощью слоёв, доступных в RenderObject через объект PaintingContext и познакомимся с принципами построения многослойного изображения.
После вы сможете:
Приступим!
Начнём чуть издалека.
В приложениях на Flutter можно создавать плавный интерфейс произвольной сложности с поддержкой анимации. Часто при анимации изменяется только часть экрана, а изменения сводятся к движению уже готовых элементов интерфейса.
Чтобы анимация оставалась плавной даже в сложных приложениях, необходимо понимать, как Flutter управляет обновлением отдельных частей экрана и рендерит слои изображений.
В этом случае можно сберечь ресурсы графического процессора и использовать заранее построенное растровое изображение виджета. Эта возможность реализуется во Flutter с помощью слоёв. Слои поддерживают оба движка — и первоначальный, но устаревающий движок Skia, и новый движок Impeller.
Слои создаются с помощью класса PaintingContext.
<aside>
PaintingContext — это объект, предоставляющий методы для рисования (paint) и управления потомками в дереве рендеринга. Он используется в методе paint классов, наследующихся от RenderObject.
</aside>
PaintingContext абстрагирует низкоуровневую отрисовку и упрощает реализацию paint() в кастомных RenderObject.
Но прежде чем поговорить о слоях, давайте сперва вспомним, как устроен процесс отрисовки приложения на экране:
build, и из Stateless/Stateful-виджетов создаётся полное дерево виджетов, состоящих из наследников классов ProxyWidget и RenderObjectWidget.RenderObjectWidget создаются объекты классов-наследников RenderObject, которые содержат код для определения собственных размеров, позиционирования дочерних RenderObject и отрисовки визуального представления RenderObject на экране.RenderObject отрисовка происходит на Canvas, при этом каждый RenderObject использует относительные координаты и размещается относительно родительского RenderObject или всей поверхности для рисования для устройства, если родителем является корневой RenderView.Давайте разберём каждый из этапов подробнее. Для удобства, первые два мы объединили вместе.