
В версии Dart 2.7 нам представили расширения, позволяющие разработчикам добавлять новые функциональные возможности в уже существующие типы. Расширения могут быть отличным помощником не только, когда мы пишем бизнес-логику, но и когда у нас есть другие задачи! Примером такой задачи может служить работа с виджетами.
Исходя из своего опыта разработки под iOS, вдохновившись ViewModifier из SwiftUI, я захотел разобраться в том, как использовать Dart расширения аналогичным образом, чтобы уменьшить визуальный беспорядок, который получается при большой вложенности дерева виджетов.
Давайте рассмотрим пример!
Вариант с вложенными виджетам
Ниже представлен MyWidget виджет c текстом внутри Padding (из стандартного примера с dartpad.dev).
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return
Padding(
padding: const EdgeInsets.all(16),
child: Text('Hello, World!', style: Theme.of(context).textTheme.headline4)
);
}
}Теперь давайте разберёмся, как мы можем сделать то же самое с помощью Dart расширений.
Вариант с раширениями
Создаем расширение для класса Widget c методом padding. При вызове данного метода объект будет обернут в Padding:
extension WidgetModifier on Widget {
Widget padding([EdgeInsetsGeometry value = const EdgeInsets.all(16)]) {
return Padding(
padding: value,
child: this,
);
}
}С новым расширением мы можем обновить MyWidget следующим образом:
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Text('Hello, World!', style: Theme.of(context).textTheme.headline4)
.padding();
}
}Пусть пример совсем не большой, но я надеюсь, что вы уловили суть! Мы используем метод расширения в качестве синтаксического сахара для компоновки, вместо того, чтобы вкладывать виджеты друг в друга.
Точно так же мы можем добавить в наше расширение еще функции и с их помощью создать более сложные пользовательские интерфейсы:
extension WidgetModifier on Widget {
// ...
Widget background(Color color) { // заливка
return DecoratedBox(
decoration: BoxDecoration(
color: color,
),
child: this,
);
}
Widget cornerRadius(BorderRadiusGeometry radius) { // закругление углов
return ClipRRect(
borderRadius: radius,
child: this,
);
}
Widget align([AlignmentGeometry alignment = Alignment.center]) { // выравнивание
return Align(
alignment: alignment,
child: this,
);
}
}class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Text('Hello, World!', style: Theme.of(context).textTheme.headline4)
.padding()
.background(Colors.lightBlue)
.cornerRadius(BorderRadius.all(Radius.circular(8.0)))
.padding(EdgeInsets.symmetric(horizontal: 8, vertical: 16))
.background(Colors.purple);
}
}
Посмотреть на dartpad.dev
Разве это не прекрасно? Теперь у нас есть чистый и элегантный виджет, который мы можем легко понять! Представьте себе, сколько уровней вложенных виджетов вам придется использовать, чтобы воссоздать это представление без расширений.
Заключение
В этой статье мы рассмотрели альтернативный подход к формированию дерева виджетов во Flutter проекте, применив концепцию, аналогичную ViewModifier из SwiftUI. При таком подходе мы можем упрощать деревья виджетов, уменьшая их вложенность. И я продемонстрировал лишь несколько примеров таких расширений, но по такому же принципу можно создать много новых для других случаев, где они будут так же полезны.
Спасибо за внимание! Надеюсь, ��то вы найдете этот пост полезным. Если у вас есть какие-либо вопросы или комментарии по поводу данного материала, не стесняйтесь обращаться ко мне в Twitter!
До следующего раза!
