Tuesday Feb 19, 2013

Tablet Layouts

There are some popular patterns for tablets that many developers are looking to implement.  First we'll describe a few of these and show you how to achieve them.

Flowing Layouts

Flowing layouts are the easiest to achieve.  You can simply add enough content so that i won't fit onto the page and the panelPage will automatically make the content scrollable so you can view it all.  Typically you would achieve this by using a tableLayout with many rowLayout components. 

Stretch Layouts

Sometimes it is desired to just separate your layout into multiple areas that are proportional to the width of the display and size dynamically based on orientation.  Many times you don't want these areas to flow but rather to resize to the size of the application size.  Let's take an example where you want to device the screen into two vertical areas, each 50% width but 100% of the height of the page.  You can achieve it like this:

<amx:tableLayout id="tl1" width="100%" shortDesc="Detail Table">
   <amx:rowLayout id="rl2">
      <amx:cellFormat id="cf2" height="#{deviceScope.hardware.screen.availableHeight-44}" 
               inlineStyle="background-color:yellow" valign="top" width="50%"  
               shortDesc="Column1 Cell">
         <amx:outputText value="Column 1 content goes here" id="ot6" 
               inline/>
      </amx:cellFormat>
      <amx:cellFormat id="cf3" inlineStyle="background-color:Aqua;" valign="top" 
               width="50%" shortDesc="Column2 Cell">
         <amx:outputText value="Column 2 content goes here" id="ot7" 
               inline/>
      </amx:cellFormat>
   </amx:rowLayout>
</amx:tableLayout> 

Note that the height attribute uses the availableHeight attribute of the deviceScope and the 44px is the height of the header (in a future release we may have some kind of constant so you don't need to hardcode this).  The availableHeight will change dynamically if the orientation changes.  The width of each cell can be set with percentages.  It is not possible to set the height using percentages with the tableLayout.  

Swim Lanes

This type of layout allows row of data to scroll horizontally independently of each other.  The lanes themselves can also be moved up and down so many different lanes can appear.  Below is an example.  You could replace the multiple hardcoded panelGroupLayout's with an iterator component to stamp out components based on a data collection. 

 <amx:tableLayout id="tl1" width="100%" shortDesc="Detail Table" cellPadding="0" 
      cellSpacing="0">
    <amx:rowLayout id="rlh1">
        <amx:cellFormat id="cfh1" valign="middle" height="30" 
                inlineStyle="background-color:blue" width="100%" 
                shortDesc="Content1 Header Cell" header="true">
            <amx:outputText value="Content1 Header" id="oth1"/>
        </amx:cellFormat>
    </amx:rowLayout>
    <amx:rowLayout id="rlc1">
        <amx:cellFormat id="cfc1" inlineStyle="background-color:yellow" width="100%" 
            shortDesc="Content1 Cell">
            <amx:panelGroupLayout id="panelGroupLayout5" inlineStyle="width:100%" 
                layout="horizontal">
                <amx:panelGroupLayout id="pgl11" styleClass="adfmf-panelGroupLayout-groupBox"
                                      inlineStyle="width:100px;height:100px">
                    <amx:outputText value="Lane1 Item1" id="otr11"/>
                </amx:panelGroupLayout>
                <amx:panelGroupLayout id="pgl12" styleClass="adfmf-panelGroupLayout-groupBox"
                                      inlineStyle="width:100px;height:100px">
                    <amx:outputText value="Lane1 Item2" id="otr12"/>
                </amx:panelGroupLayout>
                <amx:panelGroupLayout id="pgl13" styleClass="adfmf-panelGroupLayout-groupBox"
                                      inlineStyle="width:100px;height:100px">
                    <amx:outputText value="Lane1 Item3" id="otr13"/>
                </amx:panelGroupLayout>
                <amx:panelGroupLayout id="pgl14" styleClass="adfmf-panelGroupLayout-groupBox"
                                      inlineStyle="width:100px;height:100px">
                    <amx:outputText value="Lane1 Item4" id="otr14"/>
                </amx:panelGroupLayout>
                <amx:panelGroupLayout id="pgl15" styleClass="adfmf-panelGroupLayout-groupBox"
                                      inlineStyle="width:100px;height:100px">
                    <amx:outputText value="Lane1 Item5" id="otr15"/>
                </amx:panelGroupLayout>
                <amx:panelGroupLayout id="pgl16" styleClass="adfmf-panelGroupLayout-groupBox"
                                      inlineStyle="width:100px;height:100px">
                    <amx:outputText value="Lane1 Item6" id="otr16"/>
                </amx:panelGroupLayout>
                <amx:panelGroupLayout id="pgl17" styleClass="adfmf-panelGroupLayout-groupBox"
                                      inlineStyle="width:100px;height:100px">
                    <amx:outputText value="Lane1 Item7" id="otr17"/>
                </amx:panelGroupLayout>
                <amx:panelGroupLayout id="pgl18" styleClass="adfmf-panelGroupLayout-groupBox"
                                      inlineStyle="width:100px;height:100px">
                    <amx:outputText value="Lane1 Item8" id="otr18"/>
                </amx:panelGroupLayout>
                <amx:panelGroupLayout id="pgl19" styleClass="adfmf-panelGroupLayout-groupBox"
                                      inlineStyle="width:100px;height:100px">
                    <amx:outputText value="Lane1 Item9" id="otr19"/>
                </amx:panelGroupLayout>
                <amx:panelGroupLayout id="pgl110" styleClass="adfmf-panelGroupLayout-groupBox"
                                      inlineStyle="width:100px;height:100px">
                    <amx:outputText value="Lane1 Item10" id="otr110"/>
                </amx:panelGroupLayout>
            </amx:panelGroupLayout>
        </amx:cellFormat>
    </amx:rowLayout>
 </amx:tableLayout> 

Tiled Layouts

A popular layout is to have a horizontal layout of "tiled" objects that will move horizontally across the page until no more will fit and then wrap to the next line and continue until all are completed.  The entire page may scroll to enable the user to see all tiled objects.  Note that currently you need to apply the "display:inline-block" CSS attribute added to the child components that you want to wrap.  In a later release, this may be done automatically for you but until then you'll need to add this yourself.   This can be achieved by the following:

<amx:tableLayout id="tl1" width="100%" shortDesc="Detail Table">
    <amx:rowLayout id="rl1">
          <amx:cellFormat id="cfh2" valign="middle" height="30" inlineStyle="background-color:blue" 
                      width="100%" shortDesc="Content Header Cell" header="true">
              <amx:outputText value="Content Header" id="ot3" inline/>
        </amx:cellFormat>
    </amx:rowLayout>
    <amx:rowLayout id="rl2">
          <amx:cellFormat id="cf2" height="#{deviceScope.hardware.screen.availableHeight-44-30}"
                      inlineStyle="background-color:yellow" valign="top" width="50%" 
                      shortDesc="Column1 Cell">
              <amx:panelGroupLayout id="pgl1"
                      inlineStyle="height:100%">
                  <amx:panelGroupLayout id="pglw" layout="wrap">
                    <amx:panelGroupLayout id="pgl11" styleClass="adfmf-panelGroupLayout-groupBox"
                                            inlineStyle="width:100px;height:100px;display:inline-block">
                        <amx:outputText value="Lane1 Item1" id="otr11"/>
                      </amx:panelGroupLayout>
                    <amx:panelGroupLayout id="pgl12" styleClass="adfmf-panelGroupLayout-groupBox"
                                            inlineStyle="width:100px;height:100px;display:inline-block">
                        <amx:outputText value="Lane1 Item2" id="otr12"/>
                    </amx:panelGroupLayout>
                    <amx:panelGroupLayout id="pgl13" styleClass="adfmf-panelGroupLayout-groupBox"
                                            inlineStyle="width:100px;height:100px;display:inline-block">
                        <amx:outputText value="Lane1 Item3" id="otr13"/>
                    </amx:panelGroupLayout>
                    <amx:panelGroupLayout id="pgl14" styleClass="adfmf-panelGroupLayout-groupBox"
                                            inlineStyle="width:100px;height:100px;display:inline-block">
                        <amx:outputText value="Lane1 Item4" id="otr14"/>
                    </amx:panelGroupLayout>
                    <amx:panelGroupLayout id="pgl15" styleClass="adfmf-panelGroupLayout-groupBox"
                                            inlineStyle="width:100px;height:100px;display:inline-block">
                        <amx:outputText value="Lane1 Item5" id="otr15"/>
                    </amx:panelGroupLayout>
                    <amx:panelGroupLayout id="pgl16" styleClass="adfmf-panelGroupLayout-groupBox"
                                            inlineStyle="width:100px;height:100px;display:inline-block">
                        <amx:outputText value="Lane1 Item6" id="otr16"/>
                    </amx:panelGroupLayout>
                    <amx:panelGroupLayout id="pgl17" styleClass="adfmf-panelGroupLayout-groupBox"  
                                          inlineStyle="width:100px;height:100px;display:inline-block">
                        <amx:outputText value="Lane1 Item7" id="otr17"/>
                    </amx:panelGroupLayout>
                    <amx:panelGroupLayout id="pgl18" styleClass="adfmf-panelGroupLayout-groupBox" 
                                          inlineStyle="width:100px;height:100px;display:inline-block">
                        <amx:outputText value="Lane1 Item8" id="otr18"/> 
                    </amx:panelGroupLayout>
                    <amx:panelGroupLayout id="pgl19" styleClass="adfmf-panelGroupLayout-groupBox" 
                                          inlineStyle="width:100px;height:100px;display:inline-block">
                        <amx:outputText value="Lane1 Item9" id="otr19"/> 
                    </amx:panelGroupLayout>
                    <amx:panelGroupLayout id="pgl110" styleClass="adfmf-panelGroupLayout-groupBox" 
                                            inlineStyle="width:100px;height:100px;display:inline-block">
                      <amx:outputText value="Lane1 Item10" id="otr110"/> 
                    </amx:panelGroupLayout>
                    <amx:panelGroupLayout id="pgl111" styleClass="adfmf-panelGroupLayout-groupBox" 
                                            inlineStyle="width:100px;height:100px;display:inline-block">
                      <amx:outputText value="Lane1 Item11" id="otr111"/>
                    </amx:panelGroupLayout> 
                  </amx:panelGroupLayout>
            </amx:panelGroupLayout> 
          </amx:cellFormat>
    </amx:rowLayout> 
  </amx:tableLayout>

Using panelSplitter

The panelSplitter component is the most common method to achieve some simple layouts for tablets.  This provides a "navigation" facet that would typically contain a list or some kind of flowing component.  You can have multiple panelItems within the panelSplitter.  When the panelSplitter is displayed in portrait mode, the navigation facet is automatically collapsed into a popup to provide more space for the panelItems.  When in landscape mode, the navigator will appear normally.  The "position" attribute is used to define the size of the navigator facet, in either pixels or percentage.  Any of the above layout formats can be used within the panelItem so you can create a variety of master-detail layouts.  Here's an example using the stretch example above.

<amx:panelSplitter id="ps1">
    <amx:facet name="navigator">
        <amx:listView var="row" id="lv1">
            <amx:listItem id="li1" shortDesc="List Item 1">
                <amx:outputText value="Item 1" id="otli1"/>
                <amx:setPropertyListener from="Item1" to="#{pageFlowScope.item}"/>
            </amx:listItem>
            <amx:listItem id="li2" shortDesc="List Item 2">
                <amx:outputText value="Item 2" id="otli2"/>
                <amx:setPropertyListener from="Item2" to="#{pageFlowScope.item}"/>
            </amx:listItem>
            <amx:listItem id="li3" shortDesc="List Item 3">
                <amx:outputText value="Item 3" id="otli3"/>
                <amx:setPropertyListener from="Item3" to="#{pageFlowScope.item}"/>
            </amx:listItem>
            <amx:listItem id="li4" shortDesc="List Item 4">
                <amx:outputText value="Item 4" id="otli4"/>
                <amx:setPropertyListener from="Item4" to="#{pageFlowScope.item}"/>
            </amx:listItem>
            <amx:listItem id="li5" shortDesc="List Item 5">
                <amx:outputText value="Item 5" id="otli5"/>
                <amx:setPropertyListener from="Item5" to="#{pageFlowScope.item}"/>
            </amx:listItem>
            <amx:listItem id="li6" shortDesc="List Item 6">
                <amx:outputText value="Item 6" id="otli6"/>
                <amx:setPropertyListener from="Item6" to="#{pageFlowScope.item}"/>
            </amx:listItem>
            <amx:listItem id="li7" shortDesc="List Item 7">
                <amx:outputText value="Item 7" id="otli7"/>
                <amx:setPropertyListener from="Item7" to="#{pageFlowScope.item}"/>
            </amx:listItem>
            <amx:listItem id="li8" shortDesc="List Item 8">
                <amx:outputText value="Item 8" id="otli8"/>
                <amx:setPropertyListener from="Item8" to="#{pageFlowScope.item}"/>
            </amx:listItem>
            <amx:listItem id="li9" shortDesc="List Item 9">
                <amx:outputText value="Item 9" id="otli9"/>
                <amx:setPropertyListener from="Item9" to="#{pageFlowScope.item}"/>
            </amx:listItem>
            <amx:listItem id="li10" shortDesc="List Item 10">
                <amx:outputText value="Item 10" id="otli10"/>
                <amx:setPropertyListener from="Item10" to="#{pageFlowScope.item}"/>
            </amx:listItem>
        </amx:listView>
    </amx:facet>
    <amx:panelItem id="pi1">
        <amx:tableLayout id="tl1" width="100%" shortDesc="Detail Table">
            <amx:rowLayout id="rl1">
                <amx:cellFormat id="cfh2" valign="middle" height="30" inlineStyle="background-color:blue"
                                width="100%" columnSpan="2" shortDesc="Content Header Cell" header="true">
                    <amx:outputText value="Content Header" id="ot3" inlineStyle="color:White;"/>
                </amx:cellFormat>
            </amx:rowLayout>
            <amx:rowLayout id="rl2">
                <amx:cellFormat id="cf2" height="#{deviceScope.hardware.screen.availableHeight-44-30}"
                                inlineStyle="background-color:yellow" valign="top" width="50%"
                                shortDesc="Column1 Cell">
                    <amx:outputText value="Column 1 : #{pageFlowScope.item} content goes here" id="ot6"
                                    inlineStyle="color:Black;"/>
                </amx:cellFormat>
                <amx:cellFormat id="cf3" inlineStyle="background-color:Aqua;" valign="top" width="50%"
                                shortDesc="Column2 Cell">
                    <amx:outputText value="Column 2 : #{pageFlowScope.item} content goes here" id="ot7"
                                    inlineStyle="color:Black;"/>
                </amx:cellFormat>
            </amx:rowLayout>
        </amx:tableLayout>
    </amx:panelItem>
</amx:panelSplitter>


About

This blog is is dedicated to tips and tricks for developing, integrating, securing, and managing mobile applications using Oracle Mobile Platform. It is created and maintained by the Mobile Suite/Oracle ADF Mobile product development team.

Archive of past entries

Even More Mobile Development Blogs

Oracle A-Team Site - Mobile Related Entries

Code samples from the Community

Fusion Middleware Blogs

Search

Archives
« February 2013 »
SunMonTueWedThuFriSat
     
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
20
22
23
24
25
26
27
28
  
       
Today