Урок 6. SapUI5: Device Adaptation (Мобильная адаптация)

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

Responsiveness and Adaptiveness

В четвертом уроке мы реализовали Grid, который разбивает «видимую область» на 12 колонок:
grid 12 columns

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

У кнопок, лейблов, радио кнопок есть свои Agregation (посмотрите одноименную вкладочку тут https://sapui5.hana.ondemand.com/#/api/sap.ui.core.Element (это класс, от которого наследуются элементы управления)).

Посмотрим на примере кнопки (в качество Agregation у нас layoutdata),

/layout_sapui5/blob/master/webapp/view/form.fragment.xml
1
2
3
4
5
<button text="Submit" icon="sap-icon://paper-plane" press="onPressSubmit">
	<layoutdata>		<l:griddata indent="L2 M4" span="XL12 L2 M8 S12"></l:griddata>	</layoutdata></button>

Что такое XL12 L2 M8 S12?

Подробно про данные параметры можно прочитать тут https://experience.sap.com/fiori-design-web/form/#!.

А если кратко, то это размеры экрана.

  • S — размер экрана до 600 px включительно!
  • M — размер экрана от 601 px да 1024 px включительно!
  • L — размер экрана от 1025 px до 1440 px включительно!
  • XL — размер экрана от 1441 px!

То есть, строка XL12 L2 M8 S12 означает, что

  • при размере экрана свыше 1441 px (XL) элемент будет занимать 12 блоков из 12 возможных,
  • при размере экрана от 1025 px до 1440 px (L) элемент будет занимать 2 блока из 12 возможных,
  • при размере экрана от 601 px да 1024 px (M) элемент будет занимать 8 блоков из 12 возможных,
  • при размере экрана до 600 px (S) элемент будет занимать 12 блоков из 12 возможных.

indent=»L2 M4″ — для экрана L делаем отступ 2 блока, для экрана M делаем отступ 4 блока:

Это градация экранов, состоящая из 4-х точек XL L M S. Но ест и другие градации, про которые написано в документации https://sapui5.hana.ondemand.com/#/api/sap.ui.Device.media.RANGESETS.

Так же вы можете переопределить размеры для каждой конкретной точки (Xl L M S) при помощи свойств spanXL (px) spanL spanM spanS, для переопределения отступов — indentXL (px) indentL indentM indentS.
А можно напрямую задать класс, отображать или нет данный контент на данном разрешении экрана: visibleXL (true or false) visibleL visibleM visibleS (аналогично работают visibleOnLarge, visibleOnMedium, visibleOnSmall).
linebreakXL (true or false) linebreakL linebreakM linebreakS — перенос элемента на новую строку для разных размеров экрана.

CSS классы

В SapUI5 есть специальные CSS классы, для управления контентом, в зависимости от размера экрана:

  • sapUiHideOnPhone: Элемент с данным классом будет скрыт, если экран менее 600px
  • sapUiHideOnTablet: Элемент с данным классом будет скрыт, если размер экрана в интервале 600px — 1024px
  • sapUiHideOnDesktop: Элемент с данным классом будет скрыт, если экран более 1024px
  • sapUiVisibleOnlyOnPhone: Элемент с данным классом будет отображен, если экран менее 600px
  • sapUiVisibleOnlyOnTablet: Элемент с данным классом будет отображен, если размер экрана в интервале 600px — 1024px
  • sapUiVisibleOnlyOnDesktop: Элемент с данным классом будет отображен, если экран более 1024px

Отобразим фрагмент только на экранах больших мониторов (class=»sapUiVisibleOnlyOnDesktop»):

/layout_sapui5/blob/master/webapp/view/Main.view.xml
1
<core:fragment id="idCbrFrag" fragmentName="hello.layout.view.cbr" type="XML" class="sapUiVisibleOnlyOnDesktop"></core:fragment>

Размеры элементов (Cozy & Compact)

Mobile First sapui5

SapUI5 придерживается концепции Mobile First. Посмотрите на картинку выше.
Уже «из коробки» в SapUI5, как мы уже убедились, есть много различных инструментов для адаптации дизайна под разные устройства.

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

Подключаем библиотеку sap/ui/Device при помощи define.
Затем в методе инициализации пишем:
this.getView().addStyleClass(Device.support.touch ? «sapUiSizeCozy» : «sapUiSizeCompact»);
Мы смотрим на поддержку устройством функции touch (сенсорный экран или нет). Если она есть, то подключаем Cozy (sapUiSizeCozy), иначе подключаем стили Compact (sapUiSizeCompact).

/layout_sapui5/blob/master/webapp/controller/Main.controller.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
sap.ui.define([
	"sap/ui/core/mvc/Controller",
	"sap/m/MessageToast",
	"sap/ui/Device",	"hello/layout/model/formatter",
	"hello/layout/model/type/digits"
], function(Controller, MessageToast, Device, formatter, Digits) {	"use strict";
 
	return Controller.extend("hello.layout.controller.Main", {
 
		formatter: formatter,
 
		onInit: function() {
 
			this.getView().addStyleClass(Device.support.touch ? "sapUiSizeCozy" : "sapUiSizeCompact");

А можно сделать это же, но только посложнее, как описано в документации (https://sapui5.hana.ondemand.com/#/topic/d935dbf196d34997bf1ac42ac3e81579.html):

В component.js создадим метод getContentDensityClass:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
...
		init: function () {
...		},
...
		getContentDensityClass : function() {			if (!this._sContentDensityClass) {
				if (!sap.ui.Device.support.touch) {
					this._sContentDensityClass = "sapUiSizeCompact";
				} else {
					this._sContentDensityClass = "sapUiSizeCozy";
				}
			}
			return this._sContentDensityClass;
		}
 
	});
});

В методе инициализации контроллера вызываем только что созданный метод:

1
2
3
 onInit: function () {
	this.getView().addStyleClass(this.getOwnerComponent().getContentDensityClass());		},

В представлениях для диалоговых окон обязательно надо синхронизировать стили:

1
2
// forward compact/cozy style into dialog
jQuery.sap.syncStyleClass(oView.getController().getOwnerComponent().getContentDensityClass(), oView, oDialog);

Начиная с версии SapUI5 1.30 в manifest.json можно устанавливать поддержку смены дизайнов:

1
2
3
4
5
6
7
8
9
10
11
12
...
  "sap.ui5": {
    ...     
    "dependencies": {
      ...
    },
    "contentDensities": {      "compact": true,      "cozy": true    } 
  }

Сравните для тулбара!

Compact:
Compact

Cozy:
Cozy

Или таблицы:
Compact:
Compact table

Cozy:
Cozy table

Demand popin

demandPopin — свойство колонки, которое позволяет колонке сливаться с другими колонками.

Давайте обратимся к нашему примеру:

/layout_sapui5/blob/master/webapp/view/WtEkb.fragment.xml
1
2
3
4
5
6
7
8
9
10
11
<columns>
	<column>
		<text text="Дата"></text>
	</column>
	<column minScreenWidth="Tablet" demandPopin="true">		<text text="Максимальная"></text>
	</column>
	<column minScreenWidth="Tablet" demandPopin="true">		<text text="Минимальная"></text>
	</column>
</columns>

Нормальное состояние таблицы (размер экрана больше 600px):
demand popin table

Эффект свойства demandPopin=»true» (экран меньше 600px):
demand popin sapui5

Граничный размер, после которого колонки сливаются, задаются свойством minScreenWidth=»Tablet».
В качестве значения можно использовать css сущности: «1024px» или «40em».
Можно использовать уже заранее предопределенные слова: «Phone», «Tablet», «Desktop», «Small», «Medium», «Large».

Device Models

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

Допустим, нам необходимо сделать поле недоступным для ввода:
<Input enabled=»false» … />

Хорошо, а если нам надо сделать поле недоступным для ввода только для мобильных устройств?

Решается это просто! Сделаем Device Models!

Подключаем sap/ui/Device в model/models.js и создаем JSON модель:

/layout_sapui5/blob/master/webapp/model/models.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
sap.ui.define([
	"sap/ui/model/json/JSONModel",
	"sap/ui/Device"], function(JSONModel, Device) {	"use strict";
 
	return {
 
		createDeviceModel: function() {			var oModel = new JSONModel(Device);			oModel.setDefaultBindingMode("OneWay");			return oModel;		} 
	};
});

В component.js инициализируем модель:

/layout_sapui5/blob/master/webapp/Component.js
1
2
3
4
5
6
init: function() {
	 // call the base component's init function
	 UIComponent.prototype.init.apply(this, arguments);
 
	 // set the device model
	 this.setModel(models.createDeviceModel(), "device");

А дальше в представлении уже задаем свойство для поля ввода:

/layout_sapui5/blob/master/webapp/view/form.fragment.xml
1
<input id="second" enabled="{= !${device/>/system/phone} }"

{= !${device>/system/phone} — это логическое НЕ выражения {device>/system/phone}.
То есть если вы загружаете страницу с мобильного устройство, то {device>/system/phone} вернет TRUE,а {= !${device>/system/phone} — вернет FALSE:

Device Model sapui5

Для отслеживания устройство с сенсорным экраном можно использовать {device>/support/touch}.

Для более детального изучения структуры Device Models (фильтрация по операционным системам, размерам экрана, положения устройства, браузера и т. п.) читайте https://sapui5.hana.ondemand.com/1.34.7/docs/api/symbols/sap.ui.Device.html и The Device API.