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 <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 <TextView 49 android:id="@+id/text" 50 android:layout_width="wrap_content" 51 android:layout_height="wrap_content" 52 android:text="@string/hello_square" /> 53 </LinearLayout> 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> > <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 <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 </android.support.wearable.view.WatchViewStub> 124 </pre> 125 126 <p>Inflate this layout in your activity:</p> 127 128 <pre> 129 @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 @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 @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 <<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 <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 <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 <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 <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 </FrameLayout> 238 </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>