2.3. Ресурсы приложения

Flutter-проект может содержать не только файлы с кодом, но и различные файлы ресурсов, которые называются ассетами (англ. assets). К самым распространённым типам ресурсов относятся статические данные, файлы конфигурации, иконки и изображения.

В этом параграфе мы разберёмся, как добавить ассеты в проект и на что обратить внимание.

Как добавить новый ресурс

Для начала нам необходимо перенести нужный файл в папку проекта. Общепринятое решение — создавать папку с именем assets на уровне папки lib и хранить все ресурсы проекта в ней. Дальше необходимо указать расположение ресурса в файле pubspec.yaml в секции flutter:.

Теперь добавим наши ассеты. Рассмотрим процесс на примере:

  • изображений;
  • шрифтов;
  • текста;
  • иконок приложения;
  • стартового экрана (Launch Screen).

Изображения

Пример, как добавить изображение в файл проекта pubspec.yaml:

1flutter:
2    assets:
3      - assets/folder_name/asset_name.png ## Добавится изображение png
4      - assets/folder_name/asset_name.svg ## Добавится изображение svg
5      - assets/folder_name/ ## Добавятся все ресурсы из папки assets/folder_name
6      - my_folder/ ## Добавятся все ресурсы из папки my_folder
7      - packages/package_name/assets/folder_name/asset_name.png ## Добавится asset_name.png из пакета package_name

После добавления в проект доступ к изображению можно получить через класс AssetImage или Image.asset. Например, для показа изображения, которое находится по пути assets/folder_name/asset_name.png, нужно создать экземпляр Image.asset таким образом: Image.asset('assets/folder_name/asset_name.png').

Зависимые от pixel ratio изображения

Flutter может загружать изображения с соответствующим разрешением для текущего соотношения пикселей устройства (англ. pixel ratio).

Что такое pixel ratio

Это отношение между физическим количеством пикселей устройства и логическим количеством пикселей, с которым работает приложение.

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

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

Логический пиксель — абстрактная единица измерения, используемая для создания интерфейса приложения.

Коэффициент пикселей устройства позволяет адаптировать приложение к физическому разрешению экрана устройства. Он определяет, какое количество физических пикселей будет использоваться для отображения каждого логического пикселя в приложении. Если устройство имеет коэффициент пикселей, отличный от 1.0, то для каждого логического пикселя можно использовать несколько физических пикселей для отображения более чёткого и детализированного изображения.

Например, устройство с pixel ratio 2.0 будет использовать четыре физических пикселя (два по горизонтали и два по вертикали) для отображения каждого логического пикселя.

Класс AssetImage будет автоматически сопоставлять запрошенное изображение с наиболее подходящим по соотношению пикселей устройства. Для работы автоматического сопоставления ресурсы должны быть организованы согласно определённой структуре

1icons/icon.png
2icons/Mx/icon.png
3icons/Nx/icon.png
4...и т. д.

M и N — числовые идентификаторы, соответствующие разрешению изображения. Они указывают на соотношение пикселей устройства, для которого предназначены изображения. В этом примере icon.png считается основным ресурсом, а Mx/icon.png и Nx/icon.png — вариантами. Предполагается, что основной ресурс соответствует разрешению 1.0.

Пример, как структурировать ресурсы для изображения с именем my_icon.png:

1my_icon/my_icon.png       (mdpi)
2my_icon/1.5x/my_icon.png  (hdpi)
3my_icon/2.0x/my_icon.png  (xhdpi)
4my_icon/3.0x/my_icon.png  (xxhdpi)
5my_icon/4.0x/my_icon.png  (xxxhdpi)

На устройствах с коэффициентом пикселей 1.8 выбирается ресурс 2.0x/my_icon.png. Для устройства с коэффициентом пикселей 2.7 выбирается ресурс 3.0x/my_icon.png.

Если ширина и высота отображаемого изображения не указаны в виджете icon, используется номинальное разрешение для масштабирования ресурса таким образом, чтобы он занимал такое же пространство на экране, как основной ресурс, но с более высоким разрешением.

Другими словами, если my_icon.png имеет размер 72 пикселя по ширине и 72 пикселя по высоте, то 3.0x/my_icon.png должно иметь размер 216 пикселей по ширине и 216 пикселей по высоте. Однако, если ширина и высота не указаны, оба ресурса будут отображаться как 72 пикселя по ширине и 72 пикселя по высоте (в логических пикселях).

Для работы с ресурсами, зависимыми от разрешения, нужно указывать только основной ресурс или его родительский каталог. В примере ниже показаны оба варианта для my_icon:

1flutter:
2   assets:
3      - my_icon/my_icon.png # Основной ресурс
4      - my_icon/ # Родительский каталог

Использование изображений из зависимостей

Если изображение находится в импортируемом пакете, то для его использования необходимо указать поле package в AssetImage.

Например, если у пакета my_icons такая структура:

1pubspec.yaml
2icons/heart.png
3icons/1.5x/heart.png
4icons/2.0x/heart.png
5...

То загрузить изображение можно следующим образом:

1AssetImage('icons/heart.png', package: 'my_icons')

Шрифты

Для добавления шрифтов следует добавить файлы формата .ttc.ttf или .otf, содержащие конфигурацию шрифта, и указать их в поле fonts:

1flutter:
2  fonts:
3    - family: Raleway
4      fonts:
5        - asset: assets/fonts/Raleway-Regular.ttf
6        - asset: assets/fonts/Raleway-Italic.ttf
7          style: italic
8    - family: RobotoMono
9      fonts:
10        - asset: assets/fonts/RobotoMono-Regular.ttf
11        - asset: assets/fonts/RobotoMono-Bold.ttf
12          weight: 700

Параметр family определяет семейство шрифтов. Этот параметр используется в свойстве fontFamily класса TextStyle.

asset — путь к шрифту относительно файла pubspec.yaml. В примере Raleway-Regular.ttf лежит в папке assets/fonts, которая находится на том же уровне, что и pubspec.yaml.

Один шрифт может ссылаться на несколько файлов с различными стилями шрифтов:

  • weight определяет насыщенность начертания, представляет собой числовое значение в диапазоне от 100 до 900, кратное 100. Это значение соответствует FontWeight и используется в свойстве fontWeight класса TextStyle. К примеру, для использования RobotoMono-Bold нужно указать FontWeight.w700;
  • style определяет контур шрифта — курсивный или обычный. Значение соответствует полю fontStyle класса TextStyle и определяется объектом FontStyle. К примеру, для использования Raleway-Italic нужно установить fontStyle равным FontStyle.italic.

Текст

Для работы с текстовыми ассетами — к примеру, файлами .txt или .json — используется класс AssetBundle.

Есть два варианта работы с AssetBundle:

  • использовать статический объект rootBundle;
  • использовать объект DefaultAssetBundle;

Ниже — примеры для каждого варианта.

Пример №1: используем статический объект rootBundle

Он находится в пакете flutter/services.dart.

1  import 'package:flutter/services.dart' show rootBundle;
2  
3  await rootBundle.loadString('assets/config.json');

Пример №2: используем объект DefaultAssetBundle

DefaultAssetBundle — это InheritedWidget, который позволяет получить текущий AssetBundle, а не использовать основной набор ресурсов по умолчанию rootBundle.

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

1  import 'package:flutter/services.dart' show rootBundle;
2  import 'package:flutter/material.dart';
3  
4  class MyWidget extends StatelessWidget {
5    @override
6    Widget build(BuildContext context) {
7      return FutureBuilder(
8          future: DefaultAssetBundle.of(context).loadString('assets/config.json'),
9          builder: (context, snapshot) => Text(snapshot.data ?? ''),
10      );
11    }
12  }

Иконка приложения

Обновление иконки приложения Flutter выполняется таким же образом, как обновление иконки в нативных приложениях для Android или iOS.

Android

Untitled

iOS

Untitled

Launch Screen

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

В Android

Для добавления экрана запуска в приложении нужно перейти в папку android/app/src/main. В файле res/drawable/launch_background.xml можно использовать layer list drawable XML-файл для кастомизации экрана запуска.

Дополнительные сведения можно найти в официальной документации.

В iOS

Чтобы добавить изображение в центр, в папку ios/Runner/Assets.xcassets/LaunchImage.imageset нужно поместить изображения с именами LaunchImage.pngLaunchImage@2x.pngLaunchImage@3x.png. Для использования других имён файлов нужно обновить файл Contents.json в ios/Runner.

Также можно полностью настроить шаблон экрана запуска в Xcode, открыв ios/Runner.xcworkspace. В навигаторе проекта нужно перейти в Runner/Runner и добавить изображения, открыв Assets.xcassets или настроив экран запуска с помощью Interface Builder в файле LaunchScreen.storyboard.

Дополнительные сведения можно найти в официальной документации.


Отлично, с ассетами разобрались — теперь вы умеете добавлять их в приложение и разбираетесь в нюансах (например, что такое pixel ratio).

В следующем параграфе мы копнём на уровень глубже и поговорим о языке Dart — как он появился, зачем был придуман, какими особенностями обладает.

Чтобы добавить в заметки выделенный текст, нажмите Ctrl + E
Предыдущий параграф2.2. Flutter: зависимости проекта
Следующий параграф2.4. Коротко о Dart: часть первая