cookie

Мы используем файлы cookie для улучшения сервиса. Нажав кнопку «Принять все», вы соглашаетесь с использованием cookies.

avatar

Flutter. Много

Заказать мобильную разработку: https://amiga.agency/?utm_source=tg Заказать рекламу в канале @amiga_agency_bot Новости Flutter-разработки, дайджесты мероприятий, личный опыт.

Больше
Рекламные посты
2 660
Подписчики
-1724 часа
-217 дней
+18230 дней

Загрузка данных...

Прирост подписчиков

Загрузка данных...

Фото недоступноПоказать в Telegram
Hola, Amigos! На связи Павел Гершевич, Flutter Team Lead в Amiga. Продолжаем рассказывать, в чем разница между go_router и auto_route. Количество багов и костылей На личном опыте можем сказать, что с go_router костылей и правок, которых нужно исправлять вручную, всегда больше, чем с auto_route. Да, первые версии могли пропускать кадры при переходах, но со временем это исправили. Вложенная навигация В auto_route вложенная навигация устроена намного удобнее, чем в go_router. Так как у нас есть возможность создать дополнительный роутер внутри нашего экрана и переходить внутри него.

Scaffold(
  …
  body: AutoRoute(),
  …
);
Да, go_router поддерживает такое, но настройка будет в разы сложнее. Route Guards Настройка guards в go_router делается при настройке самого роутера, а перенаправление — при помощи функции redirect. В auto_route мы можем создавать именно отдельные Route Guards и присваивать их путям в наших настройках. Было полезно? Если у вас еще остались вопросы, то пишите в чат.
Показать все...
4👍 3🔥 1
Фото недоступноПоказать в Telegram
Hola, Amigos! На связи Павел Гершевич, Flutter Team Lead в Amiga. Недавно в чате вы спрашивали, в чем разница между go_router и auto_route. Рассказываем! Сходства Обе этих библиотеки работают на Navigator 2.0, что дает нам больший контроль над навигацией в наших приложениях. Также часть функционала в них совпадает. Количество кода В auto_route мы пишем намного меньше кода, так как используется кодогенерация. Но некоторые не любят ее, поэтому используют GoRouter. Также auto_route позволяет нам напрямую передавать нужные аргументы прямо в Route, не используя дополнительный код. Разберем на примере вот такого экрана:

class HomePage extends StatelessWidget {
    final String appName;
    const HomePage({required this.appName, super.key});
    … 
}
Для auto_route у нас будет:

AutoRoute(page: HomeRoute.page);

context.router.push(HomeRoute(appName: ‘My App Name’));
А для go_router:

GoRoute(
  path: ‘/home’,
  builder: (context, state) {
    final appName = state.queryParams[‘appName’];
    return HomePage(appName: appName);
  }
);

GoRouter.of(context).push(‘/home?appName=”My App Name”’);
В следующей части поговорим о количестве багов, вложенной навигации и Route Guards. А пока на этом всё, пишите в чате, было ли полезно?
Показать все...
10👍 2🔥 1
Фото недоступноПоказать в Telegram
Hola, Amigos! Лето богато на события, поэтому мы снова с анонсом. 29-30 августа приглашаем вас на BOOST — это крупнейшая конференция для руководителей студий и агентств 🅰️ Соберется 1000 IT-специалистов из разных направлений: менеджмент, разработка, дизайн, креатив, продажи, PR и маркетинг. Мы уже готовим свои доклады, о которых расскажем чуть позже, а пока знакомьтесь с программой по ссылке. Успейте купить билет по самой выгодной стоимости, ведь цена будет расти! И ловите наш промокод AMIGA10, который дарит скидку 10% 🙂 До встречи на BOOST!
Показать все...
🔥 5 2🥰 2
Фото недоступноПоказать в Telegram
Hola, Amigos! На связи Михаил Чернецов, Flutter dev в Amiga. Как и обещали, сегодня расскажем про Route Guard. Он позволяет манипулировать навигацией в самом приложение и переводить пользователя на необходимый экран.

class AuthGuard extends AutoRouteGuard {

  @override
  void onNavigation(NavigationResolver resolver, StackRouter router) {
    final authenticated = myService().authenticated;
    if  (authenticated) {
      resolver.next(true);
    }
    else {
      resolver.redirect(const AuthRoute());
    }
  }
}
Единственная проблема — это необходимость использовать или глобальные переменные или каждый раз инициализировать сервисы для проверки каких-то данных. Для этого RouteGuard, можно пометить аннотацией @injectable из одноименной библиотеки, и можно туда передать уже существующий синглтон.

@injectable
class AuthGuard extends AutoRouteGuard {
  final MySingleton singleton;

  AuthGuard({required this.singleton});

  @override
  void onNavigation(NavigationResolver resolver, StackRouter router) {
    final authenticated = singleton.isAuth;
    …..,
  }
}
Добавление же AuthGuard в роут тоже достаточно просто:

AutoRoute(
  page: HomeRoute.page,
  guards: [
AuthGuard(),
  ],
),
Или в случае использования injectable/getIt:
GetIt.instance<AuthGuard>().
Route wrapper позволяет оборачивает роут. Используя аннотацию AutoRouteWrapper.

@RoutePage()
class ProductsScreen extends StatelessWidget implements AutoRouteWrapper {
  
  @override
  Widget wrappedRoute(BuildContext context) {
    return Provider(create: (ctx) => ProductsBloc(), child: this);
  }
  ...
}
Самое интересное то, что дочерний Route не только будет иметь доступ к блоку, но и может быть обернут, например, в Scaffold с AppBar. На этом наша серия постов о библиотеке auto_route подошла к концу. Делитесь в комментариях, было ли полезно?
Показать все...
🔥 3
Фото недоступноПоказать в Telegram
Hola, Amigos! На связи Михаил Чернецов, Flutter dev в Amiga. Продолжаем нашу серию постов о библиотеке auto_route. И во второй части поговорим о вложенной навигации, анимациях и многомодульности. Вложенная навигация (Nested Navigation) используется для роутов с несколькими вложенными вкладками.в AutoRoute содержит поле children, в который можно передать список AutoRoute. И при помощи виджета AutoRouter организовать автоматическую навигацию между вложенными страницами.
AutoRoute(
  page: BottomNavRoute.page,
  children: [
    AutoRoute(page: HomeRoute.page),
    AutoRoute(page: ListRoute.page),
    ...
  ],
);
  @override
  Widget build(BuildContext context) {
    return Scaffold(
 body: AutoRouter(),
      bottomNavigationBar: BottomNavigationBar(
        /// Navigate here
      ),
    );
  }
}
Анимация при навигации Используем transitionBuilder и создаём собственный вариант перехода для анимации роута.
CustomRoute(
  page: ZoomInScreen,
  transitionsBuilder:
    (BuildContext context, Animation<double> animation, _, Widget child) {
      return ScaleTransition(scale: animation, child: child);
  },
)
Многомодульность При вводе бойлерплейт генерируется модуль для всех роутов модуля.
@AutoRouterConfig.module()
class MyPackageModule extends $MyPackageModule {}
При добавлении модуля, AppRouter получает доступ ко всей информации о роутах MyPackageModule. Однако, как и при обычной генерации, все роуты необходимо прописать в класс AppRouter.
@AutoRouterConfig([
MyPackageModule,
…
])
class AppRouter extends $AppRouter {
 @override
  List<AutoRoute> get routes => [
     AutoRoute(page: HomeRoute.page),
…
 ];
}
В следующий раз расскажем про RouteGuard и их применение. Всем хорошего кода! Делитесь в чате своим опытом работы с библиотекой.
Показать все...
5🔥 4👍 3
Фото недоступноПоказать в Telegram
Hola, Amigos! На связи Михаил Чернецов, Flutter dev в Amiga. Сегодня расскажу про пакет auto_route, который создает роуты для приложения с помощью кодогенерации. Он поддерживает deeplinks, с помощью которых можно открыть приложение на необходимой странице: например ссылка в письме, ведущая на сделанный пользователем заказ. А также Route Guard, который создатели библиотеки сравнивают с интерсептором для навигации, но о нем чуть позже. Для создание конфигурации роутера необходимо создать класс роутера:

@AutoRouterConfig()
class AppRouter extends $AppRouter {

 @override
 List<AutoRoute> get routes => [
    AutoRoute(page: HomeRoute.page),
 ];
}
Для получения HomeRoute, необходимо пометить аннотацией RoutePage HomeScreen. Причем в стандартной настройке Screen и Page в названии страницы заменяются на Route.

@RoutePage()
class HomeScreen extends StatefulWidget {}
В роуты также можно передавать параметры, при этом сохраняются стандартные значения и учитывается наличие поля required.

context.router.push(BookRoute(bookId: id));
Для того, что бы им можно было пользоваться, необходимо добавить роутер в приложение:

final _appRouter = AppRouter();

  @override
  Widget build(BuildContext context){
    return MaterialApp.router(
      routerConfig: _appRouter.config(),
    );
  }
Далее с помощью extension над context можем получать router, имеющий такое же api как у navigator и так же использует навигацию через стек. – maybePop — по возможности убирает последний роут из стека. – push — добавляет в стек новый роут. – replace — заменяет текущий роут на другой. При этом не меняет стек роутов. – remove — убирает определенный роут из стека. – navigate — если роут в стеке, убирает роуты до того, как попадется необходимый или добавляет роут в стек. Большая часть остальных методов является просто комбинацией из этих 5-ти. Всем хорошего кода! Делитесь в чате своим опытом работы с библиотекой.
Показать все...
🔥 8👍 5👏 3👎 2 1😢 1
00:48
Видео недоступноПоказать в Telegram
Hola, Amigos! На связи Владимир Зевеке, Flutter dev в Amiga. Сегодня поговорим о пакете audio_waveforms. Этот пакет добавляет возможность записывать аудиофайлы и воспроизводить их в отдельном виджете, с красивым визуальным шлейфом звуков. Он особенно полезен для разработки чатов. Установка и настройка Для установки нам нужно подключить пакет и следуя инструкции из pub.dev добавить разрешение на использование микрофона для необходимых платформ. Инициализация Создаем поля для виджетов записи и воспроизведения аудио:

late final RecorderController recorderController;
late final PlayerController playerController
Инициализируем контроллеры:

@override
void initState() {
  recorderController = RecorderController()
    ..androidEncoder = AndroidEncoder.aac
    ..androidOutputFormat = AndroidOutputFormat.mpeg4
    ..iosEncoder = IosEncoder.kAudioFormatMPEG4AAC
    ..sampleRate = 16000;

  playerController = PlayerController();
  super.initState();
}
Не забываем освобождать ресурсы:

@override
void dispose() {
  recorderController.dispose();
  playerController.dispose();
  super.dispose();
}
Запись и воспроизведение Для записи нужно проверить дал ли пользователь разрешение на использование микрофона:

final bool hasPermission = await recorderController.checkPermission();
Если оно у нас есть, то мы можем запустить запись, вызвав:

await recorderController.record();
Или остановить запись при помощи:

String pathAudio = await recorderController.stop() ?? '';
await playerController.preparePlayer(path: pathAudio);
Для проигрывания используем метод:

await playerController.startPlayer(finishMode: FinishMode.pause);
Для завершения вызываем:

await playerController.pausePlayer();
Для вывода на экран понадобятся виджеты AudioWaveforms и AudioFileWaveforms. Они легко настраиваются с помощью полей waveStyle и playerWaveStyle, которые предлагают множество опций для кастомизации.

AudioWaveforms(
size: const Size(double.infinity, 50.0),
recorderController: recorderController,
),
Пакет также поддерживает различные слушатели для работы контроллеров, что делает его гибким и мощным инструментом для разработки. Использовали ли вы пакет audio_waveforms в своих проектах? Расскажите о своем опыте в чате.
Показать все...
IMG_8943.MP42.12 MB
👍 15🔥 5💘 2👏 1
Hola, Amigos! На связи Михаил Чернецов, Flutter dev в Amiga. Сегодня поговорим про Injectable — мощный пакет для управления зависимостями в приложении. Injectable является оберткой над GetIt и помогает создавать Dependency Injection (DI) с помощью кодогенерации, избавляя от необходимости вручную редактировать файл с зависимостями ⚙️ GetIt — это популярный service locator, который позволяет централизованно управлять зависимостями в приложении. Однако, некоторые считают service locator антипаттерном, так как он может нарушать принципы SOLID и инкапсуляции. Основные возможности Injectable Injectable создает файл, который автоматически регистрирует сервисы, синглтоны и модули. Для добавления модуля достаточно пометить класс аннотацией @injectable. Этот класс затем будет доступен через GetIt.instance<YourService>(). Вы также можете объявить синглтоны с помощью аннотаций @singleton и @lazysingleton. Пример использования Чтобы подключить сторонние зависимости, такие как dio или shared_preferences, создайте класс ServicesInjectionModule и пометьте его аннотацией @module. Если вам нужно дождаться завершения фабрики, возвращающей future, используйте аннотацию @preResolve:

@preResolve
Future<SharedPreferences> get sharedPreferences => SharedPreferences.getInstance();
Многомодульность Injectable поддерживает многомодульность. Чтобы создать файл в модуле, используйте:

@InjectableInit.microPackage()
void initMicroPackage() {}
Это создаст FeaturePackageModule, который нужно будет добавить в externalPackageModules приложения. Injectable предлагает гибкие настройки, позволяя управлять последовательностью создания зависимостей в случае необходимости ⚙️ Будем рады вашим вопросам и обсуждениям в чате!
Показать все...
🔥 5👍 3 2💩 2👎 1👏 1
Hola, Amigos! На связи Павел Гершевич, Flutter Team Lead в Amiga. Вы часто спрашиваете в комментариях, где можно научиться Flutter, и просите поделиться полезными материалами. И мы очень стараемся делать это в наших постах! Но хотим порадовать вас еще одной классной новостью: вместе с тремя талантливыми и увлеченными Flutter авторами мы напишем книгу «Основы Flutter». Вы должны знать своих героев: 🔵 Станислав Чернышев — автор YouTube-канала «MADTeacher» и учебника «Основы Dart». 🔵 Юрий Петров — Flutter Tech Lead в Friflex, автор YouTube- и телеграм-каналов «Мобильный разработчик», а также курсов на платформе Stepik. 🔵 Станислав Ильин — Lead Flutter developer, автор YouTube- и телеграм-каналов «Стас Ильин». 🔵 И конечно же я, Павел Гершевич — Flutter Team Lead в Amiga, спикер различных конференций и автор телеграм-канала «Flutter TechLead Notes» буду соавтором книги. Все самые свежие материалы книги, прошедшие редактуру, будут выкладываться в курс на Stepik — Основы Flutter. Это позволит нам собирать быструю обратную связь по добавленному материалу и вносить правки. Хочешь принять участие? Предлагай тему сквозного проекта для книги в нашем чате, и если авторскому коллективу она понравится, мы добавим отдельное упоминание в графе с благодарностями. Ждите прямых эфиров на нашем канале. Будем держать вас в курсе новостей о развитии книги! 🙂
Показать все...
🔥 12 3👏 2💯 2
00:09
Видео недоступноПоказать в Telegram
Hola, Amigos! На связи Вова Зевеке, Flutter dev Amiga. Сегодня расскажу про #пп scroll_highlight_text. Пакет полезен для поиска в большом объеме текста. Виджет HighlightedTextScrollable позволяет скроллить текст и выделять совпадения при вводе ключевого слова в поиск. Виджет обладает свойствами: ⚪️ text (String, отображаемый текст виджета); ⚪️ searchController (TextEditingController, контроллер для управления поведением виджета); ⚪️ autoDisposeSearchController (bool, определяет, нужно ли автоматически удалять контроллер при удалении виджета из дерева виджетов); ⚪️ textDirection (TextDirection, определяет направление текста); ⚪️ highlightedTextStyle (TextStyle, стиль текста, применяемый к выделенным участкам текста); ⚪️ unHighlightedTextStyle (TextStyle, стиль текста, примененный к остальной части текста); ⚪️ padding (EdgeInsetsGeometry, внутренние отступы вокруг текстового виджета); ⚪️ durationOfScroll (Duration, продолжительность анимации скролла); ⚪️ animationCurveOfScroll (Curve, тип анимации скролла). Пример:

final TextEditingController controller = TextEditingController();
 final String value =
  'Понедельник - день тяжёлый, <…>';

 @override
 Widget build(BuildContext context) {
   return Column(
  crossAxisAlignment: CrossAxisAlignment.start,
  children: [
    Padding(
      padding: const EdgeInsets.symmetric(horizontal: 16.0),
      child: SearchBar(
        hintText: 'Start search',
        controller: controller,
      ),
    ),
    HighlightedTextScrollable(
      text: value,
      searchController: controller,
      highlightedTextStyle: const TextStyle(
        fontSize: 22,
        color: Colors.red,
        fontWeight: FontWeight.w600,
      ),
      unHighlightedTextStyle: const TextStyle(
        fontSize: 22,
        color: Colors.black,
      ),
      padding: const EdgeInsets.symmetric(
        horizontal: 16,
        vertical: 20,
      ),
    ),
  ],
   );
 }
Хорошего всем кода! Делитесь в чате своим опытом использования данного пакета.
Показать все...
IMG_8742.MP48.65 KB
🔥 16👍 7💯 2👀 1
Выберите другой тариф

Ваш текущий тарифный план позволяет посмотреть аналитику только 5 каналов. Чтобы получить больше, выберите другой план.