Hola, Amigos! Уже в воскресенье встретимся на крупнейшем IT-забеге страны — RUNIT. В этом году будет 12 000 участников и более 5 000 бегунов. Если не участвуете в забеге, все равно приходите на мероприятие, там будем мы!
На нашей площадке в этом году:
⚙️ команда — будем ждать вас, чтобы обсудить идею для стартапа или спеть «Верхом на звезде» до начала концерта;
⚙️ тент и пуфики — перевести дух в тени и расслабиться;
⚙️ кольцеброс — прошлогодняя звезда! Всем так понравилось играть, что мы решили повторить и в этом году. Победителей ждут вкусные подарки и фирменные носки от наших партнеров Babushkasocks.
Приходите, побеждайте и забирайте крутые призы!❤️
На нашей площадке в этом году:
Приходите, побеждайте и забирайте крутые призы!
Please open Telegram to view this post
VIEW IN TELEGRAM
❤2🔥2😍2
Hola, amigos!
Ждем всех на RUNIT!
У нас много подарков и веселые активности
Приходите на стенд Amiga
Ждем всех на RUNIT!
У нас много подарков и веселые активности
Приходите на стенд Amiga
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
🔥17👍5❤2
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🤬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