Всем привет! Я Максим Земляникин, пишу на Flutter 5 лет. И должен вам признаться, уже пол года как использую Mix вместо стандартных виджетов. А в этой статье хочу рассказать чем он мне так понравился

Начнем с небольшой базы. Mix - UI фреймворк, построенный поверх Flutter, значительно упрощающий вёрстку. В его основе лежат 3 концепции:

  • Атрибуты: они задают цвет, размер, отступы и другие параметры UI

  • Стиль: объединяет в себе список атрибутов

  • Box: принимает стиль и отрисовывает UI по его атрибутам

Можно представить, что стиль это BoxDecoration, атрибут это его параметр, например цвет или радиус, а Box это DecoratedBox. По началу Mix и был обёрткой вокруг контейнера

А вообще можно еще короче!

Атрибуты не ограничиваются возможностью Container-а. Есть ещё Opacity, TextStyle, Clip, Visibility, все виды Transform и многое другое!

А теперь соединим все сказанное выше и добавим ещё один важный факт. Что будет, если два раза указать один атрибут, например цвет? Тогда применится последний. А это приводит к очень удобным последствиям:

  1. Можно сделать базовый стиль с нужными цветами, отступами, тенями. И по надобности переопределять его, добавляя атрибут с другим цветом, отступами и чем угодно ещё

  2. Можно удобно, очень удобно, просто невероятно удобно делать условия в стилях. К черту слова, просто посмотрите на код

  3. А ещё эти изменения можно проанимировать!

Но вы можете мне возразить, что также просто можно воспользоваться 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 (на английском).

Комментарии (2)


  1. VailStrawb
    23.12.2024 10:53

    Очень интересно, спасибо за статью : )


  1. ChessMax
    23.12.2024 10:53

    В пункте о дизайн системе было бы неплохо прямо код показать как эти три вида кнопок в двух размерах будут выглядеть. Знак доллара очень неприятно смотрится (привет PHP). Фактически это шум. В дарт такое не принято. Есть ли в этом какой-то скрытый смысл?
    Задумка интересная, но конкретную реализацию, я бы в свой проект не потащил.