blob: f1f18f3dfb9411f457744de79b59223ac1cebef9 [file] [log] [blame]
page.title=Defining Layouts
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>This lesson teaches you to</h2>
<ol>
<li><a href="#add-library">Add the Wearable UI Library</a></li>
<li><a href="#different-layouts">Specify Different Layouts for Square and Round Screens</a></li>
<li><a href="#same-layout">Use a Shape-Aware Layout</a></li>
</ol>
<h2>You should also read</h2>
<ul>
<li><a href="{@docRoot}design/wear/index.html">Android Wear Design Principles</a></li>
</ul>
<h2>Video</h2>
<ul>
<li><a href="https://www.youtube.com/watch?v=naf_WbtFAlY">Full Screen Apps for Android Wear</a></li>
</ul>
</div>
</div>
<p>Wearables use the same layout techniques as handheld Android devices, but need to be designed
with specific constraints. Do not port functionality and the UI from a handheld app and expect a
good experience. For more information on how to design great wearable apps, read the
<a href="{@docRoot}design/wear/index.html">Android Wear Design Guidelines</a>.</p>
<p>When you create layouts for Android Wear apps, you need to account for devices with square
and round screens. Any content placed near the corners of the screen may be cropped on round
Android Wear devices, so layouts designed for square screens do not work well on round devices.
For a demonstration of this type of problem, see the video
<a href="https://www.youtube.com/watch?v=naf_WbtFAlY">Full Screen Apps for Android Wear</a>.</p>
<p>For example, figure 1 shows how the following layout looks on square and round screens:</p>
<img src="{@docRoot}wear/images/01_uilib.png" alt="" width="500" height="261"/>
<p class="img-caption"><strong>Figure 1.</strong> Demonstration of how a layout designed for
square screens does not work well on round screens.</p>
<pre>
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
&lt;TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_square" /&gt;
&lt;/LinearLayout&gt;
</pre>
<p>The text does not display correctly on devices with round screens.</p>
<p>The Wearable UI Library provides two different approaches to solve this problem:</p>
<ul>
<li>Define different layouts for square and round devices. Your app detects the shape
of the device screen and inflates the correct layout at runtime.</li>
<li>Use a special layout included in the library for both square and round devices. This layout
applies different window insets depending on the shape of the device screen.</li>
</ul>
<p>You typically use the first approach when you want your app to look different depending on
the shape of the device screen. You use the second approach when you want to use a similar layout
on both screen shapes without having views cropped near the edges of round screens.</p>
<h2 id="add-library">Add the Wearable UI Library</h2>
<p>Android Studio includes the Wearable UI Library on your <code>wear</code> module by default
when you use the Project Wizard. To compile your project with this library, ensure that the
<em>Extras</em> &gt; <em>Google Repository</em> package is installed in
the Android SDK manager and that the following dependency is included in the
<code>build.gradle</code> file of your <code>wear</code> module:</p>
<pre>
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
<strong>compile 'com.google.android.support:wearable:+'</strong>
compile 'com.google.android.gms:play-services-wearable:+'
}
</pre>
<p>The <code>'com.google.android.support:wearable'</code> dependency is required to implement
the layout techniques shown in the following sections.</p>
<p>Browse the <a href="{@docRoot}reference/android/support/wearable/view/package-summary.html">
API reference documentation</a> for the Wearable UI Library classes.</p>
<h2 id="different-layouts">Specify Different Layouts for Square and Round Screens</h2>
<p>The
<a href="{@docRoot}reference/android/support/wearable/view/WatchViewStub.html"><code>WatchViewStub</code></a>
class included in the Wearable UI Library lets you specify different layout definitions for square
and round screens. This class detects the screen shape at runtime and inflates the corresponding
layout.</p>
<p>To use this class for handling different screen shapes in your app:</p>
<ol>
<li>Add
<a href="{@docRoot}reference/android/support/wearable/view/WatchViewStub.html"><code>WatchViewStub</code></a>
as the main element of your activity's layout.</li>
<li>Specify a layout definition file for square screens with the <code>rectLayout</code>
attribute.</li>
<li>Specify a layout definition file for round screens with the <code>roundLayout</code>
attribute.</li>
</ol>
<p>Define your activity's layout as follows:</p>
<pre>
&lt;android.support.wearable.view.WatchViewStub
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/watch_view_stub"
android:layout_width="match_parent"
android:layout_height="match_parent"
<strong>app:rectLayout="@layout/rect_activity_wear"</strong>
<strong>app:roundLayout="@layout/round_activity_wear"</strong>>
&lt;/android.support.wearable.view.WatchViewStub>
</pre>
<p>Inflate this layout in your activity:</p>
<pre>
&#64;Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_wear);
}
</pre>
<p>Then create different layout definition files for square and round screens. In this example,
you need to create the files <code>res/layout/rect_activity_wear.xml</code> and
<code>res/layout/round_activity_wear.xml</code>. You define these layouts in the same way that
you create layouts for handheld apps, but taking into account the constraints of wearable devices.
The system inflates the correct layout at runtime depending on the screen shape.</p>
<h3>Accessing layout views</h3>
<p>The layouts that you specify for square or round screens are not inflated until
<a href="{@docRoot}reference/android/support/wearable/view/WatchViewStub.html"><code>WatchViewStub</code></a>
detects the shape of the screen, so your app cannot access their views
immediately. To access these views, set a listener in your activity to be notified when
the shape-specific layout has been inflated:</p>
<pre>
&#64;Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_wear);
WatchViewStub stub = (WatchViewStub) findViewById(R.id.watch_view_stub);
stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() {
&#64;Override public void onLayoutInflated(WatchViewStub stub) {
// Now you can access your views
TextView tv = (TextView) stub.findViewById(R.id.text);
...
}
});
}
</pre>
<h2 id="same-layout">Use a Shape-Aware Layout</h2>
<div style="float:right;margin-left:25px;width:260px">
<img src="{@docRoot}wear/images/02_uilib.png" width="250" height="250" alt=""/>
<p class="img-caption"><strong>Figure 2.</strong> Window insets on a round screen.</p>
</div>
<p>The
<a href="{@docRoot}reference/android/support/wearable/view/BoxInsetLayout.html"><code>BoxInsetLayout</code></a>
class included in the Wearable UI Library extends
{@link android.widget.FrameLayout} and lets you define a single layout that works for both square
and round screens. This class applies the required window insets depending on the screen shape
and lets you easily align views on the center or near the edges of the screen.</p>
<p>The gray square in figure 2 shows the area where
<a href="{@docRoot}reference/android/support/wearable/view/BoxInsetLayout.html"><code>BoxInsetLayout</code></a>
can automatically place its child views on round screens after applying the required window insets.
To be displayed inside this area, children views specify the <code>layout_box</code> atribute with
these values:
</p>
<ul>
<li>A combination of <code>top</code>, <code>bottom</code>, <code>left</code>, and
<code>right</code>. For example, <code>"left|top"</code> positions the child's left and top
edges inside the gray square in figure 2.</li>
<li>The <code>all</code> value positions all the child's content inside the gray square in
figure 2.</li>
</ul>
<p>On square screens, the window insets are zero and the <code>layout_box</code> attribute is
ignored.</p>
<img src="{@docRoot}wear/images/03_uilib.png" width="500" height="253" alt=""/>
<p class="img-caption"><strong>Figure 3.</strong> A layout definition that works on both
square and round screens.</p>
<p>The layout shown in figure 3 uses the
<a href="{@docRoot}reference/android/support/wearable/view/BoxInsetLayout.html"><code>&lt;BoxInsetLayout&gt;</code></a>
element and works on square and round screens:</p>
<pre>
&lt;<strong>android.support.wearable.view.BoxInsetLayout</strong>
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
<strong>android:background="@drawable/robot_background"</strong>
android:layout_height="match_parent"
android:layout_width="match_parent"
<strong>android:padding="15dp"</strong>>
&lt;FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
<strong>android:padding="5dp"</strong>
<strong>app:layout_box="all"</strong>>
&lt;TextView
android:gravity="center"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:text="@string/sometext"
android:textColor="@color/black" />
&lt;ImageButton
android:background="@null"
android:layout_gravity="bottom|left"
android:layout_height="50dp"
android:layout_width="50dp"
android:src="@drawable/ok" />
&lt;ImageButton
android:background="@null"
android:layout_gravity="bottom|right"
android:layout_height="50dp"
android:layout_width="50dp"
android:src="@drawable/cancel" />
&lt;/FrameLayout>
&lt;/android.support.wearable.view.BoxInsetLayout>
</pre>
<p>Notice the parts of the layout marked in bold:</p>
<ul>
<li>
<p><code>android:padding="15dp"</code></p>
<p>This line assigns padding to the
<a href="{@docRoot}reference/android/support/wearable/view/BoxInsetLayout.html"><code>&lt;BoxInsetLayout&gt;</code></a>
element. Because the window insets on round devices are larger than 15dp, this padding only
applies to square screens.</p>
</li>
<li>
<p><code>android:padding="5dp"</code></p>
<p>This line assigns padding to the inner {@link android.widget.FrameLayout} element. This padding
applies to both square and round screens. The total padding between the buttons and the window
insets is 20 dp on square screens (15+5) and 5 dp on round screens.</p>
</li>
<li>
<p><code>app:layout_box="all"</code></p>
<p>This line ensures that the {@link android.widget.FrameLayout} element and its children are
boxed inside the area defined by the window insets on round screens. This line has no effect on
square screens.</p>
</li>
</ul>