Flutter Pulse
416 subscribers
270 photos
540 links
На канале будут новости про flutter с сайтов, информация об обновлении пакетов, а также авторский контент.
Download Telegram
Как открыть страницу настроек приложения в системе
Привет, друзья! 👋 Сегодня мы поделимся с вами полезным советом о том, как открыть страницу настроек вашего приложения на устройстве пользователя. 📱💻

Зачем это нужно? 🤔
Например, если пользователь отклонил уведомления, система больше не будет запрашивать разрешение. В этом случае вы можете помочь пользователю перейти в настройки и включить уведомления вручную. 🔔

Используем url_launcher 📲

import 'package:url_launcher/url_launcher.dart';

Future<void> openSettings() async {
Uri url;
if (defaultTargetPlatform == TargetPlatform.iOS) {
url = Uri.parse('app-settings:');
} else if (defaultTargetPlatform == TargetPlatform.android) {
url = Uri.parse('package:uly.vlog.diary');
} else {
throw Exception('Unsupported platform');
}

if (await canLaunchUrl(url)) {
await launchUrl(url);
} else {
throw 'Could not launch $url';
}
}


Или проще с permission_handler 📦

import 'package:permission_handler/permission_handler.dart';

openAppSettings();



Оцените новую рубрику и напишите в комментариях, что вы думаете о ней! 💬 Все подобные новости можно найти по хэштегу #FlutterPulseTips
#flutter #dart #flutterpulse #FlutterPulseTips #MobileDev #AppDev #ProgrammingTips #CodingTips
Flutter tips: how to create a responsive layout
Адаптивный макет: советы по Flutter

Привет, разработчики! 👋 Сегодня мы поговорим о создании адаптивного макета в Flutter. 📱💻

Адаптация макета под разные размеры экранов 📐
Чтобы ваше приложение выглядело отлично на разных устройствах, необходимо адаптировать макет под различные размеры экранов. 📊


import 'package:flutter/widgets.dart';

// Перечисление типов устройств
enum DeviceType { small, medium, large, xlarge }

// Виджет, который адаптирует свой контент к текущему типу устройства
class ResponsiveLayout extends StatelessWidget {
final Widget? small; // Виджет для маленьких экранов
final Widget? medium; // Виджет для средних экранов
final Widget? large; // Виджет для больших экранов
final Widget? xlarge; // Виджет для очень больших экранов

const ResponsiveLayout({
super.key,
required this.small,
this.medium,
this.large,
this.xlarge,
});

@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, constraints) {
// Определение типа устройства на основе ширины экрана
switch (getDeviceType(constraints)) {
case DeviceType.small:
return small!; // Возвращаем виджет для маленьких экранов
case DeviceType.medium:
return medium ?? small!; // Возвращаем виджет для средних экранов или fallback к маленькому
case DeviceType.large:
return large ?? medium ?? small!; // Возвращаем виджет для больших экранов или fallback
case DeviceType.xlarge:
return xlarge ?? large ?? medium ?? small!; // Возвращаем виджет для очень больших экранов или fallback
}
},
);
}

// Метод для определения типа устройства на основе ограничений
DeviceType getDeviceType(BoxConstraints constraints) {
return switch (constraints.maxWidth) {
> 1200 => DeviceType.xlarge, // Очень большой экран
> 1024 => DeviceType.large, // Большой экран
> 768 => DeviceType.medium, // Средний экран
_ => DeviceType.small, // Маленький экран
};
}
}


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

ResponsiveLayout(
small: SigninForm(), // Форма входа для маленьких экранов
medium: Center( // Центрирование для средних экранов и больше
child: ConstrainedBox(
constraints: BoxConstraints(maxWidth: 600), // Ограничение максимальной ширины
child: SigninForm(), // Форма входа
),
),
)


Этот код позволяет создать адаптивный макет, который будет корректно отображаться на различных устройствах. 📱💻

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

Все подобные новости можно найти по хэштегу #FlutterPulseTips
#flutter #dart #flutterpulse #FlutterPulseTips #MobileDev #AppDev #UIUX #ProgrammingTips #CodingTips
Flutter tips: Расширения для работы с датами

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

Использование расширений для дат

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

extension DateExtension on DateTime {
DateTime get firstDayOfWeek {
return subtract(Duration(days: weekday - 1));
}

DateTime get lastDayOfWeek {
return add(Duration(days: 7 - weekday));
}

DateTime get firstDayOfMonth {
return DateTime(year, month);
}

bool isToday() => isSameDay(DateTime.now());

bool isSameDay(DateTime other) {
return day == other.day && month == other.month && year == other.year;
}

bool isAfterDayOrEqual(DateTime other) {
return isAfter(other) || isSameDay(other);
}

bool isBeforeDayOrEqual(DateTime other) {
return isBefore(other) || isSameDay(other);
}

bool isSameWeek(DateTime other) {
final kfirstDayOfTheWeek = firstDayOfWeek;
return other.isAfterDayOrEqual(kfirstDayOfTheWeek) &&
other.isBefore(lastDayOfWeek);
}
}


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

Теперь давайте рассмотрим пример использования этих расширений. Вместо того, чтобы писать громоздкий код для проверки, является ли дата сегодняшней, мы можем использовать метод isToday():

if (!activities.hasActivity(date) && date.isToday()) {
// код
}


Это намного чище и читаемее, чем:

final today = DateTime.now();
if (!activities.hasActivity(date) && date.day == today.day && date.month == today.month && date.year == today.year) {
// код
}


Оцените новую рубрику! Все подобные новости можно найти по хэштегу #FlutterPulseTips
#flutter #dart #flutterpulse #FlutterPulseTips #MobileDev #CodingTips #AppDev #FlutterTips
Flutter Tip: Как сделать нижние всплывающие окна точно по размеру контента (без лишнего пространства!)

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

Проблема: По умолчанию высота вашего модального окна будет больше, чем содержимое. 🤷‍♂️

Решение: Используйте виджет IntrinsicHeight, чтобы установить высоту всплывающего окна точно по размеру контента. 📏

Вот пример кода:

showCupertinoModalPopup<void>(
context: context,
builder: () => const IntrinsicHeight(
child: RecordChoiceSelector(), // Ваш виджет содержимого
),
);



Что делает IntrinsicHeight? 🔍
- Этот виджет устанавливает размер своего потомка в соответствии с его внутренней высотой. 📐

Результат: 🎉
- Всплывающее окно будет отображаться точно по размеру содержимого, без лишнего пространства. 👍


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

Все подобные советы вы можете найти по хэштегу #FlutterPulseTips
#flutter #dart #flutterpulse #FlutterPulseTips #MobileDevelopment #FlutterTips #AppDevelopment #UIUX #CodingTips
Адаптивный конструктор одного виджета с помощью DeviceSizeBuilder

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

@override
Widget build(BuildContext context) {
return DeviceSizeBuilder(
builder: (device) => Column(
children: [
switch (device) {
DeviceType.small => const Spacer(),
// игнорируем остальные случаи
},
ElevatedButton(
onTap: () {},
child: Text('tap me'),
),
],
),
);
}

Чтобы иметь доступ к методу didChangeMetrics, нам нужно использовать WidgetsBinding:

class DeviceSizeBuilder extends StatefulWidget {
const DeviceSizeBuilder({
super.key,
required this.builder,
});

@override
State<DeviceSizeBuilder> createState() => _DeviceSizeBuilderState();
}

class _DeviceSizeBuilderState extends State<DeviceSizeBuilder> with WidgetsBindingObserver {
late DeviceType _lastSize;

@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
_lastSize = widget.builder;
}

@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}

@override
void didChangeMetrics() {
super.didChangeMetrics();
final newSize = DeviceType.fromWidth(viewportWidth);
if (_lastSize != newSize) {
setState(() {});
}
}

double get viewportWidth => MediaQuery.of(context).size.width;

@override
Widget build(BuildContext context) {
_lastSize = DeviceType.fromWidth(viewportWidth);
return widget.builder(_lastSize);
}
}

Мы хотим перестроить дочерний элемент только при изменении типа устройства.
Наши точки останова:

enum DeviceType {
small(0),
medium(600),
large(1024),
Xlarge(2200);

final double breakpoint;

const DeviceType(this.breakpoint);

static DeviceType fromWidth(double width) {
return switch (width) {
< 600 => DeviceType.small,
< 1024 => DeviceType.medium,
< 2200 => DeviceType.large,
_ => DeviceType.Xlarge,
};
}
}


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

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

#flutter #dart #flutterpulse #FlutterPulseTips #MobileDevelopment #ResponsiveDesign #UI #UX #Widgets #CodingTips
Выход за рамки Material: добавление пользовательских цветов в тему Flutter

Хотите выйти за пределы стандартных ограничений Material Design в вашем приложении Flutter? 🤔 В этой статье мы расскажем, как создать расширение темы для добавления пользовательских цветов! 🎨

Шаг 1: Создание ThemeExtension
Для начала создайте класс, который будет предоставлять ваши цвета. Этот класс должен расширять ThemeExtension. Пример реализации:


import 'package:flutter/material.dart';

class AppareanceKitColors extends ThemeExtension<AppareanceKitColors> {
final Color primary;
final Color secondary;
final Color dark;
final Color onePrimary;
final Color background;
final Color onbackground;
final Color surface;
final Color onSurface;
final Color grey1;
final Color grey2;
final Color grey3;
final Color error;

const AppareanceKitColors({
required this.primary,
required this.secondary,
required this.dark,
required this.onePrimary,
required this.background,
required this.onbackground,
required this.surface,
required this.onSurface,
required this.grey1,
required this.grey2,
required this.grey3,
required this.error,
});

factory AppareanceKitColors.light() => const AppareanceKitColors(
primary: Color(0xFFF830FF),
secondary: Color(0xFF3057AD),
dark: Color(0xFF20001D),
onePrimary: Color(0xFF110551),
background: Color(0xFFFFFFFF),
onbackground: Color(0xFF110551),
surface: Color(0xFFAEAEAE),
onSurface: Color(0xFF000000),
grey1: Color(0xFFF9E5FF),
grey2: Color(0xFFFFD8FF),
grey3: Color(0xFF632338),
error: Color(0xFFC41E1E),
);
}



Шаг 2: Добавление расширения в тему Material
Теперь добавьте созданное расширение в вашу тему Material, используя свойство extensions:


MaterialApp(
theme: ThemeData(
extensions: [
AppareanceKitColors.light(),
],
),
)



Шаг 3: Использование цветов из расширения
Чтобы получить доступ к вашим цветам в любом месте приложения, используйте следующий код:


extension AppareanceKitThemeExt on BuildContext {
AppareanceKitColors get colors => Theme.of(this).extension<AppareanceKitColors>()!;
}

// Использование
Container(
color: context.colors.primary,
)



Оцените новую рубрику Flutter Pulse Tips и оставьте свои отзывы! 👍💬

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

#flutter #dart #flutterpulse #FlutterPulseTips #mobiledevelopment #appdevelopment #uiux #codingtips #FlutterTips #ThemeExtension #CustomColors
Шаблон Riverpod: упрощаем работу с состоянием приложения

Привет, разработчики Flutter! 👋 Сегодня мы рассмотрим полезный совет по использованию Riverpod - популярной библиотеки для управления состоянием приложения. 📈

Проблема: при использовании Riverpod часто приходится писать повторяющийся код, например, ref.read(myProvider).xxx. Это может быть утомительно и привести к ошибкам. 😩

Решение: использование расширений Dart для создания удобных шорткатов. 🔥



extension UserSessionRepositoryProvider on Ref {
UserSessionRepository get userSessionRepository =>
read(userSessionRepositoryProvider);

UserSessionRepository get userSessionRepository$ =>
watch(userSessionRepositoryProvider);
}



Эти расширения позволяют легко получать экземпляр UserSessionRepository, используя ref.userSessionRepository или следить за его изменениями с помощью ref.userSessionRepository$. 🔄

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



Future<UserSession> startSession({
required Session session,
}) async {
final activeSession = await ref.userSessionRepository
.getActiveSession(idOrThrow);
if (activeSession != null) {
throw AlreadyRunningSessionException();
}
return ref.userSessionRepository.start(
idOrThrow,
UserSession.fromSession(session),
);
}



Такой подход делает код чище и читабельнее. 📚

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

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

#flutter #dart #flutterpulse #FlutterPulseTips #Riverpod #StateManagement #FlutterTips #MobileDevelopment #CodingTips