Flutter Pulse
622 subscribers
396 photos
872 links
На канале будут новости про flutter с сайтов, информация об обновлении пакетов, а также авторский контент.
Download Telegram
Детали для улучшения формы

Ничто не раздражает так сильно, как невозможность закрыть клавиатуру. Пользователь нажимает в любом месте... и клавиатура остаётся. Вместо этого вы можете просто сделать так:


final _formKey = GlobalKey<FormState>();

class SigninPage extends StatelessWidget {
const SigninPage({super.key, this.canDismiss = true});

@override
Widget build(BuildContext context) {
final translations = Translations.of(context).signin;

return GestureDetector(
onTap: () => FocusScope.of(context).unfocus(), // Убираем фокус с полей при нажатии вне их
child: PopScope(
canPop: canDismiss,
child: TopImgBackground(
bgImagePath: 'assets/images/signin/signin_background.png',
child: Scaffold(
backgroundColor: Colors.transparent,
appBar: AppBar(
backgroundColor: Colors.transparent,
automaticallyImplyLeading: canDismiss,
foregroundColor: context.colors.background,
),
resizeToAvoidBottomInset: false,
body: Form(
autovalidateMode: AutovalidateMode.disabled,
key: _formKey,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 24.0),
child: ListView(
children: [
const SizedBox(height: 150),
Text(
translations.title,
style: Theme.of(context).textTheme.titleLarge?.copyWith(
fontWeight: FontWeight.bold,
),
),
],
),
),
),
),
),
),
);
}
}


Решение: Оберните всю страницу в GestureDetector, а затем снимите фокус со всех элементов, используя функцию FocusScope. Это позволит автоматически убрать клавиатуру при нажатии вне текстовых полей.

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

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

#flutter #dart #flutterpulse #FlutterPulseTips #MobileDev #UIUX #AppDev #CodingTips #DevTips #FlutterTips
👍4
Как воспроизвести звуки в Flutter

Звуки могут изменить опыт использования приложения. Что может быть более удовлетворительным, чем хороший звук уведомления? 😊

Шаг 1: Установите плагин audioplayers

import 'package:audioplayers/audioplayers.dart';


Шаг 2: Воспроизведите звук напрямую...

await player.play(AssetSource("sounds/beep.wav"));


Это здорово, потому что вам не нужно готовить файл или сбрасывать его, если он уже был воспроизведен... просто попросите воспроизвести, и он сделает свое дело! 👍

Дополнительные возможности

// Установите режим освобождения, чтобы сохранить источник после завершения воспроизведения.
player.setReleaseMode(ReleaseMode.stop);


Это позволяет вам делать гораздо больше, чем просто воспроизводить звук. А за этой простотой вы также можете действительно оптимизировать с помощью расширенных конфигураций, таких как режим освобождения 🔧

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

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

#flutter #dart #flutterpulse #FlutterPulseTips #mobiledevelopment #appdevelopment #codingtips #programming #softwaredevelopment
👍1
Перегрузка операторов
Ещё один отличный способ улучшить читаемость кода 😉

Вы знаете, что в Dart можно перегружать операторы? 🤔 Это очень полезная функция, которая позволяет сделать ваш код более интуитивным и понятным.

Давайте рассмотрим пример с классом Vector. Мы хотим складывать векторы с помощью оператора +. Для этого нам нужно перегрузить этот оператор в нашем классе.


class Vector {
final int x, y;
Vector(this.x, this.y);

// Перегружаем оператор +
Vector operator +(Vector other) => Vector(x + other.x, y + other.y);
}

void main() {
final v1 = Vector(1, 2);
final v2 = Vector(3, 4);

final result = v1 + v2; // Теперь мы можем складывать векторы с помощью оператора +
print('(${result.x}, ${result.y})'); // Вывод: (4, 6)
}


Таким образом, мы можем перегружать любые операторы, такие как -, *, / и другие, чтобы сделать наш код более удобным и читаемым. 👍

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

Все подобные новости можно найти по хэштегу #FlutterPulseTips
#flutter #dart #flutterpulse #FlutterPulseTips #codingTips #mobileDevelopment #programmingTips
👍1
Single execution Future Builder

FutureBuilder с единственным выполнением

FutureBuilder будет выполнять наше будущее при каждой пересборке. Если это будущее выполняет вызов API, это может быть дорогостоящим и перегружать наш бэкэнд.

Мы предоставляем Future функцию, которая предотвращает повторное выполнение Future при каждой пересборке страницы.



typedef AsyncFutureBuilder<T> = Future<T> Function();

class SingleExecFutureBuilder<T> extends StatefulWidget {
final AsyncFutureBuilder<T> future;
final Widget Function(BuildContext context, T data) builder;

const SingleExecFutureBuilder({
super.key,
required this.future,
required this.builder,
});

@override
State<SingleExecFutureBuilder<T>> createState() => _SingleExecFutureBuilderState<T>();
}

class _SingleExecFutureBuilderState<T> extends State<SingleExecFutureBuilder<T>> {
T? _futureRes;
late FutureState _futureState;

@override
void initState() {
super.initState();
_futureState = FutureState.pending;
}

Future<T?> executeFuture() async {
if (_futureState == FutureState.pending) {
try {
_futureRes = await widget.future();
_futureState = FutureState.done;
return _futureRes;
} catch (e) {
_futureState = FutureState.error;
rethrow;
}
}
return _futureRes;
}

@override
Widget build(BuildContext context) {
return FutureBuilder<T>(
future: executeFuture(),
builder: (context, snapshot) {
if (snapshot.connectionState != ConnectionState.done) {
return const SizedBox.shrink();
}
return widget.builder(context, snapshot.data as T);
},
);
}
}

enum FutureState { pending, done, error }



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


@override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: const EdgeInsets.all(16),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text('Count: $count'),
const SizedBox(height: 16),
SingleExecFutureBuilder<String>(
future: () async {
print("Getting future once");
await Future.delayed(const Duration(milliseconds: 1100));
return "Hello";
},
builder: (context, data) => Text(data),
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () {
setState(() {
count++;
});
},
child: const Text('+'),
),
],
),
),
);
}



Выполните этот код, и вы увидите "Getting future once" только один раз, вместо того, чтобы видеть это каждый раз, когда вы нажимаете кнопку "+".


Оцените новую рубрику по Flutter советам! 👍💬 Нам важно ваше мнение, чтобы мы могли улучшать контент для вас! 😊👍

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

#flutter #dart #flutterpulse #FlutterPulseTips #MobileDevelopment #FutureBuilder #FlutterTips #CodingTips #AppDevelopment
👍3
Как задать высоту строки внутри колонки

Привет, Flutter-разработчики! 👋 Сегодня мы рассмотрим интересную задачу: как правильно задать высоту строки (Row) внутри колонки (Column). Эта проблема часто возникает при создании адаптивных интерфейсов, и мы разберем, как ее решить с помощью виджета IntrinsicHeight. 📐

Проблема: 🤔
Когда вы пытаетесь разместить Row внутри Column и хотите, чтобы высота Row определялась максимальным размером дочерних элементов, вы можете столкнуться с ошибкой. Flutter требует, чтобы размеры виджетов были ограничены, а Row по умолчанию не имеет ограничений по высоте.

Решение: 💡
Используйте виджет IntrinsicHeight в качестве родителя для Row. Этот виджет устанавливает высоту Row равной максимальному размеру его дочерних элементов.



@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Column(
children: [
IntrinsicHeight( // Оберните Row в IntrinsicHeight
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisSize: MainAxisSize.min,
children: [
Expanded(
flex: 2,
child: Container(
color: Colors.red,
padding: const EdgeInsets.all(32.0),
child: const Center(child: Text('Flex 2')),
),
),
Expanded(
flex: 1,
child: Container(
color: Colors.green,
padding: const EdgeInsets.all(32.0),
child: const Center(child: Text('Flex 1')),
),
),
],
),
),
Container(
height: 100,
color: Colors.blue,
child: const Center(child: Text('Контейнер с фиксированной высотой')),
),
],
),
),
);
}



Почему это работает? 🔍
- IntrinsicHeight определяет максимальную внутреннюю высоту дочерних элементов Row и применяет ее ко всем детям.
- CrossAxisAlignment.stretch растягивает дочерние элементы на всю доступную высоту.
- mainAxisSize: MainAxisSize.min устанавливает размер Row по основной оси в минимально необходимый.

Вывод: 🎉
Использование IntrinsicHeight позволяет легко управлять размером Row внутри Column, делая ваш интерфейс гибким и адаптивным. Оцените эту рубрику и оставляйте свои комментарии! 💬

Все подобные советы вы можете найти по хэштегу #FlutterPulseTips. 👉 Оцените новую рубрику и подпишитесь на наш канал! 👍

#flutter #dart #flutterpulse #FlutterPulseTips #MobileDevelopment #UIUX #FlutterTips #AppDevelopment #CodingTips
👍1
Supabase: Привязка анонимного пользователя к аутентифицированному

Анонимный пользователь - это действительно здорово. Вы автоматически создаете нового пользователя в своей базе данных каждый раз, когда кто-то впервые запускает ваше приложение.
Затем вы можете позволить ему подписаться, начать работать с вашим приложением, не беспокоя его просьбой ввести email...
А затем, когда он действительно вовлечется в процесс, вы можете привязать его учетную запись.



@override
Future<Credentials> signup(String email, String password) async {
if (client.auth.currentUser?.isAnonymous == true) {
// Обновляем анонимного пользователя с помощью email и password
final res = await client.auth.updateUser(UserAttributes(email: email, password: password));
if (res.user != null) {
return Credentials(id: res.user!.id);
} else {
throw 'Ошибка при обновлении пользователя';
}
}
return client.auth
.signUp(email: email, password: password)
.then(
(value) => Credentials(id: value.user!.id),
onError: (error) {
Logger().e("Ошибка при регистрации: $error");
throw SignupException();
},
);
}



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

Все подобные новости можно найти по хэштегу #FlutterPulseTips
#flutter #dart #flutterpulse #FlutterPulseTips #Supabase #MobileDev #AppDev #CodingTips #DevTips
👍1