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>Browse the <a href="{@docRoot}reference/android/support/wearable/view/package-summary.html">
     92 API 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
     98 <a href="{@docRoot}reference/android/support/wearable/view/WatchViewStub.html"><code>WatchViewStub</code></a>
     99 class included in the Wearable UI Library lets you specify different layout definitions for square
    100 and round screens. This class detects the screen shape at runtime and inflates the corresponding
    101 layout.</p>
    102 
    103 <p>To use this class for handling different screen shapes in your app:</p>
    104 
    105 <ol>
    106 <li>Add
    107 <a href="{@docRoot}reference/android/support/wearable/view/WatchViewStub.html"><code>WatchViewStub</code></a>
    108 as the main element of your activity's layout.</li>
    109 <li>Specify a layout definition file for square screens with the <code>rectLayout</code>
    110     attribute.</li>
    111 <li>Specify a layout definition file for round screens with the <code>roundLayout</code>
    112     attribute.</li>
    113 </ol>
    114 
    115 <p>Define your activity's layout as follows:</p>
    116 
    117 <pre>
    118 &lt;android.support.wearable.view.WatchViewStub
    119     xmlns:android="http://schemas.android.com/apk/res/android"
    120     xmlns:app="http://schemas.android.com/apk/res-auto"
    121     xmlns:tools="http://schemas.android.com/tools"
    122     android:id="@+id/watch_view_stub"
    123     android:layout_width="match_parent"
    124     android:layout_height="match_parent"
    125     <strong>app:rectLayout="@layout/rect_activity_wear"</strong>
    126     <strong>app:roundLayout="@layout/round_activity_wear"</strong>>
    127 &lt;/android.support.wearable.view.WatchViewStub>
    128 </pre>
    129 
    130 <p>Inflate this layout in your activity:</p>
    131 
    132 <pre>
    133 &#64;Override
    134 protected void onCreate(Bundle savedInstanceState) {
    135     super.onCreate(savedInstanceState);
    136     setContentView(R.layout.activity_wear);
    137 }
    138 </pre>
    139 
    140 <p>Then create different layout definition files for square and round screens. In this example,
    141 you need to create the files <code>res/layout/rect_activity_wear.xml</code> and
    142 <code>res/layout/round_activity_wear.xml</code>. You define these layouts in the same way that
    143 you create layouts for handheld apps, but taking into account the constraints of wearable devices.
    144 The system inflates the correct layout at runtime depending on the screen shape.</p>
    145 
    146 <h3>Accessing layout views</h3>
    147 
    148 <p>The layouts that you specify for square or round screens are not inflated until
    149 <a href="{@docRoot}reference/android/support/wearable/view/WatchViewStub.html"><code>WatchViewStub</code></a>
    150 detects the shape of the screen, so your app cannot access their views
    151 immediately. To access these views, set a listener in your activity to be notified when
    152 the shape-specific layout has been inflated:</p>
    153 
    154 <pre>
    155 &#64;Override
    156 protected void onCreate(Bundle savedInstanceState) {
    157     super.onCreate(savedInstanceState);
    158     setContentView(R.layout.activity_wear);
    159 
    160     WatchViewStub stub = (WatchViewStub) findViewById(R.id.watch_view_stub);
    161     stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() {
    162         &#64;Override public void onLayoutInflated(WatchViewStub stub) {
    163             // Now you can access your views
    164             TextView tv = (TextView) stub.findViewById(R.id.text);
    165             ...
    166         }
    167     });
    168 }
    169 </pre>
    170 
    171 
    172 <h2 id="same-layout">Use a Shape-Aware Layout</h2>
    173 
    174 <div style="float:right;margin-left:25px;width:260px">
    175 <img src="{@docRoot}wear/images/02_uilib.png" width="250" height="250" alt=""/>
    176 <p class="img-caption"><strong>Figure 2.</strong> Window insets on a round screen.</p>
    177 </div>
    178 
    179 <p>The
    180 <a href="{@docRoot}reference/android/support/wearable/view/BoxInsetLayout.html"><code>BoxInsetLayout</code></a>
    181 class included in the Wearable UI Library extends
    182 {@link android.widget.FrameLayout} and lets you define a single layout that works for both square
    183 and round screens. This class applies the required window insets depending on the screen shape
    184 and lets you easily align views on the center or near the edges of the screen.</p>
    185 
    186 <p>The gray square in figure 2 shows the area where
    187 <a href="{@docRoot}reference/android/support/wearable/view/BoxInsetLayout.html"><code>BoxInsetLayout</code></a>
    188 can automatically place its child views on round screens after applying the required window insets.
    189 To be displayed inside this area, children views specify the <code>layout_box</code> atribute with
    190 these values:
    191 </p>
    192 
    193 <ul>
    194 <li>A combination of <code>top</code>, <code>bottom</code>, <code>left</code>, and
    195     <code>right</code>. For example, <code>"left|top"</code> positions the child's left and top
    196     edges inside the gray square in figure 2.</li>
    197 <li>The <code>all</code> value positions all the child's content inside the gray square in
    198     figure 2.</li>
    199 </ul>
    200 
    201 <p>On square screens, the window insets are zero and the <code>layout_box</code> attribute is
    202 ignored.</p>
    203 
    204 <img src="{@docRoot}wear/images/03_uilib.png" width="500" height="253" alt=""/>
    205 <p class="img-caption"><strong>Figure 3.</strong> A layout definition that works on both
    206 square and round screens.</p>
    207 
    208 <p>The layout shown in figure 3 uses the
    209 <a href="{@docRoot}reference/android/support/wearable/view/BoxInsetLayout.html"><code>&lt;BoxInsetLayout&gt;</code></a>
    210 element and works on square and round screens:</p>
    211 
    212 <pre>
    213 &lt;<strong>android.support.wearable.view.BoxInsetLayout</strong>
    214     xmlns:android="http://schemas.android.com/apk/res/android"
    215     xmlns:app="http://schemas.android.com/apk/res-auto"
    216     <strong>android:background="@drawable/robot_background"</strong>
    217     android:layout_height="match_parent"
    218     android:layout_width="match_parent"
    219     <strong>android:padding="15dp"</strong>>
    220 
    221     &lt;FrameLayout
    222         android:layout_width="match_parent"
    223         android:layout_height="match_parent"
    224         <strong>android:padding="5dp"</strong>
    225         <strong>app:layout_box="all"</strong>>
    226 
    227         &lt;TextView
    228             android:gravity="center"
    229             android:layout_height="wrap_content"
    230             android:layout_width="match_parent"
    231             android:text="@string/sometext"
    232             android:textColor="@color/black" />
    233 
    234         &lt;ImageButton
    235             android:background="@null"
    236             android:layout_gravity="bottom|left"
    237             android:layout_height="50dp"
    238             android:layout_width="50dp"
    239             android:src="@drawable/ok" />
    240 
    241         &lt;ImageButton
    242             android:background="@null"
    243             android:layout_gravity="bottom|right"
    244             android:layout_height="50dp"
    245             android:layout_width="50dp"
    246             android:src="@drawable/cancel" />
    247     &lt;/FrameLayout>
    248 &lt;/android.support.wearable.view.BoxInsetLayout>
    249 </pre>
    250 
    251 <p>Notice the parts of the layout marked in bold:</p>
    252 
    253 <ul>
    254 <li>
    255   <p><code>android:padding="15dp"</code></p>
    256   <p>This line assigns padding to the
    257   <a href="{@docRoot}reference/android/support/wearable/view/BoxInsetLayout.html"><code>&lt;BoxInsetLayout&gt;</code></a>
    258   element. Because the window insets on round devices are larger than 15dp, this padding only
    259   applies to square screens.</p>
    260 </li>
    261 <li>
    262   <p><code>android:padding="5dp"</code></p>
    263   <p>This line assigns padding to the inner {@link android.widget.FrameLayout} element. This padding
    264   applies to both square and round screens. The total padding between the buttons and the window
    265   insets is 20 dp on square screens (15+5) and 5 dp on round screens.</p>
    266 </li>
    267 <li>
    268   <p><code>app:layout_box="all"</code></p>
    269   <p>This line ensures that the {@link android.widget.FrameLayout} element and its children are
    270   boxed inside the area defined by the window insets on round screens. This line has no effect on
    271   square screens.</p>
    272 </li>
    273 </ul>