##目的
Fioriで1ページの画面を作るときに使う代表的な3つのレイアウトを実装し、実装の手間やわかりやすさなどを比較してみます。
関連記事:【Fiori】2つの基本的なレイアウトについて
紹介するレイアウト
- Dynamic Page
- Semantic Page
- Object Page
##3つのレイアウトの構成
SAPUI5 version: 1.73.1のAPI Referenceをもとに、それぞれのレイアウトがどのようなaggregation(パーツ)から構成されているかを図に表しました。全てのaggregationではなく、代表的と思われるものだけ載せています。
###Dynamic Page
ヘッダー、コンテンツ、フッターから構成される基本のレイアウトです。
###Semantic Page
aggregationの種類が多く、36種類もあります。aggregationによって画面のどこに表示されるかが自動的に決まります。たとえばDelete、Copyなどのボタンごとにaggregationが用意されており、DeleteはCopyより左に来ることも決まっています。
###Object Page
ヘッダ部分はDynamic Pageと同じですが、コンテンツにあたるsectionが入れ子の構造になっています。ObjectPageSectionが一番外側で、この単位でアンカーバーと呼ばれるタブのようなものがつきます。
ObjectPageSectionと画面の対応は以下のようになります。
##実装してみた
比較のため、同じ画面パーツ(フラグメント)を使って3つの画面を実装してみました。
ソースは以下にあります。
https://github.com/miyasuta/LayoutSample
<mvc:View xmlns:core="sap.ui.core" xmlns:mvc="sap.ui.core.mvc" xmlns="sap.m"
xmlns:f="sap.f"
xmlns:l="sap.ui.layout"
controllerName="demo.Train_20_LayoutSample.controller.DynamicPage" xmlns:html="http://www.w3.org/1999/xhtml">
<f:DynamicPage id="dynamicPage" headerExpanded="true" showFooter="true">
<f:title>
<f:DynamicPageTitle>
<f:heading>
<core:Fragment fragmentName="demo.Train_20_LayoutSample.fragment.Heading" type="XML" />
</f:heading>
<f:content>
<core:Fragment fragmentName="demo.Train_20_LayoutSample.fragment.TitleContent" type="XML" />
</f:content>
<f:actions>
<core:Fragment fragmentName="demo.Train_20_LayoutSample.fragment.Actions" type="XML" />
</f:actions>
<f:breadcrumbs>
<core:Fragment fragmentName="demo.Train_20_LayoutSample.fragment.Breadcrumbs" type="XML" />
</f:breadcrumbs>
<f:navigationActions>
<core:Fragment fragmentName="demo.Train_20_LayoutSample.fragment.NavigationActions" type="XML" />
</f:navigationActions>
</f:DynamicPageTitle>
</f:title>
<f:header>
<f:DynamicPageHeader pinnable="true">
<core:Fragment fragmentName="demo.Train_20_LayoutSample.fragment.HeaderContent" type="XML" />
</f:DynamicPageHeader>
</f:header>
<f:content>
<core:Fragment fragmentName="demo.Train_20_LayoutSample.fragment.MainContent" type="XML" />
</f:content>
<f:footer>
<core:Fragment fragmentName="demo.Train_20_LayoutSample.fragment.FooterActions" type="XML" />
</f:footer>
</f:DynamicPage>
</mvc:View>
<mvc:View xmlns:core="sap.ui.core" xmlns:mvc="sap.ui.core.mvc" xmlns="sap.m"
xmlns:l="sap.ui.layout"
xmlns:semantic="sap.f.semantic"
controllerName="demo.Train_20_LayoutSample.controller.SemanticPage" xmlns:html="http://www.w3.org/1999/xhtml">
<semantic:SemanticPage id="semanticPage" headerPinnable="true" showFooter="true">
<semantic:titleHeading>
<core:Fragment fragmentName="demo.Train_20_LayoutSample.fragment.Heading" type="XML" />
</semantic:titleHeading>
<semantic:titleContent>
<core:Fragment fragmentName="demo.Train_20_LayoutSample.fragment.TitleContent" type="XML" />
</semantic:titleContent>
<semantic:headerContent>
<core:Fragment fragmentName="demo.Train_20_LayoutSample.fragment.HeaderContent" type="XML" />
</semantic:headerContent>
<semantic:content>
<core:Fragment fragmentName="demo.Train_20_LayoutSample.fragment.MainContent" type="XML" />
</semantic:content>
<semantic:titleBreadcrumbs>
<core:Fragment fragmentName="demo.Train_20_LayoutSample.fragment.Breadcrumbs" type="XML" />
</semantic:titleBreadcrumbs>
<!--Header actions-->
<semantic:titleMainAction>
<semantic:TitleMainAction text="Edit"/>
</semantic:titleMainAction>
<semantic:titleCustomTextActions>
<Button text="Toggle Footer" press="onToggleFooter" />
</semantic:titleCustomTextActions>
<semantic:copyAction>
<semantic:CopyAction />
</semantic:copyAction>
<semantic:deleteAction>
<semantic:DeleteAction />
</semantic:deleteAction>
<!--Navigation actions-->
<semantic:fullScreenAction>
<semantic:FullScreenAction press="onFullScreen" visible="{= ${/actionButtonsInfo/midColumn/fullScreen} !== null }"/>
</semantic:fullScreenAction>
<semantic:exitFullScreenAction>
<semantic:ExitFullScreenAction press="onExitFullScreen" visible="{= ${/actionButtonsInfo/midColumn/exitFullScreen} !== null }" />
</semantic:exitFullScreenAction>
<semantic:closeAction>
<semantic:CloseAction press="onClose" visible="{= ${/actionButtonsInfo/midColumn/closeColumn} !== null }" />
</semantic:closeAction>
<!--Footer actions-->
<semantic:messagesIndicator>
<semantic:MessagesIndicator press="onMessagesButtonPress"/>
</semantic:messagesIndicator>
<semantic:positiveAction>
<semantic:PositiveAction />
</semantic:positiveAction>
<semantic:negativeAction>
<semantic:NegativeAction />
</semantic:negativeAction>
<semantic:footerCustomActions>
</semantic:footerCustomActions>
</semantic:SemanticPage>
</mvc:View>
<mvc:View xmlns:core="sap.ui.core" xmlns:mvc="sap.ui.core.mvc" xmlns="sap.m"
xmlns:l="sap.ui.layout"
xmlns:uxap="sap.uxap"
controllerName="demo.Train_20_LayoutSample.controller.ObjectPage" xmlns:html="http://www.w3.org/1999/xhtml">
<uxap:ObjectPageLayout id="objectPage" showFooter="true">
<uxap:headerTitle>
<uxap:ObjectPageDynamicHeaderTitle>
<uxap:heading>
<core:Fragment fragmentName="demo.Train_20_LayoutSample.fragment.Heading" type="XML" />
</uxap:heading>
<uxap:content>
<core:Fragment fragmentName="demo.Train_20_LayoutSample.fragment.TitleContent" type="XML" />
</uxap:content>
<uxap:actions>
<core:Fragment fragmentName="demo.Train_20_LayoutSample.fragment.Actions" type="XML" />
</uxap:actions>
<uxap:breadcrumbs>
<core:Fragment fragmentName="demo.Train_20_LayoutSample.fragment.Breadcrumbs" type="XML" />
</uxap:breadcrumbs>
<uxap:navigationActions>
<core:Fragment fragmentName="demo.Train_20_LayoutSample.fragment.NavigationActions" type="XML" />
</uxap:navigationActions>
</uxap:ObjectPageDynamicHeaderTitle>
</uxap:headerTitle>
<uxap:headerContent>
<core:Fragment fragmentName="demo.Train_20_LayoutSample.fragment.HeaderContent" type="XML" />
</uxap:headerContent>
<uxap:sections>
<uxap:ObjectPageSection title="Product">
<uxap:subSections>
<uxap:ObjectPageSubSection title="">
<uxap:blocks>
<core:Fragment fragmentName="demo.Train_20_LayoutSample.fragment.Product" type="XML" />
</uxap:blocks>
</uxap:ObjectPageSubSection>
</uxap:subSections>
</uxap:ObjectPageSection>
<uxap:ObjectPageSection title="Customer">
<uxap:subSections>
<uxap:ObjectPageSubSection title="">
<uxap:blocks>
<core:Fragment fragmentName="demo.Train_20_LayoutSample.fragment.Customer" type="XML" />
</uxap:blocks>
</uxap:ObjectPageSubSection>
</uxap:subSections>
</uxap:ObjectPageSection>
</uxap:sections>
<uxap:footer>
<core:Fragment fragmentName="demo.Train_20_LayoutSample.fragment.FooterActions" type="XML" />
</uxap:footer>
</uxap:ObjectPageLayout>
</mvc:View>
###同じ画面を作るのに要した行数
XMLビューの行数(スペースを除く)をカウントしてみました。
結果
- Dynamic Page: 40行
- Semantic Page: 69行
- Object Page: 58行
Semantic Pageは表示する項目ごとにaggregationが分かれるので、必然的に行数が多くなります。
##まとめ
実装してみて感じた各レイアウトのメリット、デメリットは以下です。
レイアウト | メリット | デメリット、留意点 |
---|---|---|
Dynamic Page | シンプルで実装しやすい。項目の配置の自由度が高い | ボタンの配置などについてプロジェクトで統一したルールを作ることが必要 |
Semantic Page | 出力位置が自動的に決まるので、一貫したレイアウトになる | 多数あるaggregationを使い分ける必要がある。ビューをぱっと見たときにどのような画面になるのか想像しにくい |
Object Page | コンテンツをグループ化してセクションを作れるので、多数の項目を出す画面に向いている | Dynamic Pageと同様 |