Flutter. Много
2.92K subscribers
463 photos
24 videos
286 links
Заказать мобильную разработку: https://amiga.ru//?utm_source=tg
Заказать рекламу в канале @amiga_agency_bot

Новости Flutter-разработки, дайджесты мероприятий, личный опыт.
Download Telegram
Hola, Amigos! На связи Павел Гершевич, Mobile Team Lead в Amiga. В этой небольшой серии мы разберем, как кастомизировать виджеты Slider и RangeSlider, чтобы они лучше соответствовали вашему дизайну.

Делается это как и внутри самого виджета, так и через тему. Начнём с простого кейса: внешний вид слайдера нас устраивает, но нужно изменить только цветовую схему.


Slider(
… // Основные настройки слайдера
activeColor: Colors.red,
inactiveColor: Colors.blue,
overlayColor: WidgetStatePropertyAll(Colors.green),
);


Эти три параметра позволяют быстро адаптировать внешний вид Slider:
• activeColor отвечает за цвет активной части полосы — от начального значения до текущей позиции, а также за цвет индикатора выбранного значения;
• inactiveColor задаёт цвет неактивной части полосы;
• overlayColor позволяет перекрасить цвет выделения, которое показывается при перемещении индикатора.

Те же настройки доступны и для RangeSlider.

Если нужно применять стили сразу ко всем слайдерам в приложении, удобнее вынести их в тему:


SliderThemeData(
activeTrackColor: Colors.red,
thumbColor: Colors.red,
inactiveTrackColor: Colors.blue,
overlayColor: Colors.green,
)


Как мы видим, свойство activeColor - разделилось на два: activeTrackColor отвечает за полосу, а thumbColor за индикатор выбранного значения. Кроме этого, тема позволяет кастомизировать и цвета для отключенных виджетов при помощи таких же свойств, только с префиксом disabled.

В следующей части поговорим о более глубокой кастомизации — разберём, как создать собственный индикатор выбранного значения для Slider и RangeSlider.

А пока делитесь в комментариях: приходилось ли вам менять стандартный вид этих виджетов? Какие настройки использовали?
🔥4❤1
Hola, Amigos! На связи Павел Гершевич, Mobile Team Lead в Amiga. В прошлой части мы рассмотрели базовую кастомизацию виджетов Slider и RangeSlider. Сегодня мы углубимся в детали и изменим внешний вид индикатора у слайдера.

Для этого нам нужно будет создать отдельный класс, который наследуется от SliderComponentShape для Slider или RangeSliderThumbShape для RangeSlider:


class AppThumbShape extends SliderComponentShape
class AppRangeThumbShape extends RangeSliderThumbShape


Сначала, нам нужно задать размер нашего индикатора. В нашем примере он круглый, поэтому идем от радиуса большего круга.


@override
Size getPrefferedSize(bool isEnabled, bool isDiscrete) => Size.fromRadius(8);


Далее наступает момент отрисовать на канвасе. Делается это точно также как и при использовании CustomPaint, только свойства у методов немного другие. Давайте на них посмотрим.

Для SliderComponentShape это:
• PaintingContext, который нам и выдает канвас для отрисовки;
• Offset center - координаты центра канваса;
• activationAnimation и enableAnimation - анимации начала взаимодействия и включения / выключения слайдера;
• sliderTheme - тема для получения цветов и всего необходимого, что мы уже настроили ранее;

Остальные параметры могут быть не настолько полезны, кроме тех, что используются при отрисовке текста. Например, выбранного значения.

Для RangeSliderThumbShape добавляются:
• bool isOnTop - показывает, находится ли этот индикатор над другим;
• Thumb thumb - какой это именно индикатор - в начале или в конце интервала.

Давайте нарисуем наш индикатор для обычного Slider:


@override
void paint(
PaintingContext context,
Offset center, {
required Animation<double> activationAnimation,
required Animation<double> enableAnimation,
required bool isDiscrete,
required TextPainter labelPainter,
required RenderBox parentBox,
required SliderThemeData sliderTheme,
required TextDirection textDirection,
required double value,
required double textScaleFactor,
required Size sizeWithOverflow,
) {
final canvas = context.canvas;
final redPaint = Paint()
..color = Colors.red
..style = PaintingStyle.fill;
final whitePaint = Paint()
..color = Colors.white
..style = PaintingStyle.fill;

canvas
..drawCircle(center, 8, redPaint)
..drawCircle(center, 6, whitePaint)
..drawCircle(center, 3, redPaint);
}


Теперь нужно добавить наш готовый индикатор в тему:


SliderThemeData(
…,
thumbShape: AppThumbShape(),
rangeThumbShape: AppRangeThumbShape(),
)


В следующей части мы рассмотрим, как кастомизировать полосу со значениями.

Пишите в комментариях, если уже пробовали кастомизировать слайдеры своими руками! 👇
❤3
Hola, Amigos! На связи Павел Гершевич, Mobile Team Lead в Amiga. В прошлых частях мы разобрали базовую кастомизацию виджетов Slider и RangeSlider, а также замену индикатора на собственный. Сегодня мы займемся изменением полосы значений (Track) под наш дизайн.

Для этого нам так же, как и с индикатором, нужно создать отдельный класс, наследуемый от SliderTrackShape для Slider и RangeSliderTrackShape для RangeSlider.

Данные классы отличаются от тех, которые мы применяли в прошлой части, так как вместо метода на получение размера, тут есть метод на получение объекта Rect. Для примера выберем самое простое - задать только размеры:


@override
Rect getPreferredRect({
required RenderBox parentBox,
Offset offset = Offset.zero,
required SliderThemeData sliderTheme,
bool isEnabled,
bool isDiscrete
}) {
return Rect.fromTLWH(0, 0, parentBox.constraints.width, 8.0);
}


После чего переопределяем метод для отрисовки. В нашем примере полоса всегда будет одинаковой, поэтому мы рисуем только один RRect:


@override
void void paint(
PaintingContext context,
Offset offset, {
required RenderBox parentBox,
required SliderThemeData sliderTheme,
required Animation<double> enableAnimation,
required Offset thumbCenter,
Offset? secondaryOffset,
bool? isEnabled,
bool? isDiscrete,
required TextDirection textDirection
}) {
final trackRect = Rect.fromTLWH(0, 0, parentBox.constraints.width, 8.0);
final trackRRect = RRect.fromRectAndRadius(trackRect, Radius.circular(4);

final redPaint = Paint()
..color = Colors.red
..strokeWidth = 2.0
..style = PaintingStyle.stroke;
final whitePaint = Paint()
..color = Colors.white
..style = PaintingStyle.fill;

canvas
..drawRRect(trackRRect, whitePaint)
..drawRRect(trackRRect, redPaint);
}


Если вы хотите показывать часть полосы до индикатора одним стилем, а после - другим, то на помощь придет свойство thumbCenter. Оно означает координаты центра индикатора:


final trackRectBefore = Rect.fromPoints(
Offset.zero,
Offset(thumbCenter.dx, 8.0),
);
final trackRectAfter = Rect.fromPoints(
Offset(thumbCenter.dx, 0),
Offset(parentBox.constraints.width, 8.0),
);


Для RangeSliderTrackShape будут доступны два таких свойства - startThumbCenter и endThumbCenter. С их помощью можно разделить трек на три зоны: неактивную область до начального индикатора, активную область между индикаторами и неактивную область после конечного индикатора.

Для того, чтобы применить наш стиль нужно добавить классы к теме:


SliderThemeData(
…,
trackShape: AppSliderTrackShape(),
rangeTrackShape: AppRangeSliderTrackShape(),
)


Небольшая рекомендация от нас - если применяете собственную отрисовку трека, то лучше всего Slider будет оборачивать в SizedBox для лучшего позиционирования на экране.

Рассказывайте в комментариях, кастомизацию каких виджетов хотели бы увидеть? 🙂
Please open Telegram to view this post
VIEW IN TELEGRAM
1👌2🔥1
Hola, Amigos! Сегодня мы вводим новую рубрику - обзоры правил для статического анализатора #lintRules.

В ней мы будем рассказывать о тех правилах, которыми пользуемся сами на наших проектах.

Поэтому ловите первую подборку. А также рассказывайте в комментариях, про какие правила рассказать в следующий раз?
👍17
Hola, Amigos! Сегодня посмотрим на один пакет, который может быть полезен в разработке - paged_vertical_calendar.

Он выводит календарь непрерывным вертикальным списком вместо одного месяца переключением. Это полезно в таких случаях:
⭕️ Нужно показать сразу несколько месяцев;
⭕️ Есть выбор интервала дат, которые могут быть в разных месяцах;
⭕️ Нужен другой UX, чем стандартный.

Давайте разберем его базовое использование:


PagedVerticalCalendar(
minDate: DateTime.now().subtract(Duration(days 365)),
maxDate: DateTime.now().add(Duration(days 365)),
initialDate: DateTime.now().add(Duration(days 3)),
invisibleMonthsThreshold: 1,
startWeekWithSunday: true,
onMonthLoaded: (year, month) {
// on month widget load
},
onDayPressed: (value) {
// on day widget pressed
},
onPaginationCompleted: (direction) {
// on pagination completion
},
);


Пройдемся по его параметрам:
• minDate и maxDate помогают нам сделать календарь не бесконечным;
• initialDate - дата начального месяца, который будет показан пользователю посередине списка;
• invisibleMonthThreshold - количество месяцев, которые пользователь не видит, но они просчитываются для дальнейшего отображения;
• startWeekWithSunday - полезное свойство, если приложение работает в странах, где неделя начинается с воскресенья, а не с понедельника;
• onMonthLoaded, onPaginationCompleted - обратные вызовы, которые помогают подгружать данные, если это нужно;
• onDayPressed - обработка нажатия на какой-либо день.

Так как это все-таки список, то ему доступны еще параметры, которые есть у других похожих виджетов - controller, physics, addAutomaticKeepAlives и reverse.

Но самое интересное и важное, что такой календарь можно максимально кастомизировать под себя следующими параметрами:
• dayAspectRatio - помогает задать соотношение сторон для виджета дня;
• weekdaysToHide - скрывает дни недели, если нужно показать только определенные. Например, только рабочие дни;
• listPadding - позволяет задать отступы у списка;
• monthBuilder - позволяет кастомизировать шапку месяца под себя;
• dayBuilder - позволяет кастомизировать отображение дня на календаре.

Рассказывайте, решали ли уже подобные задачи и пользовались ли этим пакетом в своих проектах?
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8❤1🔥1
Дайджест июля

Hola, Amigos! Собрали в одну подборку все полезные посты июля, которые вы могли пропустить. Выбирайте, что интересно, и переходите по ссылкам для полезного выходного чтива:

🔴Организация импортов в проекте;
🔴Обзоры виджетов OverflowBar и SliverMainAxisGroup;
🔴Кастомизация виджета Slider - Часть 1. Часть 2. Часть 3;
🔴Правила статического анализа;
🔴Обзор пакета paged_vertical_calendar.

Всем хорошего кода!
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3
Hola, Amigos! Сегодня вышли Flutter 3.47 и Dart 3.13. Давайте вместе разберемся, что в них нового.

Самое главное и важное изменение - библиотеки Material и Cupertino стали отдельными и доступны на pub.dev как material_ui и cupertino_ui.

Кроме этого, есть важные новости по операционным системам от Apple:
• Повышены минимальные версии до iOS 15 и macOS 12;
• Переход на UIScene становится обязательным, так как Xcode 27 перестанет собирать приложения без него;
• Появилась возможность отключения сборки под macOS на процессорах Intel;
• Разработчики Flutter сообщают, что 92 из 100 пакетов из топа pub.dev перехали на Swift Package Manager.
Если вы еще не совершили миграции на UIScene и SPM, то сейчас самое время.

Касаемо других платформ:
• Теперь можно собирать релизный Flutter Web на WASM при помощи команды flutter build web --release --wasm;
• Impeller теперь используется по умолчанию на десктопе;
• Добавили flavor’ы для Windows и Linux.

Обновления Dart принесло нам новые конструкторы и новый способ объявления классов.

А также Flutter 3.47 и Dart 3.13 получили много исправлений.

Делитесь в комментариях, мигрировали ли вы свои приложения на UIScene и SPM?
❤3🔥3👍1