UI5(十三)自定义控件、响应、多种设备显示

在这一步中,我们将用一个自定义控件来扩展SAPUI5的功能。我们希望对显示在详细信息页面上的产品进行评级,因此我们使用SAPUI5扩展机制创建了多个标准控件的组合,并添加了一些连接代码,使它们能够很好地一起工作。这样,我们可以在整个应用程序中重用控件,并将所有相关的功能保存在一个模块中。

webapp/control/ProductRating.js (New)

sap.ui.define([
	"sap/ui/core/Control"
], function (Control) {
	"use strict";
	return Control.extend("sap.ui.demo.walkthrough.control.ProductRating", {
		metadata : {
		},
		init : function () {
		},
		renderer : function (oRM, oControl) {
		}
	});
});

我们创建一个新的文件夹控件和一个文件将保存我们的新控件的productratings .js。与我们的控制器和视图一样,自定义控件从SAPUI5基对象继承了公共控件功能,对于控件来说,这是通过扩展基类sap.ui.core.Control来完成的。
自定义控件是可以在应用程序中很容易创建的小型重用组件。由于它们的特性,它们有时也被称为“记事本”或“动态”控件。自定义控件是一个JavaScript对象,它有两个特殊的部分(数据和视图)和许多实现控件功能的方法。
元数据部分定义了数据结构,从而定义了控件的API。通过这些关于控件属性、事件和聚合的元信息,SAPUI5自动创建setter和getter方法以及其他可以在应用程序中调用的便利函数。
渲染器定义了HTML结构,当控件在视图中实例化时,该结构将被添加到应用程序的DOM树中。它通常最初由SAPUI5的核心调用,在控件的属性发生改变时调用。呈现函数的参数oRM是SAPUI5呈现管理器,它可以用来向HTML页面编写字符串和控制属性。
init方法是一个特殊的函数,每当控件被实例化时,SAPUI5核心都会调用它。它可用于设置控件并准备显示其内容。

控件总是扩展sap.ui.core.Control并呈现自己。你也可以直接扩展sap.ui.core.Element或sap.ui.base.ManagedObject,如果你想重用SAPUI5的生命周期特性,包括未呈现的对象的数据绑定。请参考API参考来了解更多关于控件继承层次结构的信息。

webapp/control/ProductRating.js

sap.ui.define([
	"sap/ui/core/Control",
	"sap/m/RatingIndicator",
	"sap/m/Label",
	"sap/m/Button"
"RatingIndicator控件用于收集用户对产品的输入,一个标签显示进一步的信息,一个按钮将评级提交给应用程序以存储它。"
], function (Control, RatingIndicator, Label, Button){     
	"use strict";
	return Control.extend("sap.ui.demo.walkthrough.control.ProductRating", {
		metadata : {
			properties : {
				value: 	{type : "float", defaultValue : 0}
			},
			aggregations : {
				_rating : {type : "sap.m.RatingIndicator", multiple: false, visibility : "hidden"},
				_label : {type : "sap.m.Label", multiple: false, visibility : "hidden"},
				_button : {type : "sap.m.Button", multiple: false, visibility : "hidden"}
			},
			events : {
				change : {
					parameters : {
						value : {type : "int"}
					}
				}
			}
		},
		init : function () {
			this.setAggregation("_rating", new RatingIndicator({
				value: this.getValue(),
				iconSize: "2rem",
				visualMode: "Half",
				liveChange: this._onRate.bind(this)               "liveChange"
			}));
			this.setAggregation("_label", new Label({
				text: "{i18n>productRatingLabelInitial}"
			}).addStyleClass("sapUiSmallMargin"));
			this.setAggregation("_button", new Button({
				text: "{i18n>productRatingButton}",
				press: this._onSubmit.bind(this)                  " press"
			}).addStyleClass("sapUiTinyMarginTopBottom"));
		},

		setValue: function (fValue) {
			this.setProperty("value", fValue, true);
			this.getAggregation("_rating").setValue(fValue);
		},

		reset: function () {
			var oResourceBundle = this.getModel("i18n").getResourceBundle();

			this.setValue(0);
			this.getAggregation("_label").setDesign("Standard");
			this.getAggregation("_rating").setEnabled(true);
			this.getAggregation("_label").setText(oResourceBundle.getText("productRatingLabelInitial"));
			this.getAggregation("_button").setEnabled(true);
		},

		_onRate : function (oEvent) {
			var oRessourceBundle = this.getModel("i18n").getResourceBundle();
			var fValue = oEvent.getParameter("value");

			this.setProperty("value", fValue, true);

			this.getAggregation("_label").setText(oRessourceBundle.getText("productRatingLabelIndicator", [fValue, oEvent.getSource().getMaxValue()]));
			this.getAggregation("_label").setDesign("Bold");
		},

		_onSubmit : function (oEvent) {
			var oResourceBundle = this.getModel("i18n").getResourceBundle();

			this.getAggregation("_rating").setEnabled(false);
			this.getAggregation("_label").setText(oResourceBundle.getText("productRatingLabelFinal"));
			this.getAggregation("_button").setEnabled(false);
			this.fireEvent("change", {
				value: this.getValue()
			});
		},
		renderer : function (oRm, oControl) {
			oRm.openStart("div", oControl);
			oRm.class("myAppDemoWTProductRating");
			oRm.openEnd();
			oRm.renderControl(oControl.getAggregation("_rating"));
			oRm.renderControl(oControl.getAggregation("_label"));
			oRm.renderControl(oControl.getAggregation("_button"));
			oRm.close("div");
		}
	});
});

现在,我们用所需的自定义功能增强了新的自定义控件。在本例中,我们希望创建一个交互式的产品评级,因此我们定义一个值并使用三个内部控件,这些控件自动更新显示。RatingIndicator控件用于收集用户对产品的输入,一个标签显示进一步的信息,一个按钮将评级提交给应用程序以存储它。

因此,在数据部分,我们定义了几个属性:

Value

我们定义一个控件属性值,该属性值将保存用户在评级中选择的值。这个属性的Getter和setter函数将自动创建,如果愿意,我们还可以将它绑定到XML视图中的数据模型的一个字段。

Aggregations

如第一段所述,我们需要三个内部控制来实现我们的评级功能。因此,通过将visibility属性设置为hidden,我们创建了三个隐藏聚合。
这样,我们可以在内部控件中使用视图中设置的模型,SAPUI5将负责生命周期管理,并在不再需要这些控件时销毁它们。聚合也可以用来保存控件数组,但我们只想在每个聚合中都有一个控件,因此需要通过将属性倍数设置为false来调整基数。

_rating: A

sap.m.RatingIndicator 用户输入控件

_label: A sap.m.Label to

显示额外的信息

_button: A sap.m.Button to
提交评级

注释

可以为控件定义聚合和关联。区别在于父控件和相关控件之间的关系:
聚合 aggregation是一种强关系,它还管理相关控件的生命周期,例如,当父控件被销毁时,相关控件也被销毁。此外,控件只能分配给一个单独的聚合,如果将其分配给第二个聚合,则将自动从先前的聚合中删除该控件。

关联是一种弱关联,它不管理生命周期,可以被定义多次。为了有明确的区别,关联只存储ID,而聚合存储对控件的直接引用。在这个例子中,我们没有指定关联,因为我们想让我们的内部控制由父方管理。

更改

我们指定了一个更改事件,当评级提交时,控件将触发该事件。它包含当前值作为事件参数。应用程序可以注册到这个事件并处理类似于“常规”SAPUI5控件的结果,后者实际上是类似于自定义控件构建的。

每当控件的一个新实例被实例化时,SAPUI5就会自动调用init函数,在这个函数中,我们设置了内部控件。我们实例化这三个控件,并通过调用从sap.ui.core.Control继承来的框架方法setAggregation将它们存储在内部聚合中。我们传递上面指定的内部聚合的名称和新的控件实例。我们指定了一些控件属性以使我们的自定义控件看起来更漂亮,并为评级注册了liveChange事件,为按钮注册了press事件。标签和按钮的初始文本来自我们的i18n模型。

现在让我们先忽略其他内部帮助函数和事件处理程序,然后定义我们的渲染器。在SAPUI5呈现管理器和作为引用传递的控件实例的帮助下,可以控件渲染HTML结构。我们将外部

标签的开始呈现为div,并调方法writeControlData来呈现div标签内的控件的ID和其他基本属性。接下来,我们添加一个自定义CSS类,以便稍后在我们的CSS文件中为自定义控件定义样式规则。这个CSS类和视图中添加的其他CSS类,然后通过在呈现器实例上调用writeclass来呈现。然后关闭周围的div标签,并通过将内部聚合的内容传递给呈现管理器renderControl函数来呈现三个内部控件。这将调用控件的呈现程序并将它们的HTML添加到页面中。最后,关闭周围的
标签。

setValue是一个被重写的setter。当在控制器中调用或定义时,SAPUI5将生成一个setter来更新属性值XML视图,但是我们还需要更新隐藏聚合中的内部评级控制,以正确地反映状态。同样,我们可以跳过SAPUI5的重新呈现,这通常是在控件上的属性被更改时触发的,通过调用setProperty方法以true作为第三个参数更新控件属性。

现在我们为内部评级控制定义事件处理程序。每次用户更改评级时都会调用它。rating控件的当前值可以从sap.m.RatingIndicator控件的事件参数值中读取。使用该值,我们调用重写的setter来更新控件状态,然后更新评级旁边的标签,以显示用户当前选择的值,并显示最大值。带有占位符值的字符串是从自动分配给控件的i18n模型中读取的。

接下来,我们有用于提交评级的评级按钮的按下处理程序。我们假设对产品进行评级是一次性操作,首先禁用评级和按钮,这样用户就不允许提交另一个评级。我们还会更新标签,显示“感谢您的评价!”,然后我们触发控件的change事件,并将当前值作为参数传入,以便侦听此事件的应用程序可以对评级交互作出反应。

我们定义了reset方法,以便能够将UI上的控件状态恢复到初始状态,以便用户可以再次提交评级。

webapp/view/Detail.view.xml

<mvc:View
	controllerName="sap.ui.demo.walkthrough.controller.Detail"
	xmlns="sap.m"
	xmlns:mvc="sap.ui.core.mvc"
	xmlns:wt="sap.ui.demo.walkthrough.control">
	<Page
		title="{i18n>detailPageTitle}"
		showNavButton="true"
		navButtonPress=".onNavBack">
		<ObjectHeader
			intro="{invoice>ShipperName}"
			title="{invoice>ProductName}"/>
		<wt:ProductRating id="rating" class="sapUiSmallMarginBeginEnd" change=".onRatingChange"/>
	</Page>
</mvc:View>

在detail视图上定义了一个新的命名空间wt,这样我们就可以在视图中轻松地引用我们的自定义控件。的实例
ProductRating控件,并为更改事件注册一个事件处理程序。为了有一个合适的布局,我们还添加了一个边距样式类。

webapp/controller/Detail.controller.js

sap.ui.define([
	"sap/ui/core/mvc/Controller",
	"sap/ui/core/routing/History",
	"sap/m/MessageToast",

	"sap/ui/core/UIComponent"
], function (Controller, History, MessageToast, UIComponent) {
	"use strict";

	return Controller.extend("sap.ui.demo.walkthrough.controller.Detail", {
		…
		_onObjectMatched: function (oEvent) {        "_onObjectMatched             ``````````````"
			this.byId("rating").reset();
			this.getView().bindElement({
				path: "/" + oEvent.getParameter("arguments").invoicePath,
				model: "invoice"
			});
		},

		onNavBack: function () {
			var oHistory = History.getInstance();
			var sPreviousHash = oHistory.getPreviousHash();

			if (sPreviousHash !== undefined) {
				window.history.go(-1);
			} else {
				var oRouter = UIComponent.getRouterFor(this);
				oRouter.navTo("overview", {}, true);
			}
		},

		onRatingChange: function (oEvent) {
			var fValue = oEvent.getParameter("value");
			var oResourceBundle = this.getView().getModel("i18n").getResourceBundle();

			MessageToast.show(oResourceBundle.getText("ratingConfirmation", [fValue]));
		}
	});
});

在Detail控制器中,我们将依赖项加载到sap.m.MessageToast,因为我们将只显示一条消息,而不是将评级发送到后端,以保持示例的简单性。事件处理程序onRatingChange读取评级提交时触发的定制更改事件的值。然后,我们显示一个带有MessageToast控件中的值的确认消息。

在onObjectMatched私有方法中,我们调用reset方法,使它能够在一个不同项目的详细视图显示时立即提交另一个评级。

webapp/css/style.css

.myAppDemoWTmyCustomButton.sapMBtn {
	margin-right: 0.125rem;
}
.myAppDemoWTmyCustomText {
	font-weight: bold;
}
/*  ProductRating */
.myAppDemoWTProductRating {
	padding: 0.75rem;
}
.myAppDemoWTProductRating .sapMRI {
	vertical-align: initial;
}

为了布局控件,我们向根类添加一些填充,以使三个内部控件周围有一些空间,并覆盖RatingIndicator控件,使其与标签和按钮在一行中对齐。我们也可以在渲染器中使用更多的HTML,但这是最简单的方式,它将只应用于我们的自定义控件。但是,请注意,自定义控件在您的应用程序中,可能需要在SAPUI5未来版本的内部控件更改时进行调整。

webapp/i18n/i18n.properties

…
# Detail Page
detailPageTitle=Walkthrough - Details
ratingConfirmation=You have rated this product with {0} stars

# Product Rating
productRatingLabelInitial=Please rate this product
productRatingLabelIndicator=Your rating: {0} out of {1}
productRatingLabelFinal=Thank you for your rating!
productRatingButton=Rate

使用确认消息和我们在自定义控件中引用的字符串扩展资源包。我们现在可以用我们的全新控件在详细页面上评价产品。

约定

将自定义控件放到应用程序的控件文件夹中。

在这一步中,我们改进了应用程序的响应能力。SAPUI5应用程序可以在手机、平板电脑和桌面设备上运行,我们可以配置应用程序,以便在每个场景中充分利用屏幕属性。幸运的是,SAPUI5控件,比如sap.m.Table,已经提供了很多我们可以使用的特性。

webapp/view/InvoiceList.view.xml

<mvc:View
		controllerName="sap.ui.demo.walkthrough.controller.InvoiceList"
		xmlns="sap.m"
		xmlns:mvc="sap.ui.core.mvc">
	<Table
		id="invoiceList"
		class="sapUiResponsiveMargin"
		width="auto"
		items="{
			path : 'invoice>/Invoices',
			sorter : {
				path : 'ShipperName',
				group : true
			}
		}">
		<headerToolbar>
			<Toolbar>
				<Title text="{i18n>invoiceListTitle}"/>
				<ToolbarSpacer/>
				<SearchField width="50%" search=".onFilterInvoices"/>
			</Toolbar>
		</headerToolbar>
		"----------------------------------------------------------------------------------------------"
		<columns>
			<Column
				hAlign="End"
				minScreenWidth="Small"
				demandPopin="true"
				width="4em">
				<Text text="{i18n>columnQuantity}"/>
			</Column>
			<Column>
				<Text text="{i18n>columnName}"/>
			</Column>
			<Column
				minScreenWidth="Small"
				demandPopin="true">
				<Text text="{i18n>columnStatus}"/>
			</Column>
			<Column
				minScreenWidth="Tablet"
				demandPopin="false">
				<Text text="{i18n>columnSupplier}"/>
			</Column>
			<Column
				hAlign="End">
				<Text text="{i18n>columnPrice}"/>
			</Column>
		</columns>
		<items>
		"----------------------------------------------------------------------------------------"
			<ColumnListItem
				type="Navigation"
				press=".onPress">
				<cells>
					<ObjectNumber number="{invoice>Quantity}" emphasized="false"/>
					<ObjectIdentifier title="{invoice>ProductName}"/>
					<Text text="{
						path: 'invoice>Status',
						formatter: '.formatter.statusText'
					}"/>
					<Text text="{invoice>ShipperName}"/>
					<ObjectNumber
						number="{
							parts: [{path: 'invoice>ExtendedPrice'}, {path: 'view>/currency'}],
							type: 'sap.ui.model.type.Currency',
							formatOptions: {
								showMeasure: false
							}
						}"
						unit="{view>/currency}"
						state="{= ${invoice>ExtendedPrice} > 50 ? 'Error' : 'Success' }"/>
				</cells>
			</ColumnListItem>
		</items>
	</Table>

</mvc:View>

只需替换标记,就可以用表交换与

。这个表有一个内置的响应功能,可以让我们的应用程序更灵活。表和列表共享相同的属性集,因此我们可以简单地重用它们和排序器。因为一个表的每一行都有多个单元格,所以我们必须为表定义列,并根据数据为这些列命名。我们在列聚合中添加了5个sap.m.Column控件,每个控件的配置都稍有不同:

Quantity
该列将包含一个短数字,因此我们将对齐方式设置为End(在LTR语言中意味着“右”),并将宽度设置为4em,这对于列描述来说足够长了。我们使用sap.m.Text控件作为描述文本,该控件引用资源包的一个属性。我们将属性minScreenWidth设置为Small,表示这一列在手机上不那么重要。通过将demandPopin属性设置为true,我们将告诉表在主列下面显示这一列。

Name
我们的主列有一个相当大的宽度,以显示所有的细节。它将始终显示。

Status
状态不是那么重要,所以我们也可以通过设置minScreenWidth为small和demandPopin为true在小屏幕的name字段下面显示它

Supplier
我们通过设置minScreenWidth为Tablet和demandPopin为false来完全隐藏手机设备上的Supplier列。

Price
这一栏总是可见的,因为它包含了我们的发票价格。我们将不再使用以前的ObjectListItem,而是将信息拆分到与上面定义的列匹配的单元格上。因此,我们将其更改为具有相同属性的columnlisttitem控件,但现在使用了单元格聚合。这里我们创建了五个控件来显示我们的数据:

Quantity

绑定到数据字段的简单的sap.m.ObjectNumber控件。

Name

一个sap.m.ObjectIdentifier控件用于指定名称。

Status

一个具有与以前相同的格式化程序的sap. m.t文本控件。

Supplier

一个简单的sap.m.Text控件。

Price

一个ObjectNumber控件,具有与前面步骤中的属性number和numberUnit相同的格式化程序。

现在我们已经响应地定义了我们的表,当我们减少浏览器的屏幕大小时,可以看到结果。供应商栏不显示手机大小,数量和状态两栏将显示在名称下面。

webapp/i18n/i18n.properties

...
# Invoice List
invoiceListTitle=Invoices
invoiceStatusA=New
invoiceStatusB=In Progress
invoiceStatusC=Done
columnQuantity=Quantity
columnName=Name
columnSupplier=Supplier
columnStatus=Status
columnPrice=Price

# Detail Page
...

我们将列名和属性标题添加到i18n文件中。当我们缩小浏览器的屏幕尺寸或在一个小设备上打开应用程序时,我们可以看到结果。

约定

为手机、平板电脑和桌面设备的不同屏幕尺寸优化应用程序。

现在,我们根据运行应用程序的设备配置控件的可见性和属性。通过使用sap.ui.Device API并定义一个设备模型,我们将使应用程序在许多设备上看起来很棒。

webapp/view/HelloPanel.view.xml

<mvc:View
	controllerName="sap.ui.demo.walkthrough.controller.HelloPanel"
	xmlns="sap.m"
	xmlns:mvc="sap.ui.core.mvc">
	<Panel
		headerText="{i18n>helloPanelTitle}"
		class="sapUiResponsiveMargin"
		width="auto"
		expandable="{device>/system/phone}"
		expanded="{= !${device>/system/phone} }">
		<content>
			<Button
				id="helloDialogButton"
				icon="sap-icon://world"
				text="{i18n>openDialogButtonText}"
				press=".onOpenDialog"
				class="sapUiSmallMarginEnd sapUiVisibleOnlyOnDesktop"/>
			<Button
				text="{i18n>showHelloButtonText}"
				press=".onShowHello"
				class="myCustomButton"/>
			<Input
				value="{/recipient/name}"
				valueLiveUpdate="true"
				width="60%"/>
			<FormattedText
				htmlText="Hello {/recipient/name}"
				class="sapUiSmallMargin sapThemeHighlight-asColor myCustomText"/>
		</content>
	</Panel>
</mvc:View>

我们添加了两个可扩展的新属性并将其扩展到HelloPanel。在屏幕较小的设备上,用户现在可以关闭或打开面板,为下面的表留出更多的空间。可扩展属性绑定到名为device的模型和路径/系统/电话。因此,面板只能在电话设备上扩展。设备模型由SAPUI5的sap.ui.Device API填充。扩展属性控制面板的状态,我们使用表达式绑定语法在手机设备上关闭它,并在所有其他设备上扩展面板。SAPUI5的设备API提供了更多的功能来检测各种设备特定的设置,请查看文档以了解更多细节。

设备API基于用户代理和设备的许多其他属性来检测设备类型(手机、平板电脑、桌面)。因此,简单地缩小屏幕尺寸并不会改变设备类型。要测试此功能,您必须在浏览器中启用设备模拟,或在实际设备上打开设备模拟。

当我们设置像sapUiVisibleOnlyOnDesktop或sapUiHideOnDesktop这样的CSS类时,我们也可以根据设备类型隐藏单个控件。我们只在桌面设备上显示打开对话框的按钮,而在其他设备上隐藏它。有关更多选项,请参阅下面链接的文档。

webapp/Component.js

sap.ui.define([
	"sap/ui/core/UIComponent",
	"sap/ui/model/json/JSONModel",
	"./controller/HelloDialog",
	"sap/ui/Device"
], function (UIComponent, JSONModel, HelloDialog, Device) {
	"use strict";
	return UIComponent.extend("sap.ui.demo.walkthrough.Component", {
		metadata: {
			manifest: "json"
		},
		init: function () {
			// call the init function of the parent
			UIComponent.prototype.init.apply(this, arguments);

			// set data model
			var oData = {
				recipient: {
					name: "World"
				}
			};
			var oModel = new JSONModel(oData);
			this.setModel(oModel);
			// disable batch grouping for v2 API of the northwind service
			this.getModel("invoice").setUseBatch(false);

			// set device model
			var oDeviceModel = new JSONModel(Device);
			oDeviceModel.setDefaultBindingMode("OneWay");
			this.setModel(oDeviceModel, "device");

			// set dialog
			this._helloDialog = new HelloDialog(this.getRootControl());
			// create the views based on the url/hash
			this.getRouter().initialize();
		},

		exit : function () {
			this._helloDialog.destroy();
			delete this._helloDialog;
		},

		openHelloDialog : function () {
			this._helloDialog.open();
		}

	});
});

在app组件中,我们给sap.ui.Device添加了一个依赖,并在init方法中初始化设备模型。我们可以简单地传递已加载的依赖项设备到JSONModel的构造函数。这将使SAPUI5设备API的大部分属性作为JSON模型可用。然后在组件上将模型设置为命名模型,这样我们就可以在数据绑定中引用它,就像我们在上面的视图中看到的那样。

我们必须将绑定模式设置为单向模式,因为设备模型是只读的,并且我们希望在将控件的属性绑定到它时避免意外更改模型。默认情况下,SAPUI5中的模型是双向的(TwoWay)。当属性更改时,绑定的模型值也会更新。

你可以使用浏览器的开发工具测试应用的设备特定功能。例如在谷歌Chrome中,你可以模拟平板电脑或手机,很容易看到效果。SAPUI5的一些响应选项仅在加载应用程序时设置,所以你可能需要重新加载页面才能看到结果。

webapp/view/Detail.view.xml

<mvc:View
	controllerName="sap.ui.demo.walkthrough.controller.Detail"
	xmlns="sap.m"
	xmlns:mvc="sap.ui.core.mvc"
	xmlns:wt="sap.ui.demo.walkthrough.control">
	<Page
		title="{i18n>detailPageTitle}"
		showNavButton="true"
		navButtonPress=".onNavBack">
		<ObjectHeader
			responsive="true"
			fullScreenOptimized="true"      "----------------------------------------------------------------------"
			number="{
				parts: [{path: 'invoice>ExtendedPrice'}, {path: 'view>/currency'}],
				type: 'sap.ui.model.type.Currency',
				formatOptions: {
					showMeasure: false
				}
			}"
			numberUnit="{view>/currency}"
			intro="{invoice>ShipperName}"
			title="{invoice>ProductName}">
			<attributes>
				<ObjectAttribute title="{i18n>quantityTitle}" text="{invoice>Quantity}"></ObjectAttribute>
				<ObjectAttribute title="{i18n>dateTitle}" text="{
					path: 'invoice>ShippedDate',
					type: 'sap.ui.model.type.Date',
					formatOptions: {
					  style: 'long',
					  source: {
						pattern: 'yyyy-MM-ddTHH:mm:ss'
					  }
					}
				  }"/>
			</attributes>
		</ObjectHeader>
		<wt:ProductRating id="rating" class="sapUiSmallMarginBeginEnd" change=".onRatingChange"/>
	</Page>
</mvc:View>

一些控件已经具有可配置的内置响应功能。通过将响应属性设置为true和fullScreenOptimized属性设置为true, ObjectHeader控件可以被置于一个更灵活的模式中。这将根据设备大小在屏幕的不同位置显示我们添加到视图的数据。
我们还将前面步骤列表中的number和numberUnit字段添加到ObjectHeader,并使用与前面步骤中货币类型相同的格式化器。然后我们定义两个属性:发票的数量和作为数据模型一部分的发货日期。到目前为止,我们还没有从发票JSON文件中使用这个shippedDate字段,它包含一个典型字符串格式的日期。
现在,我们使用Date类型,并在格式选项的源代码部分提供日期格式的模式。它将显示更易于阅读的格式化日期文本,也适合小屏幕设备。

webapp/controller/Detail.controller.js

sap.ui.define([
	"sap/ui/core/mvc/Controller",
	"sap/ui/core/routing/History",
	"sap/m/MessageToast",
	"sap/ui/model/json/JSONModel",

	"sap/ui/core/UIComponent"
], function (Controller, History, MessageToast, JSONModel, UIComponent) {
	"use strict";
	return Controller.extend("sap.ui.demo.walkthrough.controller.Detail", {
		onInit : function () {
			var oViewModel = new JSONModel({
				currency: "EUR"
			});
			this.getView().setModel(oViewModel, "view");

			var oRouter = sap.ui.core.UIComponent.getRouterFor(this);
			oRouter.getRoute("detail").attachPatternMatched(this._onObjectMatched, this);
		},
		_onObjectMatched :});

在Detail控制器中,我们只需添加带有货币定义的视图模型,以正确显示数字。代码与InvoiceList控制器文件。

webapp/i18n/i18n.properties

# Detail Page
detailPageTitle=Walkthrough - Details
ratingConfirmation=You have rated this product with {0} stars
dateTitle=Order date
quantityTitle=Quantity

我们将列名和属性标题添加到i18n文件中。当我们缩小浏览器的屏幕尺寸或在一个小设备上打开应用程序时,我们可以看到结果。

约定
为手机、平板电脑和桌面设备的不同屏幕尺寸优化应用程序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值