Всем привет! Я Максим Земляникин, пишу на Flutter 5 лет. И должен вам признаться, уже пол года как использую Mix вместо стандартных виджетов. А в этой статье хочу рассказать чем он мне так понравился
Начнем с небольшой базы. Mix — UI фреймворк, построенный поверх Flutter, значительно упрощающий вёрстку. В его основе лежат 3 концепции:
-
Атрибуты: они задают цвет, размер, отступы и другие параметры UI
-
Стиль: объединяет в себе список атрибутов
-
Box: принимает стиль и отрисовывает UI по его атрибутам
Можно представить, что стиль это BoxDecoration
, атрибут это его параметр, например цвет или радиус, а Box
это DecoratedBox
. По началу Mix и был обёрткой вокруг контейнера
А вообще можно еще короче!
Атрибуты не ограничиваются возможностью Container
-а. Есть ещё Opacity
, TextStyle
, Clip
, Visibility
, все виды Transform
и многое другое!
А теперь соединим все сказанное выше и добавим ещё один важный факт. Что будет, если два раза указать один атрибут, например цвет? Тогда применится последний. А это приводит к очень удобным последствиям:
-
Можно сделать базовый стиль с нужными цветами, отступами, тенями. И по надобности переопределять его, добавляя атрибут с другим цветом, отступами и чем угодно ещё
-
Можно удобно, очень удобно, просто невероятно удобно делать условия в стилях. К черту слова, просто посмотрите на код
-
А ещё эти изменения можно проанимировать!
Но вы можете мне возразить, что также просто можно воспользоваться AnimatedContainer-ом. А я напомню, что он не проанимирует Scale, TextStyle, Clip и многое другое! Вообще Mix и flutter_animate делают 90% анимаций донельзя простыми
Лично мне этого было бы уже достаточно. Но Mix состоит не из одного только Box виджета. В нем есть StyledText
, StyledIcon
, StyledImage
, HBox
, VBox
, ZBox
и другие виджеты. Все они умеют работать со стандартными атрибутами и имеют свои собственные
HBox
, VBox
и ZBox
виджеты — аналоги Row
, Column
и Stack
соответственно. Только они принимают параметры в стиле Mix, через атрибуты
Обратите внимание на еще один сахарок от Mix. Чтобы задать атрибуты, но не писать каждый раз $flex
или $stack
, я использовал chain
Styled*
виджеты рассмотрим на примере StyledText
. Его можно настроить атрибутами точно также как и виджет Text
через DefaulTextStyle
. Причем я не зря упомянул именно DefaulTextStyle
, ведь StyledText
тоже ищет свои атрибуты через контекст
Ладно, с основами разобрались. Теперь расскажу про его фишки, которые мне больше всего нравятся
Сахар
Как вы уже могли заметить, Mix подсластили не меньше чем Kotlin в сравнении с Java. Он использует много фишек Dart, типо возможности вызвать класс как функцию, опциональные параметры и chain вызовы методов через ..
. Добавили к этому огромную кучу helper методов, Inherited виджеты, хорошую документацию и покрытие тестами. Поэтому, хоть Mix и позиционирует себя в первую очередь как инструмент для дизайн систем, я нашел его наиболее удобным для повседневной верстки. Ну правда, зачем писать padding: EdgeInsets.symmetric(vertical: 10, horizontal: 8)
, когда можно обойтись $box.padding(10, 8)
? Да и читать такой код тоже проще, меньше шума
Директивы — изменяют содержимое виджета. К примеру $text.upperCase
сделает все буквы в StyledText
виджете заглавными! Или $box.color.withOpacity(0.5)
сделает любой цвет, который вы укажете в атрибуте $box.color
, полупрозрачным
Вложенность становится меньше. Так как в Mix свойства задаются списком атрибутов, элементы UI можно описать парой-тройкой виджетов. К примеру нам нужно задать стиль текста и обернуть в карточку с фоном, тенью и закруглением
Во первых Mix в этом коде выразительнее и короче. Но есть ещё одна важная особенность малой вложенности. Что если понадобится изменить этот виджет? К примеру добавить прозрачность всей карточке. В Mix в список атрибутов добавится $with.opacity(...)
. А вот без него придется обернуть всё в виджет Opacity
и на ревь diff будет не одна строка, а 15! Считаю это не очевидной, но очень важной особенностью
Дизайн системы
Для них Mix и был создан. Сначала расскажу до боли знакомую многим разработчикам историю. На проекте дизайнер нарисовал 3 типа кнопок: outlined, filled и text. В этих кнопках могли быть текст с иконками по бокам и loader. Плюс не активное состояние. Потом добавились маленькие версии этих кнопок: меньше отступы, иконки, шрифт и не растягиваются на ширину экрана. Дизайнера было уже не остановить, он добавил icon button — те же маленькие кнопки, но только с иконкой. И отполировал это постоянными изменениями. Привело это к каше в коде и багам в вёрстке
Как поможет Mix? Во первых стили можно вынести в отдельное место. Во вторых их можно разбить на базовый, filled, outlined и text. В эти стили можно добавить variants: маленький и большой. Это позволит один раз описать decoration, стили текста и иконок, и переиспользовать их в 3 виджетах, которые в свою очередь будут заниматься только layout-ом
Минусы
Дополнительный слой абстракции поверх Flutter. Во первых нужно учить ещё один UI framework, знать в какие виджеты он маппит атрибуты. Во вторых в нем есть свои скрытые концепции. Например он сортирует некоторые атрибуты. Хочу я задать ширину виджету, и поместить его в угол, пишу Style($with.sizedBox(), $with.align())
. А Mix меняет их местами, помещает виджет в углу SizedBox
, а не наоборот. И узнаю я об этом только запустив приложение. А почему так происходит выясню через пол часа, изучив все issues и код пакета
Некоторые вещи можно сделать несколькими способами. Отступ можно задать через $box.padding
или $with.padding
. Размер через $box.height
и $box.width
или $with.sizedBox
. причем второй вариант более гибкий, например в него можно передать Size. Если задаешь через $box
, то в итоге оно превращается в Container
, соответственно и разницы в порядке $box
атрибутов нет. А в случае $with
атрибутов порядок важен, но не со всеми, ведь некоторые он отсортирует. Иногда думаешь, какой бы атрибут использовать, разумеется выбираешь неправильный, переписываешь
Вместо заключения
Вот вы и дочитали до конца, а значит что-то вас зацепило. Дальше советую углубиться в документацию или посмотреть выпуск Observable Flutter про Mix (на английском).
ссылка на оригинал статьи https://habr.com/ru/articles/868626/
Добавить комментарий