Приборкуємо Icon: як він працює зсередини?
У даній статті ми розглянемо віджет Icon, а також розкажемо про лайфхак, завдяки якому значення для піктограми можна задавати динамічно: наприклад, передавати з сервера.
Також ми переклали цю статтю англійською
Віджет Icon
У Material Framework, що входить до Flutter, є віджет Icon. Даний віджет використовується, щоб відобразити яку-небудь піктограму. Його відмінність від віджету Image у тому, що даний віджет підпорядковується встановленій темі та може бути інтегрований з віджетом, у якому він використовується (наприклад, піктограма відповідно змінює свій колір у віджеті IconButton).
Розглянемо, які параметри приймає даний віджет:
Наведений приклад виводить піктограму з колекції Material Icons. Розберемо параметри:
- Перший позиційний параметр: значення типу IconData. Його ми розглянемо нижче
- Непозиційний параметр color: значення типу Color щоб, відповідно, перефарбувати піктограму
- Непозиційний параметр size: дійсне число, розмір піктограми у пікселях
Віджет ImageIcon
Даний віджет дозволяє використовувати растрові зображення для простого створення власних піктограм:
Синтаксис аналогічний до Icon, окрім того, що у перший позиційний параметр передається об'єкт типу ImageProvider. ImageProvider це об'єкт у Flutter, що відповідає за отримання зображення іншими віджетами. Наприклад, віджетом Image.
Скоріш за все, ви ніколи не працюватимете з ImageProvider напряму, натомість, ви будете використовувати одну з готових реалізацій:
- AssetImage — отримання зображення з асетів Flutter (див. документацію щодо того, як додати зображення до списку асетів)
- NetworkImage — завантаження зображення по HTTP
- FileImage — отримання зображення з об'єкту File
- MemoryImage — отримання зображення з масиву байтів у оперативній пам'яті
- ExactAssetImage — аналог AssetImage, див. документацію щодо особливостей
У даному прикладі використовується зображення-асет.
Слід зазначити, що кольорові піктограми будуть приведені до монохромного вигляду за каналом прозорості:
Колекція Icons та CupertinoIcons
Дані класи містять у собі колекції піктограм для Material Design та iOS відповідно. Слід зазначити, що між собою дані колекції не сумісні: якщо ви розробляєте такий застосунок, що використовує Material Icons на Android, а Cupertino — на iOS, вам доведеться власноруч вказувати відповідну піктограму, або, наприклад, скористатись бібліотекою flutter_platform_widgets, яка пропонує обмежений список піктограм, що відповідають одна одній.
Список усіх піктограм для Material Design знаходиться на сторінці Material Icons. Кожна піктограма представлена у чотирьох стилях: звичайний, Rounded, Sharp та Outline. Щоб звернутися до необхідного стилю, слід додати до назви піктограми відповідне закінчення:
Список усіх наявних Cupertino Icons наведено на сторінці бібліотеки.
Піктограми та теми
Усі компоненти Material Framework підпорядковуються заданій темі. Тема задається у віджеті MaterialApp, завдяки об'єкту ThemeData та властивості theme.
Ви можете глобально змінити стиль за замовчуванням для усіх піктограм у вашому застосунку, використовуючи властивість iconTheme у ThemeData:
Але крім цього, тему можна перезаписати безпосередньо у дереві віджетів, використовуючи віджет IconTheme (варто помітити, при цьому на перезаписану піктограму властивості теми діяти припиняють):
Як працюють векторні піктограми
У Flutter для роботи векторних піктограм використовуються так звані icon fonts, тобто шрифти, що використовують символи для виводу піктограм. Насправді, коли ви використовуєте віджет Icon, Flutter створює віджет Text з спеціально заданим шрифтом. Ми переконаємося у цьому далі.
Тип IconData
IconData виступає контейнером для даних піктограми, що має бути виведено. Саме об'єкти цього типу зберігаються у колекції Icons: наприклад, Icons.people є об'єктом IconData. Давайте розглянемо конструктор цього об'єкта:
Першим позиційним параметром є ціле число, що позначає номер символу, який буде використано для поточної піктограми.
Параметр fontFamily містить назву шрифта, що використовується для виводу піктограми.
Таким чином, вивід піктограми зводиться до віджету Text (\ue8f5 - позначення символу під номером e8f5):
Крім того ж, у поле тексту можна помістити читабельну назву піктограми:
Слід зауважити, що конструктор IconData є константним, що дозволяє компілятору виключити невикористані піктограми з програми.
Динамічні піктограми й інтеграція з Material Framework
❗ Робіть зазначене нижче тільки якщо вам дійсно це треба. Дана практика шкодить розміру застосунку. Замість цього, ви можете, наприклад, завантажувати піктограму з мережі через NetworkImage та використовувати ImageIcon.
Таким чином можна зробити висновок, що використовуючи віджет Text можна відобразити піктограму за її кодом або навіть назвою. Проте, у такого підходу є суттєвий недолік: відсутність інтеграції з темою та Material Framework у цілому, адже Flutter сприймає таку піктограму як звичайний текст. Тому, ми напишемо власний об'єкт Icon, що не є константою, та який приймає назву піктограми для її відображення (див. кінець статті).
Використання:
Увага, через те, що конструктор не константний, tree shaking не працюватиме, що призведе до помилки компіляції, але дану поведінку можна виключили прапорцем збирання --no-tree-shake-icons
.
Приєднуйтесь до нашого чату.