Вопрос использования ассетов в Flutter web проекте

Всем доброго дня!

Меня зовут Алексей, я основатель и frontend разработчик системы автоматизации работы управляющих компаний «Оператор 18».

Сейчас я переписываю проекта с нуля, с учётом ошибок применения архитектуры и структуры самого проекта.

Посмотреть вторую версию системы (то что готово) и понажимать на кнопки можно тут. Доступ в систему: Логин operator@mail. ru, пароль: operator.

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

В этой статье я хочу рассказать об опыте применения ассетов (assets), а именно картинок для web приложения написанного на фреймворке Flutter.

В системе «Оператор 18» основным элементом является реестр заявок. Выглядит он следующим образом:

Вопрос использования ассетов в Flutter web проекте

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

Вопрос использования ассетов в Flutter web проекте

Все изображения статусов — это png картинки, которые я добавил в проект, а именно — в папку assets/icons в корне проекта. И еще прописал зависимости в pubspec.yaml:

... flutter: uses-material-design: true assets: - assets/icons/ ...

В самом коде я получаю картинку просто обращаясь к текущему статусу заявки и, в зависимости от статуса, геттер отдает мне ту или иную картинку:

extension StatusIcon on UserRequest { Widget? get requestStatusIcon { if (status == RS.received) { return Image.asset( 'icons/request_status/received.png', ); } if (status == RS.inProgress) { return Image.asset( 'icons/request_status/in_progress.png', ); } // и так далее, аналогично отдавал нужные картинки } }

Ну, кажется всё! Бидлим проект, загружаем на сервер и… получаем следующий результат:

Вопрос использования ассетов в Flutter web проекте

Как видно, ни одна картинка не подгрузилась. Но если открыть консоль Google Chrome, станет сразу понятно, что браузер не знает где взять эти самые картинки (хоть они и есть на сервере).

Чтобы это поправить, нужно прописать ещё некоторые моменты, а именно:

1 Открываем файл web/index. html и добавляем описание картинок в него:

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta content="IE=Edge" http-equiv="X-UA-Compatible"> <meta name="description" content="Управляющая компания"> <!-- iOS meta tags & icons --> <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black"> <meta name="apple-mobile-web-app-title" content="Управляющая компания"> <link rel="apple-touch-icon" href="icons/Icon-192.png"> <!-- Ниже указываем все кастомные картинки которые используются в проекте, из разрешение и пусть к ним --> <link rel="icon" type="image/png" sizes="512x512" href="icons/request_status/cancelled.png"> <link rel="icon" type="image/png" sizes="512x512" href="icons/request_status/common_done.png"> <!-- и так далее... --> <!-- Дальше идет код стандартный для index.html файла Flutter проекта --> <!-- Favicon --> <link rel="shortcut icon" type="image/png" href="favicon.png" /> <link rel="stylesheet" href="loader.css"> <title>Управляющая компания</title> <link rel="manifest" href="manifest.json"> </head> <body> // ... </body> </html>

2 Открываем далее web/manifest. json и добавляем следующий код:

{ "name": "Управляющая компания", "short_name": "Управляющая компания", "start_url": ".", "display": "standalone", "background_color": "#0175C2", "theme_color": "#0175C2", "description": "Управляющая компания", "orientation": "portrait-primary", "prefer_related_applications": false, "icons": [ // прописываем место расположения картинки и размер { "src": "icons/Icon-192.png", "sizes": "192x192", "type": "image/png" }, { "src": "icons/Icon-512.png", "sizes": "512x512", "type": "image/png" }, { "src": "icons/request_status/cancelled.png", "sizes": "512x512", "type": "image/png" }, // ... и так далее по всем картинкам которые есть ] }

Снова билдим и деплоим на сервер. Теперь картинки загружаются!

Но некоторые картинки в итоге выглядят не очень хорошо, как будто бы разрешение картинки не подходит для разрешения экрана. К слову сказать, я использую flutter_screenutil, и размер экрана выбран 1920 х 1080 пикселей (может быть в этом проблема).

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

Сама иконка статуса теперь оформлена следующим образом:

xtension StatusIcon on UserRequest { Widget? get requestStatusIcon { if (status == RS.received) { return Container( alignment: Alignment.center, height: 32.h, width: 32.w, decoration: BoxDecoration( color: AppColors.grey_1, borderRadius: BorderRadius.circular(8.r), ), // иконка для статуса "Получна" child: Icon( Icons.inbox_outlined, color: AppColors.grey_2, size: 20.w, ), ); } // контейнеры с иконками для других статусов... } }

А страница с заявками выглядит так:

Вопрос использования ассетов в Flutter web проекте

По итогу, я получил:

  • экономию времени;
  • отсутсвие необходимости контроля множества файлов;
  • отсутсвие необходимости использовать множество картинок для разных разрешений экрана (1х, 2х и т. д.);
  • упрощенную процедуру деплоя очередной сборки на сервер.

Спасибо за прочтение! Буду благодарен за критику/советы/иные комментарии.

2
Начать дискуссию