Home | History | Annotate | Download | only in ui
      1 page.title=Defining Layouts
      2 
      3 @jd:body
      4 
      5 <div id="tb-wrapper">
      6 <div id="tb">
      7 <h2>This lesson teaches you to</h2>
      8 <ol>
      9   <li><a href="#add-library">Add the Wearable UI Library</a></li>
     10   <li><a href="#different-layouts">Specify Different Layouts for Square and Round Screens</a></li>
     11   <li><a href="#same-layout">Use a Shape-Aware Layout</a></li>
     12 </ol>
     13 <h2>You should also read</h2>
     14 <ul>
     15   <li><a href="{@docRoot}design/wear/index.html">Android Wear Design Principles</a></li>
     16 </ul>
     17 <h2>Video</h2>
     18 <ul>
     19   <li><a href="https://www.youtube.com/watch?v=naf_WbtFAlY">Full Screen Apps for Android Wear</a></li>
     20 </ul>
     21 </div>
     22 </div>
     23 
     24 <p>Wearables use the same layout techniques as handheld Android devices, but need to be designed
     25 with specific constraints. Do not port functionality and the UI from a handheld app and expect a
     26 good experience. For more information on how to design great wearable apps, read the
     27 <a href="{@docRoot}design/wear/index.html">Android Wear Design Guidelines</a>.</p>
     28 
     29 <p>When you create layouts for Android Wear apps, you need to account for devices with square
     30 and round screens. Any content placed near the corners of the screen may be cropped on round
     31 Android Wear devices, so layouts designed for square screens do not work well on round devices.
     32 For a demonstration of this type of problem, see the video
     33 <a href="https://www.youtube.com/watch?v=naf_WbtFAlY">Full Screen Apps for Android Wear</a>.</p>
     34 
     35 <p>For example, figure 1 shows how the following layout looks on square and round screens:</p>
     36 
     37 <img src="{@docRoot}wear/images/01_uilib.png" alt="" width="500" height="261"/>
     38 <p class="img-caption"><strong>Figure 1.</strong> Demonstration of how a layout designed for
     39 square screens does not work well on round screens.</p>
     40 
     41 <pre>
     42 &lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     43     xmlns:tools="http://schemas.android.com/tools"
     44     android:layout_width="match_parent"
     45     android:layout_height="match_parent"
     46     android:orientation="vertical">
     47 
     48     &lt;TextView
     49         android:id="@+id/text"
     50         android:layout_width="wrap_content"
     51         android:layout_height="wrap_content"
     52         android:text="@string/hello_square" /&gt;
     53 &lt;/LinearLayout&gt;
     54 </pre>
     55 
     56 <p>The text does not display correctly on devices with round screens.</p>
     57 
     58 <p>The Wearable UI Library provides two different approaches to solve this problem:</p>
     59 
     60 <ul>
     61 <li>Define different layouts for square and round devices. Your app detects the shape
     62     of the device screen and inflates the correct layout at runtime.</li>
     63 <li>Use a special layout included in the library for both square and round devices. This layout
     64     applies different window insets depending on the shape of the device screen.</li>
     65 </ul>
     66 
     67 <p>You typically use the first approach when you want your app to look different depending on
     68 the shape of the device screen. You use the second approach when you want to use a similar layout
     69 on both screen shapes without having views cropped near the edges of round screens.</p>
     70 
     71 
     72 <h2 id="add-library">Add the Wearable UI Library</h2>
     73 
     74 <p>Android Studio includes the Wearable UI Library on your <code>wear</code> module by default
     75 when you use the Project Wizard. To compile your project with this library, ensure that the
     76 <em>Extras</em> &gt; <em>Google Repository</em> package is installed in
     77 the Android SDK manager and that the following dependency is included in the
     78 <code>build.gradle</code> file of your <code>wear</code> module:</p>
     79 
     80 <pre>
     81 dependencies {
     82     compile fileTree(dir: 'libs', include: ['*.jar'])
     83     <strong>compile 'com.google.android.support:wearable:+'</strong>
     84     compile 'com.google.android.gms:play-services-wearable:+'
     85 }
     86 </pre>
     87 
     88 <p>The <code>'com.google.android.support:wearable'</code> dependency is required to implement
     89 the layout techniques shown in the following sections.</p>
     90 
     91 <p><a href="/shareables/training/wearable-support-docs.zip">Download the full API
     92 reference documentation</a> for the Wearable UI Library classes.</p>
     93 
     94 
     95 <h2 id="different-layouts">Specify Different Layouts for Square and Round Screens</h2>
     96 
     97 <p>The <code>WatchViewStub</code> class included in the Wearable UI Library lets you specify
     98 different layout definitions for square and round screens. This class detects the screen shape
     99 at runtime and inflates the corresponding layout.</p>
    100 
    101 <p>To use this class for handling different screen shapes in your app:</p>
    102 
    103 <ol>
    104 <li>Add <code>WatchViewStub</code> as the main element of your activity's layout.</li>
    105 <li>Specify a layout definition file for square screens with the <code>rectLayout</code>
    106     attribute.</li>
    107 <li>Specify a layout definition file for round screens with the <code>roundLayout</code>
    108     attribute.</li>
    109 </ol>
    110 
    111 <p>Define your activity's layout as follows:</p>
    112 
    113 <pre>
    114 &lt;android.support.wearable.view.WatchViewStub
    115     xmlns:android="http://schemas.android.com/apk/res/android"
    116     xmlns:app="http://schemas.android.com/apk/res-auto"
    117     xmlns:tools="http://schemas.android.com/tools"
    118     android:id="@+id/watch_view_stub"
    119     android:layout_width="match_parent"
    120     android:layout_height="match_parent"
    121     <strong>app:rectLayout="@layout/rect_activity_wear"</strong>
    122     <strong>app:roundLayout="@layout/round_activity_wear"</strong>>
    123 &lt;/android.support.wearable.view.WatchViewStub>
    124 </pre>
    125 
    126 <p>Inflate this layout in your activity:</p>
    127 
    128 <pre>
    129 &#64;Override
    130 protected void onCreate(Bundle savedInstanceState) {
    131     super.onCreate(savedInstanceState);
    132     setContentView(R.layout.activity_wear);
    133 }
    134 </pre>
    135 
    136 <p>Then create different layout definition files for square and round screens. In this example,
    137 you need to create the files <code>res/layout/rect_activity_wear.xml</code> and
    138 <code>res/layout/round_activity_wear.xml</code>. You define these layouts in the same way that
    139 you create layouts for handheld apps, but taking into account the constraints of wearable devices.
    140 The system inflates the correct layout at runtime depending on the screen shape.</p>
    141 
    142 <h3>Accessing layout views</h3>
    143 
    144 <p>The layouts that you specify for square or round screens are not inflated until
    145 <code>WatchViewStub</code> detects the shape of the screen, so your app cannot access their views
    146 immediately. To access these views, set a listener in your activity to be notified when
    147 the shape-specific layout has been inflated:</p>
    148 
    149 <pre>
    150 &#64;Override
    151 protected void onCreate(Bundle savedInstanceState) {
    152     super.onCreate(savedInstanceState);
    153     setContentView(R.layout.activity_wear);
    154 
    155     WatchViewStub stub = (WatchViewStub) findViewById(R.id.watch_view_stub);
    156     stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() {
    157         &#64;Override public void onLayoutInflated(WatchViewStub stub) {
    158             // Now you can access your views
    159             TextView tv = (TextView) stub.findViewById(R.id.text);
    160             ...
    161         }
    162     });
    163 }
    164 </pre>
    165 
    166 
    167 <h2 id="same-layout">Use a Shape-Aware Layout</h2>
    168 
    169 <div style="float:right;margin-left:25px;width:250px">
    170 <img src="{@docRoot}wear/images/02_uilib.png" width="250" height="250" alt=""/>
    171 <p class="img-caption"><strong>Figure 2.</strong> Window insets on a round screen.</p>
    172 </div>
    173 
    174 <p>The <code>BoxInsetLayout</code> class included in the Wearable UI Library extends
    175 {@link android.widget.FrameLayout} and lets you define a single layout that works for both square
    176 and round screens. This class applies the required window insets depending on the screen shape
    177 and lets you easily align views on the center or near the edges of the screen.</p>
    178 
    179 <p>The gray square in figure 2 shows the area where <code>BoxInsetLayout</code> can automatically
    180 place its child views on round screens after applying the required window insets. To be displayed
    181 inside this area, children views specify the <code>layout_box</code> atribute with these values:
    182 </p>
    183 
    184 <ul>
    185 <li>A combination of <code>top</code>, <code>bottom</code>, <code>left</code>, and
    186     <code>right</code>. For example, <code>"left|top"</code> positions the child's left and top
    187     edges inside the gray square in figure 2.</li>
    188 <li>The <code>all</code> value positions all the child's content inside the gray square in
    189     figure 2.</li>
    190 </ul>
    191 
    192 <p>On square screens, the window insets are zero and the <code>layout_box</code> attribute is
    193 ignored.</p>
    194 
    195 <img src="{@docRoot}wear/images/03_uilib.png" width="500" height="253" alt=""/>
    196 <p class="img-caption"><strong>Figure 3.</strong> A layout definition that works on both
    197 square and round screens.</p>
    198 
    199 <p>The layout shown in figure 3 uses <code>BoxInsetLayout</code> and works on square and
    200 round screens:</p>
    201 
    202 <pre>
    203 &lt;<strong>android.support.wearable.view.BoxInsetLayout</strong>
    204     xmlns:android="http://schemas.android.com/apk/res/android"
    205     xmlns:app="http://schemas.android.com/apk/res-auto"
    206     <strong>android:background="@drawable/robot_background"</strong>
    207     android:layout_height="match_parent"
    208     android:layout_width="match_parent"
    209     <strong>android:padding="15dp"</strong>>
    210 
    211     &lt;FrameLayout
    212         android:layout_width="match_parent"
    213         android:layout_height="match_parent"
    214         <strong>android:padding="5dp"</strong>
    215         <strong>app:layout_box="all"</strong>>
    216 
    217         &lt;TextView
    218             android:gravity="center"
    219             android:layout_height="wrap_content"
    220             android:layout_width="match_parent"
    221             android:text="@string/sometext"
    222             android:textColor="@color/black" />
    223 
    224         &lt;ImageButton
    225             android:background="@null"
    226             android:layout_gravity="bottom|left"
    227             android:layout_height="50dp"
    228             android:layout_width="50dp"
    229             android:src="@drawable/ok" />
    230 
    231         &lt;ImageButton
    232             android:background="@null"
    233             android:layout_gravity="bottom|right"
    234             android:layout_height="50dp"
    235             android:layout_width="50dp"
    236             android:src="@drawable/cancel" />
    237     &lt;/FrameLayout>
    238 &lt;/android.support.wearable.view.BoxInsetLayout>
    239 </pre>
    240 
    241 <p>Notice the parts of the layout marked in bold:</p>
    242 
    243 <ul>
    244 <li>
    245   <p><code>android:padding="15dp"</code></p>
    246   <p>This line assigns padding to the <code>BoxInsetLayout</code> element. Because the window
    247   insets on round devices are larger than 15dp, this padding only applies to square screens.</p>
    248 </li>
    249 <li>
    250   <p><code>android:padding="5dp"</code></p>
    251   <p>This line assigns padding to the inner <code>FrameLayout</code> element. This padding applies
    252   to both square and round screens. The total padding between the buttons and the window insets
    253   is 20 dp on square screens (15+5) and 5 dp on round screens.</p>
    254 </li>
    255 <li>
    256   <p><code>app:layout_box="all"</code></p>
    257   <p>This line ensures that the <code>FrameLayout</code> element and its children are boxed inside
    258   the area defined by the window insets on round screens. This line has no effect on square
    259   screens.</p>
    260 </li>
    261 </ul>