Как экспортировать 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🤬2❤1
Как создавать качественные интерфейсы, где все отступы и размеры кратные 8 px
Что это даст? По сути, «8» — это простая и эффективная система: все элементы дизайна (ширина, высота, внутренние/внешние отступы) кратны 8 px. Такой подход упрощает верстку, делает интерфейс визуально гармоничным и облегчает работу команды.
С помощью AppSpacer.pX() вы задаете отступы и размеры строго по системе 8: 8, 16, 24, 32. Делитесь в чате, пробовали такой метод?
Что это даст? По сути, «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. Делитесь в чате, пробовали такой метод?
👍6❤4🤔4🤡3🔥1
Hola, Amigos! Сегодня расскажем, как открыть системные настройки, если пользователь отказался от уведомлений (особенно на iOS)
Если пользователь отключил уведомления на iOS, повторно показать системный prompt уже нельзя. Единственный вариант — перенаправить его в настройки приложения вручную.
Вариант 1 — через url_launcher
Вариант проще — с permission_handler:
Делитесь в чате, использовали эти методы?
Если пользователь отключил уведомления на 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();
Делитесь в чате, использовали эти методы?
🔥5❤2👍1
Hola, Amigos! На связи Павел Гершевич, Mobile Team Lead в Amiga. Сегодня разберемся, как нам установить релизное приложение на iOS 🙂
Для начала нам нужен файл с разрешением
Для сборки через консоль нужно пойти по пути
Для сборки через Xcode из Organizer нажимаем правой кнопкой мыши на архив, выбираем “Show in Finder”, а дальше, как и с архивом из консоли, пока не дойдем до
Обращаю внимание, что устройство должно быть зарегистрировано в App Store Connect на аккаунт, которому принадлежит приложение.
Пишите в чате, использовали такой метод?
Для начала нам нужен файл с разрешением
`.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
👍5❤3🔥2👎1
Hola, Amigos! Уже скоро пройдет IT-конференция BOOST. Делимся программой докладов, которая еще будет дополняться 🙂
В этом году будет 7 тематических потоков:
▫️ Управление бизнесом
▫️ Продажи
▫️ Маркетинг и PR
▫️ Управление проектами
▫️ Управление разработкой
▫️ Дизайн и креатив
▫️ Digital-маркетинг
Дополнительно к докладам на конференции вас ждут:
▫️ Мастермайнды и мастер-классы с лидерами отрасли: вы сможете получить ценные знания и навыки, которые помогут вашему агентству выйти на новый уровень.
▫️ Выставка продуктов и решений: ознакомьтесь с новейшими инструментами и технологиями, которые помогут оптимизировать процессы в вашем бизнесе.
▫️ Премьера фильма «Старая Школа».
▫️ Нетворкинг с коллегами по рынку и яркая вечерняя программа.
Регистрируйтесь по ссылке и не забудьте применить наш промокод:AMIGA10 со скидкой 10%
До встречи на BOOST!
В этом году будет 7 тематических потоков:
▫️ Управление бизнесом
▫️ Продажи
▫️ Маркетинг и PR
▫️ Управление проектами
▫️ Управление разработкой
▫️ Дизайн и креатив
▫️ Digital-маркетинг
Дополнительно к докладам на конференции вас ждут:
▫️ Мастермайнды и мастер-классы с лидерами отрасли: вы сможете получить ценные знания и навыки, которые помогут вашему агентству выйти на новый уровень.
▫️ Выставка продуктов и решений: ознакомьтесь с новейшими инструментами и технологиями, которые помогут оптимизировать процессы в вашем бизнесе.
▫️ Премьера фильма «Старая Школа».
▫️ Нетворкинг с коллегами по рынку и яркая вечерняя программа.
Регистрируйтесь по ссылке и не забудьте применить наш промокод:
До встречи на BOOST!
Please open Telegram to view this post
VIEW IN TELEGRAM
Hola, Amigos! Сегодня разберем, как ускорить скролл в ListView с помощью layout hints.
Если ваши элементы списка имеют фиксированную высоту, Flutter может работать быстрее, если вы ему это подскажете. Тогда он не будет тратить время на лишние вычисления.
Вариант 1 — через
Вариант 2 — с
А если хотите убрать лаги при быстром скролле, рассмотрите
Если ваши элементы списка имеют фиксированную высоту, Flutter может работать быстрее, если вы ему это подскажете. Тогда он не будет тратить время на лишние вычисления.
Вариант 1 — через
itemExtent
:ListView.builder(
itemCount: items.length,
itemExtent: 72, // фиксированная высота в пикселях
itemBuilder: (_, i) => ItemTile(item: items[i]),
);
Вариант 2 — с
prototypeItem
:ListView.builder(
itemCount: items.length,
prototypeItem: const ItemTile(item: sampleItem),
itemBuilder: (_, i) => ItemTile(item: items[i]),
);
А если хотите убрать лаги при быстром скролле, рассмотрите
cacheExtent
. И делитесь своим опытом использования подобных фишек в чате!🔥8👏4❤3