Скачивание файла из Firebase и отслеживание прогресса
Привет, разработчики Flutter! 👋 Сегодня мы рассмотрим полезный совет по загрузке файлов из Firebase Storage и отслеживанию прогресса загрузки. 📈
Код для скачивания файла:
Ключевые моменты:
- Проверка разрешений: Используем
- Сохранение в папку загрузок: Файл сохраняется в папку "Download" на Android.
- Замена существующего файла: Если файл уже существует, он будет удален и заменен новым.
- Отслеживание прогресса: Используем
Чтобы получить текущий прогресс, можно использовать:
Оцените нашу новую рубрику советов по Flutter! 👍 Ваши отзывы помогут нам сделать ее еще лучше. 💬
Все подобные советы вы можете найти по хэштегу #FlutterPulseTips.
#flutter #dart #flutterpulse #FlutterPulseTips #Firebase #MobileDevelopment #FlutterTips #AppDevelopment #CodingTips
Привет, разработчики Flutter! 👋 Сегодня мы рассмотрим полезный совет по загрузке файлов из Firebase Storage и отслеживанию прогресса загрузки. 📈
Код для скачивания файла:
Stream<TaskSnapshot> downloadFile(String path) async* {
if (await Permission.storage.request().isDenied) {
throw "Вы должны принять разрешение на запись";
}
var fileRef = storage.ref().child(path);
var fileName = fileRef.name;
Directory directory;
if (Platform.isAndroid) {
directory = Directory("/storage/emulated/0/Download");
} else {
directory = (await getExternalStorageDirectory())!;
}
final File destinationFile = File('${directory.path}/$fileName');
if (destinationFile.existsSync()) {
destinationFile.deleteSync();
}
destinationFile.createSync();
var task = fileRef.writeToFile(destinationFile);
yield* task.asStream();
}
Ключевые моменты:
- Проверка разрешений: Используем
permission_handler
для проверки разрешения на доступ к хранилищу.- Сохранение в папку загрузок: Файл сохраняется в папку "Download" на Android.
- Замена существующего файла: Если файл уже существует, он будет удален и заменен новым.
- Отслеживание прогресса: Используем
yield*
для передачи событий из задачи в наш поток, что позволяет отображать прогресс загрузки в приложении.Чтобы получить текущий прогресс, можно использовать:
var progress = task.bytesTransferred / task.totalBytes * 100;
Оцените нашу новую рубрику советов по Flutter! 👍 Ваши отзывы помогут нам сделать ее еще лучше. 💬
Все подобные советы вы можете найти по хэштегу #FlutterPulseTips.
#flutter #dart #flutterpulse #FlutterPulseTips #Firebase #MobileDevelopment #FlutterTips #AppDevelopment #CodingTips
👍1
Firestore: конфигурация из нативных приложений
Вы, возможно, пропустили это... Плагин Firebase может использовать конфигурацию напрямую на стороне Dart!
Шаги по настройке:
1. Создайте несколько окружений Firebase для разработки/стадии/продакшена, используя только Dart.
Создайте 3 файла в папке runners. Один для каждой среды.
2. Создайте несколько файлов конфигурации Flavors.
Также сгенерируйте все файлы FirebaseOptions, используя flutterFire cli.
3. Удалите запуск из вашего main.dart и добавьте это:
4. Запустите приложение:
Важно:
- FlutterFire cli добавляет нативную зависимость на iOS/Android.
- Удалите конфигурацию Firebase из папок android и iOS.
- На Android удалите службы Google из build.gradle.
Оцените новую рубрику! 👍 Оставляйте ваши отзывы в комментариях! 💬
Все подобные новости можно найти по хэштегу #FlutterPulseTips
#flutter #dart #flutterpulse #FlutterPulseTips #Firestore #Firebase #FlutterTips #MobileDevelopment #AppDevelopment
Вы, возможно, пропустили это... Плагин Firebase может использовать конфигурацию напрямую на стороне Dart!
Шаги по настройке:
1. Создайте несколько окружений Firebase для разработки/стадии/продакшена, используя только Dart.
Создайте 3 файла в папке runners. Один для каждой среды.
2. Создайте несколько файлов конфигурации Flavors.
Также сгенерируйте все файлы FirebaseOptions, используя flutterFire cli.
3. Удалите запуск из вашего main.dart и добавьте это:
Future<void> runWrapperApp(FlavorConfig config) async {
// Инициализируйте конфигурацию приложения здесь
// Например, установите уровень журнала на основе среды
final firebaseApp = await Firebase.initializeApp(
options: config.firebaseConfig,
);
runApp(MyApp());
}
4. Запустите приложение:
flutter run -t lib/runners/main_dev.dart
Важно:
- FlutterFire cli добавляет нативную зависимость на iOS/Android.
- Удалите конфигурацию Firebase из папок android и iOS.
- На Android удалите службы Google из build.gradle.
Оцените новую рубрику! 👍 Оставляйте ваши отзывы в комментариях! 💬
Все подобные новости можно найти по хэштегу #FlutterPulseTips
#flutter #dart #flutterpulse #FlutterPulseTips #Firestore #Firebase #FlutterTips #MobileDevelopment #AppDevelopment
👍1
Оптимизация генерации кода
Ускорьте генерацию кода Flutter ⚡️
Заметка: Что такое генерация кода в Flutter?
Flutter позволяет генерировать шаблонный код с помощью аннотаций над классом/методом.
Это особенно полезно для генерации JSON-объектов (пакет json_serializable) или внедрения сервисов (gate_generator).
Как запустить генерацию кода?
1. Установите пакет build_runner и пакет, генерирующий код (см. примечание выше)
2. Выполните команду:
1 - Создайте файл
Включайте папки, содержащие файлы с аннотациями.
Генераторы кода будут сканировать только эти папки.
Вы можете легко исключать папки или файлы для каждого генератора кода.
Оцените новую рубрику и напишите своё мнение! 👍💬
Все подобные новости можно найти по хэштегу #FlutterPulseTips
#flutter #dart #flutterpulse #FlutterPulseTips #FlutterTips #CodeGeneration #OptimizeCode #FlutterDevelopment #MobileDevelopment #ProgrammingTips #DevelopmentTips
Ускорьте генерацию кода Flutter ⚡️
Заметка: Что такое генерация кода в Flutter?
Flutter позволяет генерировать шаблонный код с помощью аннотаций над классом/методом.
Это особенно полезно для генерации JSON-объектов (пакет json_serializable) или внедрения сервисов (gate_generator).
Как запустить генерацию кода?
1. Установите пакет build_runner и пакет, генерирующий код (см. примечание выше)
2. Выполните команду:
flutter packages pub run build_runner build --delete-conflicting-outputs
1 - Создайте файл
build.yaml
в корне проекта, как этот:
targets:
$default:
builders:
gate_generator:gate_schema:
enabled: true
generate_for:
include:
- "lib/gate/**.dart"
- "lib/services/**/**.dart"
- "lib/data/repositories/**.dart"
- "lib/ui/**/**.dart"
exclude:
- "lib/data/entities/**.freezed.dart"
- "lib/data/entities/**.g.dart"
freezed:
enabled: true
generate_for:
exclude:
- test
include:
- lib/data/entities/**
source_gen|combining_builder:
options:
ignore_for_file:
- "type=lint"
Включайте папки, содержащие файлы с аннотациями.
Генераторы кода будут сканировать только эти папки.
Вы можете легко исключать папки или файлы для каждого генератора кода.
Оцените новую рубрику и напишите своё мнение! 👍💬
Все подобные новости можно найти по хэштегу #FlutterPulseTips
#flutter #dart #flutterpulse #FlutterPulseTips #FlutterTips #CodeGeneration #OptimizeCode #FlutterDevelopment #MobileDevelopment #ProgrammingTips #DevelopmentTips
👍2🔥2
Как создать список чекбоксов с помощью CheckboxListTile
Привет, подписчики! 👋 Сегодня мы рассмотрим, как легко создать список чекбоксов в вашем Flutter-приложении, используя виджет CheckboxListTile. 📝
Преимущества CheckboxListTile:
- Упрощает создание списков с чекбоксами
- Позволяет легко управлять состоянием выбранных элементов
- Поддерживает стандартный стиль Material Design
Пример кода:
Ключевые моменты:
✦ ListView.separated используется для создания списка с разделителями
✦ CheckboxListTile упрощает создание элемента списка с чекбоксом и текстом
✦ Свойство onChanged обрабатывает изменения состояния чекбокса
Оцените эту рубрику и напишите в комментариях, какие темы вы хотели бы видеть в будущих выпусках! 💬
Все подобные новости можно найти по хэштегу #FlutterPulseTips
#flutter #dart #flutterpulse #FlutterPulseTips #MobileDev #UIUX #FlutterTips #AppDevelopment #CodingTips
Привет, подписчики! 👋 Сегодня мы рассмотрим, как легко создать список чекбоксов в вашем Flutter-приложении, используя виджет CheckboxListTile. 📝
Преимущества CheckboxListTile:
- Упрощает создание списков с чекбоксами
- Позволяет легко управлять состоянием выбранных элементов
- Поддерживает стандартный стиль Material Design
Пример кода:
class SkillsFilterList extends StatelessWidget {
final SkillsFilter skillsFilter;
final Function() onChanged;
const SkillsFilterList({
Key? key,
required this.skillsFilter,
required this.onChanged,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return ListView.separated(
shrinkWrap: true,
physics: const BouncingScrollPhysics(),
itemCount: skillsFilter.value.length,
separatorBuilder: (context, index) => const SizedBox.shrink(),
itemBuilder: (context, index) {
final skill = this.skillsFilter.value[index];
return ListTileTheme(
contentPadding: EdgeInsets.all(0),
child: CheckboxListTile(
dense: true,
title: Text(skill.scopeName),
value: skill.chosed,
onChanged: (skill) {
skillsFilter.select(skill);
onChanged();
},
),
);
},
);
}
}
Ключевые моменты:
✦ ListView.separated используется для создания списка с разделителями
✦ CheckboxListTile упрощает создание элемента списка с чекбоксом и текстом
✦ Свойство onChanged обрабатывает изменения состояния чекбокса
Оцените эту рубрику и напишите в комментариях, какие темы вы хотели бы видеть в будущих выпусках! 💬
Все подобные новости можно найти по хэштегу #FlutterPulseTips
#flutter #dart #flutterpulse #FlutterPulseTips #MobileDev #UIUX #FlutterTips #AppDevelopment #CodingTips
👍4❤1
Кнопка с градиентом и анимацией
Привет, подписчики! 👋 Сегодня мы рассмотрим интересный пример создания анимированной кнопки с градиентным фоном во Flutter. 📱✨
Основная идея:
Мы создадим кнопку, у которой при нажатии будет изменяться градиентный фон с анимацией. Для этого мы используем
Код примера:
Как это работает:
1. Мы оборачиваем
2. При нажатии на кнопку запускается анимация, которая изменяет градиент от исходного к целевому.
3.
Перспективы:
- Можно создать собственный объект рендеринга.
- Полностью переработать кнопку без использования
- Расширить
Оцените новую рубрику и напишите в комментариях, что хотели бы увидеть дальше! 👍 Оцените пост и подпишитесь 😉
Все подобные новости можно найти по хэштегу #FlutterPulseTips
#flutter #dart #flutterpulse #FlutterPulseTips #MobileDevelopment #UIUX #Animation #FlutterTips #DartLang #GradientButton #AnimatedButton
Привет, подписчики! 👋 Сегодня мы рассмотрим интересный пример создания анимированной кнопки с градиентным фоном во Flutter. 📱✨
Основная идея:
Мы создадим кнопку, у которой при нажатии будет изменяться градиентный фон с анимацией. Для этого мы используем
AnimatedGradientButton
, который будет обрабатывать анимацию.Код примера:
class AnimatedGradientButton extends StatefulWidget {
final Text? label;
final Gradient gradient;
final Gradient onPushGradient;
final Icon? icon;
final Function()? onPressed;
AnimatedGradientButton({
this.label,
required this.gradient,
required this.onPushGradient,
this.icon,
this.onPressed,
});
@override
_AnimatedGradientButtonState createState() => _AnimatedGradientButtonState();
}
class _AnimatedGradientButtonState extends State<AnimatedGradientButton>
with TickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _animation;
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: Duration(milliseconds: 1000),
vsync: this,
);
_animation = CurvedAnimation(curve: Curves.decelerate, parent: _controller);
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _controller,
builder: (context, child) {
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(24),
gradient: LinearGradient(
colors: widget.gradient.colors.map((color) => Color.lerp(
color,
widget.onPushGradient.colors[widget.gradient.colors.indexOf(color)],
_animation.value,
)).toList(),
),
),
child: MaterialButton(
onPressed: () {
_controller.forward();
widget.onPressed?.call();
_controller.reverse();
},
child: widget.label,
),
);
},
);
}
}
Как это работает:
1. Мы оборачиваем
MaterialButton
в контейнер с градиентным фоном.2. При нажатии на кнопку запускается анимация, которая изменяет градиент от исходного к целевому.
3.
Color.lerp
используется для плавного перехода между цветами градиента.Перспективы:
- Можно создать собственный объект рендеринга.
- Полностью переработать кнопку без использования
MaterialButton
.- Расширить
ButtonStyleButton
как обычные кнопки.Оцените новую рубрику и напишите в комментариях, что хотели бы увидеть дальше! 👍 Оцените пост и подпишитесь 😉
Все подобные новости можно найти по хэштегу #FlutterPulseTips
#flutter #dart #flutterpulse #FlutterPulseTips #MobileDevelopment #UIUX #Animation #FlutterTips #DartLang #GradientButton #AnimatedButton
🔥2👍1
Работаем с клавиатурными сокращениями
При создании приложений для Flutter Web или Desktop, важно обеспечить удобное управление клавиатурными сокращениями. В этом нам помогут виджеты Shortcuts и Actions! 🚀
Shortcuts - это виджет, который создаёт привязку клавиш к определённым действиям для своих потомков. Всё просто: вы предоставляете карту клавиш и интенций (Intent).
Actions - этот виджет позволяет потомкам вызывать действия, определённые в родителе. Его можно использовать как вместе с Shortcuts, так и отдельно 😉
Давайте рассмотрим пример кода:
В этом примере мы создаём клавиатурное сокращение Ctrl+A для вызова действия SelectAllAction. Просто и удобно! 👍
Оцените нашу новую рубрику и напишите, о чём бы вы хотели узнать в следующий раз 🤔
Все подобные советы ищите по хэштегу #FlutterPulseTips
#flutter #dart #flutterpulse #FlutterPulseTips #FlutterTips #MobileDev #KeyboardShortcuts #FlutterDev #CodingTips
При создании приложений для Flutter Web или Desktop, важно обеспечить удобное управление клавиатурными сокращениями. В этом нам помогут виджеты Shortcuts и Actions! 🚀
Shortcuts - это виджет, который создаёт привязку клавиш к определённым действиям для своих потомков. Всё просто: вы предоставляете карту клавиш и интенций (Intent).
Actions - этот виджет позволяет потомкам вызывать действия, определённые в родителе. Его можно использовать как вместе с Shortcuts, так и отдельно 😉
Давайте рассмотрим пример кода:
// Это просто используется для указания нужного действия
class SelectAllIntent extends Intent {}
@override
Widget build(BuildContext context) {
return Shortcuts(
shortcuts: <LogicalKeySet, Intent>{
LogicalKeySet(LogicalKeyboardKey.control, LogicalKeyboardKey.keyA): SelectAllIntent(),
},
child: Actions(
dispatcher: LoggingActionDispatcher(),
actions: <Type, Action<Intent>>{
SelectAllIntent: SelectAllAction(),
},
child: Builder(
builder: (BuildContext context) => TextButton(
onPressed: Actions.handler<SelectAllIntent>(context, SelectAllIntent()),
child: const Text('SELECT ALL'),
),
),
),
);
}
// Action будет содержать логику, которую вы хотите выполнить при срабатывании клавиатурного сокращения
class SelectAllAction extends Action<SelectAllIntent> {
@override
void invoke(covariant SelectAllIntent intent) {
// делайте то, что вам нужно
}
}
В этом примере мы создаём клавиатурное сокращение Ctrl+A для вызова действия SelectAllAction. Просто и удобно! 👍
Оцените нашу новую рубрику и напишите, о чём бы вы хотели узнать в следующий раз 🤔
Все подобные советы ищите по хэштегу #FlutterPulseTips
#flutter #dart #flutterpulse #FlutterPulseTips #FlutterTips #MobileDev #KeyboardShortcuts #FlutterDev #CodingTips
👍3
🚀 Расширяем возможности Flutter с помощью FFI: Вызываем функции из GO!
Привет, Flutter-энтузиасты! Руслан подготовил 🔥горячее видео, которое откроет вам мир межъязыкового взаимодействия. Узнайте, как заставить Dart и Go работать в тандеме через FFI (Foreign Function Interface)!
👉 Смотрите видео здесь:
Расширяем возможности Flutter с помощью FFI. Вызываем функции из GO
В этом выпуске вы узнаете:
🔹 Как передавать строки между Dart и Go (и обратно!)
🔹 Особенности работы с памятью и Garbage Collector
🔹 Магию горутин (goroutine) и defer
🔹 Практические примеры вызова Go-кода из Flutter-приложений
✨ Почему это важно?
Вы сможете использовать сильные стороны Go (например, многопоточность через горутины) в своих Flutter-проектах! Автор наглядно показывает процесс компиляции, преобразования типов и управления памятью.
💡 В следующих выпусках:
- Работа с Rust, Python и C++ через FFI
- Продвинутые техники оптимизации
🔥P.S. Увидите, как Go-горутины ускоряют вычисления в сравнении с Dart-изолятами!
#Flutter #Dart #FlutterPulse #FlutterPulseTips #FlutterPulseYoutube
#FFI #Golang #MobileDevelopment #CrossPlatform
👉 Больше полезного в плейлисте: #FlutterPulseYoutube
Привет, Flutter-энтузиасты! Руслан подготовил 🔥горячее видео, которое откроет вам мир межъязыкового взаимодействия. Узнайте, как заставить Dart и Go работать в тандеме через FFI (Foreign Function Interface)!
👉 Смотрите видео здесь:
Расширяем возможности Flutter с помощью FFI. Вызываем функции из GO
В этом выпуске вы узнаете:
🔹 Как передавать строки между Dart и Go (и обратно!)
🔹 Особенности работы с памятью и Garbage Collector
🔹 Магию горутин (goroutine) и defer
🔹 Практические примеры вызова Go-кода из Flutter-приложений
✨ Почему это важно?
Вы сможете использовать сильные стороны Go (например, многопоточность через горутины) в своих Flutter-проектах! Автор наглядно показывает процесс компиляции, преобразования типов и управления памятью.
💡 В следующих выпусках:
- Работа с Rust, Python и C++ через FFI
- Продвинутые техники оптимизации
🔥
#Flutter #Dart #FlutterPulse #FlutterPulseTips #FlutterPulseYoutube
#FFI #Golang #MobileDevelopment #CrossPlatform
👉 Больше полезного в плейлисте: #FlutterPulseYoutube
Шпаргалка по Dart map
Maps are fast - Карты работают быстро
Карта - это коллекция пар ключ/значение. Значение извлекается из карты с помощью связанного с ним ключа.
В Dart существует 3 типа карт:
- HashMap - неупорядоченная
- LinkedHashMap - упорядоченная по порядку вставки
- SplayTreeMap - упорядоченная по ключам
Преобразование списка в карту
Зачем использовать карту?
Доступ к элементу в списке с использованием
Доступ к элементу или проверка его наличия в карте занимает O(1).
Карты выигрывают в этом
Как создать неизменяемую карту?
https://pub.dev/packages/built_collection - Этот пакет предоставляет способы создания неизменяемых карт (разработан командой Dart).
Функции карты
Оцените новую рубрику! 👍💬
Все подобные новости можно найти по хэштегу #FlutterPulseTips
#flutter #dart #flutterpulse #FlutterPulseTips #DartTips #MobileDevelopment #ProgrammingTips #Coding #FlutterCommunity
Maps are fast - Карты работают быстро
Карта - это коллекция пар ключ/значение. Значение извлекается из карты с помощью связанного с ним ключа.
В Dart существует 3 типа карт:
- HashMap - неупорядоченная
- LinkedHashMap - упорядоченная по порядку вставки
- SplayTreeMap - упорядоченная по ключам
// Простая карта со строковым ключом: строковым значением
var data = {'name': 'John Doe', 'occupation': 'gardener'};
// карта, типизированная с помощью конструктора Map<String, String>()
var data2 = <int, String>{1: 'sky', 2: 'falcon', 3: 'rock'};
Преобразование списка в карту
// преобразование списка в карту
var resultMap = Map.fromIterable(list, key: (v) => v[0], value: (v) => v[1]);
// или
var result = { for (var v in list) v[0]: v[1] };
// или просто используя метод asMap() для автоматического индексирования
var result = ["test","test2","test3"].asMap(); // {0: test, 1: test2, 2: test3}
Зачем использовать карту?
Доступ к элементу в списке с использованием
indexOf
или contains
имеет сложность O(n).Доступ к элементу или проверка его наличия в карте занимает O(1).
Карты выигрывают в этом
Как создать неизменяемую карту?
https://pub.dev/packages/built_collection - Этот пакет предоставляет способы создания неизменяемых карт (разработан командой Dart).
Функции карты
var details = {'Usrname': 'bruce', 'Password': 'mypas'};
// добавление
details['Uid'] = '3802983209A';
// обновление
details.putIfAbsent("Uid", () => "3802983209A");
// преобразование в другую карту
details.map((key, value) => MapEntry(key, "$key:$value"));
// приведение к другому типу
details.cast<int, int>();
// проверка наличия ключа
details.containsKey("key"); // сложность O(1)
// копирование
var copy = {...details};
// обновление
details.update("Usrname", (value) => "joker");
Оцените новую рубрику! 👍💬
Все подобные новости можно найти по хэштегу #FlutterPulseTips
#flutter #dart #flutterpulse #FlutterPulseTips #DartTips #MobileDevelopment #ProgrammingTips #Coding #FlutterCommunity
👍3
Изменение яркости системной панели
Отобразить системную панель с правильной яркостью на iOS и Android 🚀
При разработке мобильных приложений важно обеспечить корректное отображение системной панели на разных платформах. В этой статье мы рассмотрим, как изменить яркость системной панели в приложениях Flutter для iOS и Android.
Код для изменения яркости системной панели:
Обратите внимание:
-
-
Особенности для iOS: 🤔
На iOS строка состояния может быть изначально скрыта. Чтобы отобразить ее, откройте ваш проект в Xcode и убедитесь, что свойство
👍 Оцените нашу новую рубрику советов по Flutter! Ваши отзывы помогут нам сделать контент еще лучше.
Все подобные новости можно найти по хэштегу #FlutterPulseTips
#flutter #dart #flutterpulse #FlutterPulseTips #MobileDev #iOS #Android #FlutterTips #DevTips
Отобразить системную панель с правильной яркостью на iOS и Android 🚀
При разработке мобильных приложений важно обеспечить корректное отображение системной панели на разных платформах. В этой статье мы рассмотрим, как изменить яркость системной панели в приложениях Flutter для iOS и Android.
Код для изменения яркости системной панели:
SystemChrome.setSystemUIOverlayStyle(
SystemUIOverlayStyle(
statusBarColor: Colors.transparent, // Прозрачный цвет статус-бара
statusBarBrightness: // Установка яркости статус-бара в зависимости от темы
mode == ThemeMode.light ? Brightness.light : Brightness.dark,
statusBarIconBrightness: // Установка яркости иконок статус-бара в зависимости от темы
mode == ThemeMode.light ? Brightness.dark : Brightness.light,
),
);
Обратите внимание:
-
statusBarBrightness
применяется только на Android.-
statusBarIconBrightness
также применяется только на Android, но с инвертированными значениями для iOS.Особенности для iOS: 🤔
На iOS строка состояния может быть изначально скрыта. Чтобы отобразить ее, откройте ваш проект в Xcode и убедитесь, что свойство
status bar initially hidden
не отмечено.👍 Оцените нашу новую рубрику советов по Flutter! Ваши отзывы помогут нам сделать контент еще лучше.
Все подобные новости можно найти по хэштегу #FlutterPulseTips
#flutter #dart #flutterpulse #FlutterPulseTips #MobileDev #iOS #Android #FlutterTips #DevTips
👍2
Создаем чистую круглую кнопку
Как сделать свою собственную круглую кнопку в Flutter? 🤔
В этом совете мы покажем, как создать красивую и простую круглую кнопку для вашего Flutter-приложения. 📱
Давайте разберем пример кода:
Оцените новую рубрику и напишите свое мнение в комментариях! 💬
Все подобные новости можно найти по хэштегу #FlutterPulseTips
#flutter #dart #flutterpulse #FlutterPulseTips #mobiledevelopment #uiux #fluttertutorial #codingtips
Как сделать свою собственную круглую кнопку в Flutter? 🤔
В этом совете мы покажем, как создать красивую и простую круглую кнопку для вашего Flutter-приложения. 📱
Давайте разберем пример кода:
const CircleButton({
super.key,
required this.bgColor, // Цвет фона кнопки
required this.borderColor, // Цвет границы кнопки
required this.iconColor, // Цвет иконки
required this.onTap, // Обработчик нажатия
required this.radius, // Радиус кнопки
required this.iconSize, // Размер иконки
required this.borderWidth, // Ширина границы
required this.icon, // Иконка
this.disabled = false, // Флаг блокировки кнопки
});
@override
Widget build(BuildContext context) {
return Opacity(
opacity: disabled ? 0.5 : 1, // Изменяем прозрачность, если кнопка заблокирована
child: ClipOval(
child: Material(
color: Colors.transparent, // Прозрачный фон для эффекта Ink
// Ink покажет эффект касания, который вы видите на всех кнопках Flutter
child: Ink(
width: radius,
height: radius,
decoration: BoxDecoration(
shape: BoxShape.circle, // Круглая форма
color: bgColor, // Цвет фона
border: Border.all(color: borderColor, width: borderWidth), // Граница кнопки
),
child: InkWell(
onTap: () {
if (disabled) {
return; // Ничего не делаем, если кнопка заблокирована
}
// Даем легкую вибрационную обратную связь
HapticFeedback.lightImpact();
// Вызываем метод onTap
onTap();
},
child: Icon(icon, color: iconColor, size: iconSize), // Иконка внутри кнопки
),
),
),
),
);
}
Оцените новую рубрику и напишите свое мнение в комментариях! 💬
Все подобные новости можно найти по хэштегу #FlutterPulseTips
#flutter #dart #flutterpulse #FlutterPulseTips #mobiledevelopment #uiux #fluttertutorial #codingtips
👍1
Рисуем и анимируем круглый прогресс-бар с помощью Custom Painter
В этом совете мы рассмотрим, как создать анимированный круглый прогресс-бар, используя виджет
Основные моменты:
1️⃣ Передача анимации в конструктор
2️⃣ При обновлении прогресса мы изменяем начало и конец анимации, а затем запускаем её. Поскольку время загрузки предсказать невозможно, анимация прогресс-бара продолжается после обновления прогресса.
Пример кода:
Оцените новую рубрику и напишите в комментариях, что вы хотели бы увидеть в следующих постах! 👍💬
Все подобные новости можно найти по хэштегу #FlutterPulseTips
#flutter #dart #flutterpulse #FlutterPulseTips #MobileDevelopment #UI #Animation #CustomPainter #ProgressBar #LoadingAnimation #FlutterTips
В этом совете мы рассмотрим, как создать анимированный круглый прогресс-бар, используя виджет
CustomPaint
во Flutter. Такой прогресс-бар можно использовать, например, для индикации загрузки.Основные моменты:
1️⃣ Передача анимации в конструктор
CustomPainter
автоматически вызывает перерисовку.2️⃣ При обновлении прогресса мы изменяем начало и конец анимации, а затем запускаем её. Поскольку время загрузки предсказать невозможно, анимация прогресс-бара продолжается после обновления прогресса.
Пример кода:
class RoundProgressPainter extends CustomPainter {
final double radius;
final double progress;
final Color color;
final Animation<double> animation;
final double strokeWidth;
RoundProgressPainter({
required this.radius,
required this.progress,
required this.color,
required this.animation,
required this.strokeWidth,
}) : super(repaint: animation);
@override
void paint(Canvas canvas, Size size) {
final center = Offset(size.width / 2, size.height / 2);
final progressAngle = math.pi * 2 * progress;
final progressPaint = Paint()
..color = color
..strokeWidth = strokeWidth
..style = PaintingStyle.stroke
..strokeCap = StrokeCap.round;
canvas.drawCircle(
center,
radius - strokeWidth / 2,
Paint()
..color = color.withOpacity(0.1)
..strokeWidth = strokeWidth
..style = PaintingStyle.stroke,
);
canvas.drawArc(
Rect.fromCircle(center: center, radius: radius),
-math.pi / 2,
progressAngle,
false,
progressPaint,
);
}
@override
bool shouldRepaint(RoundProgressPainter oldDelegate) =>
progress != oldDelegate.progress || color != oldDelegate.color;
}
class RoundProgress extends StatefulWidget {
final double radius;
final double progress;
final Color color;
final Widget? child;
final double strokeWidth;
const RoundProgress({
super.key,
required this.radius,
required this.progress,
required this.color,
this.child,
this.strokeWidth = 4.0,
});
@override
_RoundProgressState createState() => _RoundProgressState();
}
class _RoundProgressState extends State<RoundProgress> with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _animation;
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 300),
);
_animation = Tween(begin: 0.0, end: 1.0).animate(
CurvedAnimation(parent: _controller, curve: Curves.decelerate),
);
_controller.forward(from: 0);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
void didUpdateWidget(covariant RoundProgress oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.progress != oldWidget.progress && widget.progress != null) {
_animation = Tween(begin: oldWidget.progress, end: widget.progress).animate(
CurvedAnimation(parent: _controller, curve: Curves.easeIn),
);
_controller.forward(from: 0);
}
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _animation,
builder: (context, child) => CustomPaint(
size: Size(widget.radius * 2, widget.radius * 2),
painter: RoundProgressPainter(
radius: widget.radius,
progress: widget.progress,
color: widget.color,
animation: _animation,
strokeWidth: widget.strokeWidth,
),
child: widget.child,
),
);
}
}
Оцените новую рубрику и напишите в комментариях, что вы хотели бы увидеть в следующих постах! 👍💬
Все подобные новости можно найти по хэштегу #FlutterPulseTips
#flutter #dart #flutterpulse #FlutterPulseTips #MobileDevelopment #UI #Animation #CustomPainter #ProgressBar #LoadingAnimation #FlutterTips
👍2
Тестирование с навигацией GoRouter
Как запускать тесты с навигацией GoRouter
Иногда вам хочется быть уверенными, что некоторые виджеты перенаправляют на правильный маршрут.
Гораздо проще тестировать ваши страницы вне навигации, но это все равно может помочь в некоторых случаях.
Пример теста:
Дополнительный совет:
Вы можете использовать ваш app router, чтобы получить точно такое же поведение маршрутизации, как и в вашем приложении.
Таким образом, вы действительно можете проверить, работает ли навигация корректно.
Встройте создание GoRouter в функцию с параметром initialLocation, чтобы ваш тест мог начинаться прямо с того места, которое вам нужно.
Оцените новую рубрику по тестированию Flutter-приложений! 👍
Все подобные новости можно найти по хэштегу #FlutterPulseTips
#flutter #dart #flutterpulse #FlutterPulseTips #MobileAppDevelopment #FlutterTips #Testing #GoRouter
Как запускать тесты с навигацией GoRouter
Иногда вам хочется быть уверенными, что некоторые виджеты перенаправляют на правильный маршрут.
Гораздо проще тестировать ваши страницы вне навигации, но это все равно может помочь в некоторых случаях.
Пример теста:
testWidgets('условие защиты возвращает false => переход на ошибочный url',
(WidgetTester tester) async {
final app = MaterialApp.router(
routerConfig: GoRouter(
initialLocation: '/page1',
routes: [
GoRoute(
path: '/page1',
builder: (context, state) => Guard(
canActivate: future.value(false),
fallbackRoute: '/page2',
),
child: const FakePage(msg: 'page1'),
),
GoRoute(
path: '/page2',
builder: (context, state) => const FakePage(msg: 'page2'),
),
],
),
);
await tester.pumpWidget(app);
await tester.pumpAndSettle(const Duration(milliseconds: 100));
expect(find.text('page2'), findsOneWidget);
});
Дополнительный совет:
Вы можете использовать ваш app router, чтобы получить точно такое же поведение маршрутизации, как и в вашем приложении.
Таким образом, вы действительно можете проверить, работает ли навигация корректно.
Встройте создание GoRouter в функцию с параметром initialLocation, чтобы ваш тест мог начинаться прямо с того места, которое вам нужно.
GoRouter createRouter(final String initialLocation) {
return GoRouter(
initialLocation: initialLocation,
routes: [
GoRoute(
path: '/page1',
builder: (context, state) => const FakePage(msg: 'page1'),
),
GoRoute(
path: '/page2',
builder: (context, state) => const FakePage(msg: 'page2'),
),
],
);
}
Оцените новую рубрику по тестированию Flutter-приложений! 👍
Все подобные новости можно найти по хэштегу #FlutterPulseTips
#flutter #dart #flutterpulse #FlutterPulseTips #MobileAppDevelopment #FlutterTips #Testing #GoRouter
⚡2👍2