Flutter Pulse
524 subscribers
347 photos
765 links
На канале будут новости про flutter с сайтов, информация об обновлении пакетов, а также авторский контент.
Download Telegram
Зачем использовать ключ виджета?

Ключи виджетов в Flutter: когда и почему они нужны? 🤔

В большинстве случаев вам не нужно использовать ключи... но есть ситуации, когда они крайне полезны! 😎

Новый виджет будет использован для обновления существующего элемента только если его ключ совпадает с ключом текущего виджета, связанного с этим элементом.

Ключи необходимы для:
- клонирования состояния виджета между несколькими страницами/вкладками 📑
- изменения порядка виджетов внутри списка 🔄
- сохранения позиции прокрутки 🕳️
- идентификации виджетов и их состояния 🔍
- идентификации для тестирования 🧪

Ключ позволяет Flutter связать элемент из elementTree с виджетом 🔗



class MyWidget extends StatefulWidget {
@override
_MyWidgetState createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
@override
Widget build(BuildContext context) {
// Используем ключ для сохранения состояния
return KeyedSubtree(
key: ObjectKey('my_unique_key'), // Уникальный ключ
child: MyStatefulChild(),
);
}
}



Если вы поменяете местами два виджета с ключами в дереве виджетов, Flutter также поменяет их местами в дереве элементов 🔄

Оцените нашу новую рубрику и напишите ваше мнение в комментариях! 💬

Все подобные новости можно найти по хэштегу #FlutterPulseTips

#flutter #dart #flutterpulse #FlutterPulseTips #MobileDevelopment #WidgetKeys #FlutterTips #AppDevelopment #UIUX #CodingTips
Ждём... или используем скелетную анимацию?

При загрузке контента важно сделать ожидание для пользователя максимально комфортным. Есть два основных способа сделать это: использовать стандартный индикатор загрузки или скелетную анимацию.

Индикатор загрузки - простой и понятный способ показать, что контент загружается. Flutter предоставляет встроенный виджет CircularProgressIndicator.adaptive(), который адаптируется под разные платформы.

// Создает индикатор, который является 
// [CupertinoActivityIndicator] на iOS
// [CircularProgressIndicator] на других платформах
CircularProgressIndicator.adaptive();


Для более широких возможностей можно использовать пакеты, такие как:
- sleek_circular_slider
- flutter_spinkit

Скелетная анимация дает пользователю представление о том, какого типа контент загружается (изображение, текст, длинный текст и т.д.). Это воспринимается как более быстрое и плавное.

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

Для реализации скелетной анимации можно использовать пакет better_skeleton.

Оцените новую рубрику и напишите своё мнение в комментарии! 🤔💬

Все подобные новости можно найти по хэштегу #FlutterPulseTips

#flutter #dart #flutterpulse #FlutterPulseTips #MobileDevelopment #UIUX #LoadingAnimation #AppDevelopment #FlutterTips
👍1
Форматирование JSON с помощью Dart

Привет, разработчики! 👋 Сегодня мы рассмотрим полезный совет по работе с JSON в Dart. Вы узнаете, как красиво напечатать JSON-строку, сделав её более читаемой и удобной для отладки 🛠️

Проблема: JSON-данные часто приходят в компактном, неформатированном виде, что затрудняет их чтение и анализ.

Решение: Используйте класс JsonEncoder из пакета dart:convert для форматирования JSON.


import 'dart:convert';

// Создаём кодировщик с отступами для форматирования
var encoder = const JsonEncoder.withIndent(' ');
// Преобразуем данные в красиво отформатированную строку
String prettyprint = encoder.convert(data);


Этот простой код позволяет превратить нечитаемую JSON-строку в структурированный и понятный формат с отступами 🌟

Оцените эту рубрику и напишите в комментариях, какие темы вам было бы интересно разобрать в следующих выпусках! 💬

Все подобные новости вы можете найти по хэштегу #FlutterPulseTips

#flutter #dart #flutterpulse #FlutterPulseTips #JSON #DartTips #FlutterTips #CodingTips #AppDevelopment #MobileDevelopment
👍31
Изучаем OverflowBar: Легкое управление адаптивными строками и столбцами

Привет, разработчики Flutter! 👋 Вы когда-нибудь сталкивались с проблемой, когда содержимое строки или столбца выходит за пределы экрана? 🤔 Сегодня мы рассмотрим OverflowBar - удобный виджет, который помогает легко решить эту проблему! 💡

Что такое OverflowBar?
OverflowBar - это виджет, который располагает своих потомков в строке, если хватает места, или в столбце, если места недостаточно. 📐 Это особенно полезно для создания адаптивных интерфейсов, которые корректно отображаются на разных устройствах и в различных ориентациях экрана.

Пример использования:



OverflowBar(
children: [
Image.asset('asset/image.jpg'), // Загружаем изображение из assets
const Card(
child: Text('My Title'), // Отображаем текст внутри карточки
),
],
);



Как видно из примера, OverflowBar автоматически определяет доступное пространство и перераспределяет элементы при необходимости. 🔄

Ключевые особенности:
- Автоматическое обнаружение переполнения и перераспределение элементов 🔍
- Возможность использования вместе с виджетом Wrap 🌟
- Гибкость в управлении выравниванием переполненных элементов ⚖️

Документация гласит:
"Виджет, который располагает своих потомков в строке, если они помещаются, или в столбце, если они не помещаются в доступном горизонтальном пространстве."

👉 Оцените новую рубрику #FlutterPulseTips и оставьте свои отзывы! 💬

Все подобные новости вы можете найти по хэштегу #FlutterPulseTips.

#flutter #dart #flutterpulse #FlutterPulseTips #MobileDevelopment #UIUX #AppDevelopment #CodingTips
OverflowBar или Wrap?
В чем основные различия между этими двумя виджетами Flutter? 🤔

При создании адаптивных интерфейсов в Flutter часто возникает вопрос о том, какой виджет использовать для размещения дочерних элементов: OverflowBar или Wrap? Давайте разберемся в их основных различиях. 🔍



_buildTestA(BuildContext context) => OverflowBar(
children: [
Container(width: 300, height: 100, color: Colors.blue),
const Card(
margin: EdgeInsets.all(32),
child: Text('My Title lorem lorem lorem'),
),
Expanded(child: Container(height: 100, color: Colors.red)),
],
);

_buildTestB(BuildContext context) => Wrap(
children: [
Container(width: 300, height: 100, color: Colors.blue),
const Card(
margin: EdgeInsets.all(32),
child: Text('My Title lorem lorem lorem'),
),
Expanded(child: Container(height: 100, color: Colors.red)),
],
);



OverflowBar и Wrap имеют разные подходы к размещению дочерних элементов. OverflowBar предназначен для размещения элементов в одной строке и не переносит их на новую строку, если они не помещаются. Wrap, наоборот, переносит элементы на новую строку, если они не помещаются в доступное пространство. 🌟

Оцените новую рубрику и напишите в комментариях, насколько она вам полезна! 👍💬

Все подобные новости можно найти по хэштегу #FlutterPulseTips. 🔍

#flutter #dart #flutterpulse #FlutterPulseTips #mobiledevelopment #appdevelopment #uiux #programmingtips
👍2🔥2
Центрирование формы без скрытия полей при открытом клавиатуре

Привет, подписчики! 👋 Сегодня мы рассмотрим полезный совет по Flutter, который поможет вам улучшить пользовательский опыт в ваших приложениях. 📱💡

Проблема: Когда клавиатура открывается, поля формы могут быть скрыты, что затрудняет ввод данных пользователем. 😕

Решение: Использовать Scaffold с параметром resizeToAvoidBottomInset: true и обернуть форму в SingleChildScrollView. 📝



Scaffold(
resizeToAvoidBottomInset: true, // Изменяет размер при открытии клавиатуры
body: Form(
key: _formKey,
child: SingleChildScrollView( // Позволяет прокручивать содержимое
child: SizedBox(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center, // Центрирует содержимое
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Spacer(flex: 1), // Гибкое пространство сверху
TextFormField(...), // Поля формы
TextFormField(...),
const Spacer(flex: 1), // Гибкое пространство снизу
],
),
),
),
),
)



Как это работает:
- resizeToAvoidBottomInset: true заставляет Scaffold изменять размер при открытии клавиатуры. 🔄
- SingleChildScrollView позволяет прокручивать содержимое формы, если оно не помещается на экране. 🔄
- Spacer с гибким размером (flex: 1) обеспечивает равномерное распределение пространства сверху и снизу формы. ⚖️

👍 Оцените новую рубрику и напишите в комментариях, какие темы вам интересны! 💬

Все подобные новости можно найти по хэштегу #FlutterPulseTips. 🔍

#flutter #dart #flutterpulse #FlutterPulseTips #MobileDev #UIUX #AppDevelopment #CodingTips
👍41🔥1🤯1
Круглый аватар с границей
Круглый аватар не имеет границы, но есть быстрый способ добавить её!

Если вы не хотите переписывать виджет CircleAvatar...
Просто оберните его ещё в один или используйте Container с градиентом.



CircleAvatar(
radius: radius + 2, // Увеличиваем радиус для границы
backgroundColor: borderColor, // Цвет границы
child: CircleAvatar(
radius: radius, // Радиус внутреннего аватара
backgroundImage: NetworkImage(url), // Изображение из сети
),
);



Оцените новую рубрику лайком 👍 и подпишитесь, чтобы не пропустить новые советы! 😉
Все подобные новости можно найти по хэштегу #FlutterPulseTips
#flutter #dart #flutterpulse #FlutterPulseTips #mobiledev #appdevelopment #uiux #codingtips
👍3
Создаем собственный экран ошибок

Вам надоело видеть красный или серый экран при возникновении ошибки? 🤔

Это поведение Flutter-приложения по умолчанию. 📱

Примечание: Если вы хотите, чтобы Flutter перестал показывать красный экран в режиме отладки или серый в production-режиме, просто удалите функцию presentError. 💡

Вы можете переопределить виджет ошибки по умолчанию или вообще не показывать ничего... 🤷‍♂️

Хорошим решением может быть перенаправление пользователя и отображение ошибки в виде всплывающего сообщения. 📢



void main() {
FlutterError.onError = (FlutterErrorDetails details) {
FlutterError.presentError(details); // Показываем ошибку
};
runApp(const MyApp());
}

class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);

@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
routes: routes,
initialRoute: 'route1',
builder: (context, widget) {
ErrorWidget.builder = (FlutterErrorDetails errorDetails) {
Widget error = Text('...rendering error... : ${errorDetails.summary}');
if (widget is Scaffold || widget is Navigator) {
error = Scaffold(body: Center(child: error));
}
return error;
};
return widget;
},
);
}
}



Оцените нашу новую рубрику! 👍💬 Оставляйте ваши отзывы в комментариях! 💬👇

Все подобные новости можно найти по хэштегу #FlutterPulseTips

#flutter #dart #flutterpulse #FlutterPulseTips #MobileDevelopment #AppDevelopment #ErrorHandling #CustomErrorScreen #FlutterTips
👍2
Создаём круглый индикатор прогресса
Привет, подписчики! 👋 Сегодня мы рассмотрим интересный Flutter-трюк, который поможет вам создать круглый индикатор прогресса с помощью ClipRRect 🌟

Вы можете использовать виджет ClipRRect, чтобы создать круглый индикатор прогресса. Для этого нужно обернуть LinearProgressIndicator в ClipRRect и задать ему радиус границы 🌈



ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(10)),
child: LinearProgressIndicator(
minHeight: 14,
value: progress, // текущий прогресс
color: Colors.red, // цвет прогресса
backgroundColor: Colors.white, // фон индикатора
),
),



В этом примере мы используем LinearProgressIndicator с minHeight равным 14 и оборачиваем его в ClipRRect с радиусом 10, чтобы получить круглый индикатор прогресса 🔴⚪️

Оцените новую рубрику и напишите в комментариях, какие темы вам интересны 🔥

Все подобные новости можно найти по хэштегу #FlutterPulseTips 🤓
#flutter #dart #flutterpulse #FlutterPulseTips #MobileDevelopment #UIUX #ProgressIndicator #FlutterTips #CodingTricks #AppDevelopment
👍2
Скачивание файла из Firebase и отслеживание прогресса

Привет, разработчики 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 и добавьте это:


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