• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1page.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
25with specific constraints. Do not port functionality and the UI from a handheld app and expect a
26good 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
30and round screens. Any content placed near the corners of the screen may be cropped on round
31Android Wear devices, so layouts designed for square screens do not work well on round devices.
32For 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
39square 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
68the shape of the device screen. You use the second approach when you want to use a similar layout
69on 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
75when 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
77the 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>
81dependencies {
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
89the layout techniques shown in the following sections.</p>
90
91<p><a href="/shareables/training/wearable-support-docs.zip">Download the full API
92reference 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
98different layout definitions for square and round screens. This class detects the screen shape
99at 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
130protected 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,
137you 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
139you create layouts for handheld apps, but taking into account the constraints of wearable devices.
140The 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
146immediately. To access these views, set a listener in your activity to be notified when
147the shape-specific layout has been inflated:</p>
148
149<pre>
150&#64;Override
151protected 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
176and round screens. This class applies the required window insets depending on the screen shape
177and 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
180place its child views on round screens after applying the required window insets. To be displayed
181inside 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
193ignored.</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
197square and round screens.</p>
198
199<p>The layout shown in figure 3 uses <code>BoxInsetLayout</code> and works on square and
200round 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>