Адаптивність в MAUI. Контейнери
Maui — це сучасна технологія крос-платформного програмування. Код, написаний один раз у MAUI-проєкті, буде працювати і на Windows Machine, і на Android, і на IOS тощо. Однак тут же постає питання: як розробити інтерфейс, який буде виглядати однаково привабливо як на десктопних, так і на мобільних пристроях? Задля зручності програмування та привабливості інтерфейсу заведено використовувати контейнери компонування.
Серед них:
- StackLayout — контейнер, який виставляє компоненти в рядок по вертикалі або горизонталі. Ключовими властивостями є Orientation — спосіб розміщення та Spacing — простір між компонентами.
- VerticalStackLayout / HorizontalStackLayout — принцип схожий на StackLayout, однак напрямок фіксований. Ключовими командами тут є HorizontalOptions / VerticalOptions — вирівнювання по вертикалі або горизонталі.
Ці компоненти зручно використовувати, якщо порядок компонентів має зберігатися як на телефонах, так і на комп’ютері. Зокрема, хорошою практикою є вкладати StackLayout до Border або ScrollView, які можуть приймати тільки один дочірній елемент. (Зверніть увагу на це: компоненти в контейнерах записуються до списку Children, у той час, як вміст Border / ScrollView зберігається у властивості Content). Ключовим недоліком є неможливість роботи із відносними одиницями розмірів: тут спрацьовують тільки пікселі. Відносним рішенням є використання OnIdiom при заданні розмірів чи відступів. Але ви ніколи наперед не знаєте, наприклад, наскільки малим буде екран телефона, на якому відкриють ваш застосунок. Отже, залишається імовірність появи прокрутки або виходу дочірніх компонентів за межі області.
У прикладі, що розглядається, побудовано хедер із застосуванням HorizontalStackLayout та Grid (про нього далі). Додатково стилі було винесено до App.xaml, але суті розмітки це не змінює.
<Grid Style="{StaticResource headerGrid}" Grid.Row="0">
<HorizontalStackLayout HorizontalOptions="Start"
ColumnDefinitions="*"
RowDefinitions="*"
>
<Label Style="{StaticResource bookSailStyle}" Text="BookSail"/>
<ImageButton Source="ship.png" Style="{DynamicResource IconStyle}"/>
</HorizontalStackLayout>
<HorizontalStackLayout HorizontalOptions="Center"
Margin="{OnIdiom Desktop='50,0,0,0', Phone='15,0,0,0'}">
<Entry Style="{DynamicResource searchEntryStyle}" Placeholder="Шукати книги.."/>
<ImageButton Source="search.png" Style="{DynamicResource IconStyle}" />
</HorizontalStackLayout>
<HorizontalStackLayout HorizontalOptions="End"
Spacing="{OnIdiom Desktop=35, Phone=5}"
Margin="{OnIdiom Phone='3, 2, 10, 0', Desktop='25, 5, 50, 0'}">
<ImageButton Source="basket.png"
Command="{Binding GoToBasketCommand}"
Style="{DynamicResource IconStyle}" />
<ImageButton Source="login.png"
Style="{DynamicResource IconStyle}"
Command="{Binding GoToLoginCommand}"/>
<Switch x:Name="themeSwitch"
IsToggled="{Binding GlobalThemeState, Mode=TwoWay}" />
</HorizontalStackLayout>
</Grid>
Результат на Windows Machine:
![]()
Результат на Android:

Grid — контейнер, який розміщує компоненти в гнучкій таблиці. Його ключовими компонентами є RowDefinitions та ColumnDefinitions — визначення кількості рядків та стовпців у конкретному Grid одразу із їхніми розмірами. Тут прихована ключова перевага Grid над іншими способами компонування — він може працювати із відносними одиницями вимірювання (хоча за потреби можна застосовувати і пікселі).
Задля розміщення дочірніх елементів всередині Grid потрібно надати їм властивості Grid. Row / Grid.Column — індекс рядка та колонки для розміщення компонента (індексація з 0), Grid.RowSpan / Grid.ColumnSpan — «злиття» по рядку або стовпцю, приймає число кількості комірок.
Приклад:
<Grid RowDefinitions="Auto, *, Auto" ColumnDefinitions="1*, 2*, 100"/>
Як прочитати такий код? Auto — це команда для компонента «займи мінімальний простір, що тобі потрібен»; * - це навпаки, зайняти максимальний доступний простір. Якщо використовуються 1*, 2* абощо — це позначення співвідношення між колонками або рядками. У цьому прикладі перша колонка буде вдвічі меншою за другу. Натомість третя колонка займатиме фіксовані 100 пікселів.
Лайфхак для універсальності інтерфейсу:
<Grid RowDefinitions="Auto, *, Auto"
ColumnDefinitions="1*, 3*"
BackgroundColor="{StaticResource customGray}"
>
…
<Grid Grid.Row="1"
Grid.Column="0"
Grid.ColumnSpan="{OnIdiom Desktop=1, Phone=2}"
ZIndex="2"
VerticalOptions="{OnIdiom Desktop=Fill, Phone=Start}"
>
У цьому прикладі на «злиття» колонок для розміщення дочірнього Grid прив’язане до платформи. На телефоні компонент займає дві комірки, у той час, як на комп’ютері — тільки одну.
Сторінка виглядатиме наступним чином:



Як видно зі скріншотів, меню «фільтри» на телефоні автоматично розширюється.
FlexLayout — максимально гнучкий макет, який дає змогу розмістити компоненти як у вигляді ряду, так і таблиці. Ключових властивостей дуже багато, деякі розглянемо на прикладі:
<FlexLayout FlexLayout.Order="2"
FlexLayout.Basis="7%"
JustifyContent="SpaceAround"
AlignContent="Center"
Direction="Row"
Background="{StaticResource LightLightBlue}"
Wrap="NoWrap"
x:Name="upperNav"
Loaded="FlexLayout_Loaded"
>
Order — це властивість, яка визначає «яким по рахунку» дочірнім компонентом буде той, із яким ми працюємо.
Basis — це властивість, яка визнає допустимий для компонента простір.
JustifyContent — команда розподілу вільного простору між дочірніми елементами.
Direction — вісь розміщення компонентів.
Wrap — визначення можливості переносу компонентів на новий рядок.

На цій сторінці навігацію було створено за допомогою FlexLayout.

Отже, у цій статті було розглянути основи адаптивного дизайну в MAUI за допомогою контейнерів компонування.
Немає коментарів
Додати коментар Підписатись на коментаріВідписатись від коментарів