Flutter. Много
2.76K subscribers
332 photos
23 videos
257 links
Заказать мобильную разработку: https://amiga.agency/?utm_source=tg
Заказать рекламу в канале @amiga_agency_bot

Новости Flutter-разработки, дайджесты мероприятий, личный опыт.
Download Telegram
Hola, amigos!

Ждем всех на RUNIT!

У нас много подарков и веселые активности

Приходите на стенд Amiga
🔥6
Hola, Amigos! Сегодня расскажем, как сэкономить время при работе в VSCode.

Добавьте в settings.json:


{
"editor.formatOnSave": true,
"[dart]": {
"editor.formatOnSave": false,
"editor.inlayHints.enabled": "off",
"editor.codeActionsOnSave": {
"source.fixAll": "explicit",
"source.organizeImports": "explicit",
}
}
}


⚙️ editor.formatOnSave: автоматически форматирует Dart-файлы;

⚙️ "[dart]": { "editor.formatOnSave": false }: отключает или включает дефолтный Dart Formatter при сохранении файла;

⚙️ editor.inlayHints.enabled: "off": отключает подсказки типов (inlay hints);

⚙️ source.fixAll: автоматически фиксит мелкие ошибки (добавляет const, корректирует код);

⚙️ source.organizeImports: упорядочивает и удаляет неиспользуемые импорты;

Эти настройки помогают поддерживать чистый, организованный, готовый к продакшну код без лишней рутины.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥16👍52
Hola, Amigos! Спасибо всем, кто забежал на нашу площадку на крупнейшем IT-забеге страны RUNIT'25. Нас буквально не отпускали — со всеми поболтали, тысячу раз сыграли в кольцеброс, обменялись идеями и зарядились энергией на год вперед!

⚙️Кольцеброс снова стал звездой, а брендированные подарки — шары от МосШар и носки от наших друзей из Babushkasocks быстро разлетелись между крутыми участниками.

Спасибо всем, кто был с нами в этом году, а остальных ждем в следующем — мы готовим кое-что очень классное ❤️
Please open Telegram to view this post
VIEW IN TELEGRAM
6🔥4
Как экспортировать Canvas в изображение без рендера на экране

Иногда нужно сохранить нарисованное в CustomPainter в виде PNG, но не хочется (или невозможно) отображать его на экране. Можно это сделать, используя Canvas и PictureRecorder:

Future<Uint8List> toImage(BuildContext context, Size size) async {
final devicePixelRatio = MediaQuery.of(context).devicePixelRatio;
final recorder = ui.PictureRecorder();
final canvas = Canvas(recorder);

// Масштабируем канвас под плотность пикселей
canvas.scale(devicePixelRatio);

final painter = MyPainter(); // <-- ваш кастомный painter
painter.paint(canvas, size);

// Считаем итоговый размер
final width = (size.width * devicePixelRatio).floor();
final height = (size.height * devicePixelRatio).floor();

// Получаем изображение
final imageResult = await recorder
.endRecording()
.toImage(width, height);

// Конвертируем в PNG
final byteData = await imageResult.toByteData(
format: ui.ImageByteFormat.png,
);

return byteData!.buffer.asUint8List();
}
👍17🤬21
Как создавать качественные интерфейсы, где все отступы и размеры кратные 8 px

Что это даст? По сути, «8» — это простая и эффективная система: все элементы дизайна (ширина, высота, внутренние/внешние отступы) кратны 8 px. Такой подход упрощает верстку, делает интерфейс визуально гармоничным и облегчает работу команды.

class AppSpacer extends StatelessWidget {
final double? width;
final double? height;

const AppSpacer._({Key? key, this.width, this.height}) : super(key: key);

factory AppSpacer.p32() => const AppSpacer._(height: 32, width: 32);
factory AppSpacer.p24() => const AppSpacer._(height: 24, width: 24);
factory AppSpacer.p16() => const AppSpacer._(height: 16, width: 16);
factory AppSpacer.p8() => const AppSpacer._(height: 8, width: 8);

@override
Widget build(BuildContext context) {
return SizedBox(width: width, height: height);
}
}


С помощью AppSpacer.pX() вы задаете отступы и размеры строго по системе 8: 8, 16, 24, 32. Делитесь в чате, пробовали такой метод?
👍64🤔4🤡3🔥1
Hola, Amigos! Сегодня расскажем, как открыть системные настройки, если пользователь отказался от уведомлений (особенно на iOS)

Если пользователь отключил уведомления на iOS, повторно показать системный prompt уже нельзя. Единственный вариант — перенаправить его в настройки приложения вручную.

Вариант 1 — через 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();


Делитесь в чате, использовали эти методы?
🔥52👍1
Hola, Amigos! На связи Павел Гершевич, Mobile Team Lead в Amiga. Сегодня разберемся, как нам установить релизное приложение на iOS 🙂

Для начала нам нужен файл с разрешением `.app` или .ipa — для этого собираем iOS привычным способом. Тут все зависит от вас — flutter build ios --release или flutter build ipa, а может даже архивирование через Xcode. Для IPA делать нам уже ничего не надо, а вот для других способов нам нужно достать файл:

Для сборки через консоль нужно пойти по пути /build/ios/archive/Runner.xcarchive, там нажать правой кнопкой мыши и в меню выбрать “Показать содержимое пакета”, файл будет по пути /Products/Applications/Runner.app.

Для сборки через Xcode из Organizer нажимаем правой кнопкой мыши на архив, выбираем “Show in Finder”, а дальше, как и с архивом из консоли, пока не дойдем до Runner.app.

Вся остальная работа проста. Нужно открыть Xcode, пойти по пути Windows -> Devices and Simulators -> Ваше устройство. Там будет графа Installed Apps, куда мы и добавим файл — можно либо перетащить его, либо нажать на плюсик и выбрать из системы. После этого нужно немного подождать завершения установки.

Обращаю внимание, что устройство должно быть зарегистрировано в App Store Connect на аккаунт, которому принадлежит приложение.

Пишите в чате, использовали такой метод?
Please open Telegram to view this post
VIEW IN TELEGRAM
👍43🔥2