am 0e61e44d: am 2a02b881: Merge "docs: Training class for the Wearable UI Library" into klp-modular-docs
* commit '0e61e44ddf8c8abb774020cde90ec44d4ae43bc6': docs: Training class for the Wearable UI Library
@@ -782,6 +782,34 @@ include the action bar on devices running Android 2.1 or higher."
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="nav-section">
|
||||
<div class="nav-section-header">
|
||||
<a href="<?cs var:toroot ?>training/wearables/ui/index.html"
|
||||
description="How to create custom user interfaces for wearable apps."
|
||||
>Creating Custom UIs</a>
|
||||
</div>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="<?cs var:toroot ?>training/wearables/ui/layouts.html">Defining Layouts</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="<?cs var:toroot ?>training/wearables/ui/cards.html">Creating Cards</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="<?cs var:toroot ?>training/wearables/ui/lists.html">Creating Lists</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="<?cs var:toroot ?>training/wearables/ui/2d-picker.html">Creating a 2D Picker</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="<?cs var:toroot ?>training/wearables/ui/confirm.html">Showing Confirmations</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="<?cs var:toroot ?>training/wearables/ui/exit.html">Exiting Full-Screen Activities</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="nav-section">
|
||||
<div class="nav-section-header">
|
||||
<a href="<?cs var:toroot ?>training/wearables/data-layer/index.html"
|
||||
|
||||
181
docs/html/training/wearables/ui/2d-picker.jd
Normal file
@@ -0,0 +1,181 @@
|
||||
page.title=Creating a 2D Picker
|
||||
|
||||
@jd:body
|
||||
|
||||
<div id="tb-wrapper">
|
||||
<div id="tb">
|
||||
<h2>This lesson teaches you to</h2>
|
||||
<ol>
|
||||
<li><a href="#add-page-grid">Add a Page Grid</a></li>
|
||||
<li><a href="#implement-adapter">Implement a Page Adapter</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>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>The <a href="{@docRoot}design/wear/structure.html#2DPicker">2D Picker</a> pattern in Android
|
||||
Wear allows users to navigate and choose from a set of items shown as pages. The Wearable UI
|
||||
Library lets you easily implement this pattern using a page grid, which is a layout manager
|
||||
that allows users to scroll vertically and horizontally through pages of data.</p>
|
||||
|
||||
<p>To implement this pattern, you add a <code>GridViewPager</code> element to the layout
|
||||
of your activity and implement an adapter that provides a set of pages by extending
|
||||
the <code>FragmentGridPagerAdapter</code> class.</p>
|
||||
|
||||
<p class="note"><strong>Note:</strong> The <em>GridViewPager</em> sample in the Android SDK
|
||||
demonstrates how to use the <code>GridViewPager</code> layout in your apps. This sample is
|
||||
located in the <code>android-sdk/samples/android-20/wearable/GridViewPager</code> directory.</p>
|
||||
|
||||
|
||||
<h2 id="add-page-grid">Add a Page Grid</h2>
|
||||
|
||||
<p>Add a <code>GridViewPager</code> element to your layout definition as follows:</p>
|
||||
|
||||
<pre>
|
||||
<android.support.wearable.view.GridViewPager
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/pager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
</pre>
|
||||
|
||||
<p>You can use any of the techniques described in
|
||||
<a href="{@docRoot}training/wearables/ui/layouts.html">Defining Layouts</a> to ensure that
|
||||
your 2D picker works on both round and square devices.</p>
|
||||
|
||||
|
||||
<h2 id="implement-adapter">Implement a Page Adapter</h2>
|
||||
|
||||
<p>A page adapter provides a set of pages to populate a <code>GridViewPager</code> component. To
|
||||
implement this adapter, you extend the <code>FragmentGridPageAdapter</code> class from the
|
||||
Wearable UI Library</p>
|
||||
|
||||
<p>For example, the <em>GridViewPager</em> sample in the Android SDK contains
|
||||
the following adapter implementation that provides a set of static cards with custom background
|
||||
images:</p>
|
||||
|
||||
<pre>
|
||||
public class SampleGridPagerAdapter extends FragmentGridPagerAdapter {
|
||||
|
||||
private final Context mContext;
|
||||
|
||||
public SampleGridPagerAdapter(Context ctx, FragmentManager fm) {
|
||||
super(fm);
|
||||
mContext = ctx;
|
||||
}
|
||||
|
||||
static final int[] BG_IMAGES = new int[] {
|
||||
R.drawable.debug_background_1, ...
|
||||
R.drawable.debug_background_5
|
||||
};
|
||||
|
||||
// A simple container for static data in each page
|
||||
private static class Page {
|
||||
// static resources
|
||||
int titleRes;
|
||||
int textRes;
|
||||
int iconRes;
|
||||
...
|
||||
}
|
||||
|
||||
// Create a static set of pages in a 2D array
|
||||
private final Page[][] PAGES = { ... };
|
||||
|
||||
// Override methods in FragmentGridPagerAdapter
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>The picker calls <code>getFragment</code> and <code>getBackground</code> to retrieve the content
|
||||
to display at each position of the grid:</p>
|
||||
|
||||
<pre>
|
||||
// Obtain the UI fragment at the specified position
|
||||
@Override
|
||||
public Fragment getFragment(int row, int col) {
|
||||
Page page = PAGES[row][col];
|
||||
String title =
|
||||
page.titleRes != 0 ? mContext.getString(page.titleRes) : null;
|
||||
String text =
|
||||
page.textRes != 0 ? mContext.getString(page.textRes) : null;
|
||||
CardFragment fragment = CardFragment.create(title, text, page.iconRes);
|
||||
|
||||
// Advanced settings (card gravity, card expansion/scrolling)
|
||||
fragment.setCardGravity(page.cardGravity);
|
||||
fragment.setExpansionEnabled(page.expansionEnabled);
|
||||
fragment.setExpansionDirection(page.expansionDirection);
|
||||
fragment.setExpansionFactor(page.expansionFactor);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
// Obtain the background image for the page at the specified position
|
||||
@Override
|
||||
public ImageReference getBackground(int row, int column) {
|
||||
return ImageReference.forDrawable(BG_IMAGES[row % BG_IMAGES.length]);
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>The <code>getRowCount</code> method tells the picker how many rows of content are
|
||||
available, and the <code>getColumnCount</code> method tells the picker how many columns
|
||||
of content are available for each of the rows.</p>
|
||||
|
||||
<pre>
|
||||
// Obtain the number of pages (vertical)
|
||||
@Override
|
||||
public int getRowCount() {
|
||||
return PAGES.length;
|
||||
}
|
||||
|
||||
// Obtain the number of pages (horizontal)
|
||||
@Override
|
||||
public int getColumnCount(int rowNum) {
|
||||
return PAGES[rowNum].length;
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>The adapter implementation details depend on your particular set of pages. Each page provided
|
||||
by the adapter is of type <code>Fragment</code>. In this example, each page is a
|
||||
<code>CardFragment</code> instance that uses one of the default card layouts. However, you can
|
||||
combine different types of pages in the same 2D picker, such as cards, action icons, and custom
|
||||
layouts depending on your use cases.</p>
|
||||
|
||||
<div style="float:right;margin-left:25px;width:250px">
|
||||
<img src="{@docRoot}wear/images/07_uilib.png" width="250" height="250" alt=""/>
|
||||
<p class="img-caption" style="text-align:center"><strong>Figure 1:</strong>
|
||||
The <em>GridViewPager</em> sample.</p>
|
||||
</div>
|
||||
|
||||
<p>Not all rows need to have the same number of pages. Notice that in this example the number of
|
||||
colums is different for each row. You can also use a <code>GridViewPager</code> component to
|
||||
implement a 1D picker with only one row or only one column.</p>
|
||||
|
||||
<p><code>GridViewPager</code> provides support for scrolling in cards whose content does not fit
|
||||
the device screen. This example configures each card to expand as required, so users can scroll
|
||||
through the card's content. When users reach the end of a scrollable card, a swipe in the same
|
||||
direction shows the next page on the grid, if one is available.</p>
|
||||
|
||||
<p>You can specify a custom background for each page with the <code>getBackground()</code> method.
|
||||
When users swipe to navigate across pages, <code>GridViewPager</code> applies parallax
|
||||
and crossfade effects between different backgrounds automatically.</p>
|
||||
|
||||
<h3>Assign an adapter instance to the page grid</h3>
|
||||
|
||||
<p>In your activity, assign an instance of your adapter implementation to the
|
||||
<code>GridViewPager</code> component:</p>
|
||||
|
||||
<pre>
|
||||
public class MainActivity extends Activity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
...
|
||||
final GridViewPager pager = (GridViewPager) findViewById(R.id.pager);
|
||||
pager.setAdapter(new SampleGridPagerAdapter(this, getFragmentManager()));
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
169
docs/html/training/wearables/ui/cards.jd
Normal file
@@ -0,0 +1,169 @@
|
||||
page.title=Creating Cards
|
||||
|
||||
@jd:body
|
||||
|
||||
<div id="tb-wrapper">
|
||||
<div id="tb">
|
||||
<h2>This lesson teaches you to</h2>
|
||||
<ol>
|
||||
<li><a href="#card-fragment">Create a Card Fragment</a></li>
|
||||
<li><a href="#card-layout">Add a Card to Your 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>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<p>Cards present information to users with a consistent look and feel across different apps.
|
||||
This lesson shows you how to create cards in your Android Wear apps.</p>
|
||||
|
||||
<p>The Wearable UI Library provides implementations of cards specifically designed for wearable
|
||||
devices. This library contains the <code>CardFrame</code> class, which wraps views inside
|
||||
a card-styled frame with a white background, rounded corners, and a light-drop shadow.
|
||||
<code>CardFrame</code> can only contain one direct child, usually a layout manager, to which
|
||||
you can add other views to customize the content inside the card.</p>
|
||||
|
||||
<p>You can add cards to your app in two ways:</p>
|
||||
|
||||
<ul>
|
||||
<li>Use or extend the <code>CardFragment</code> class.</li>
|
||||
<li>Add a card inside a <code>CardScrollView</code> in your layout.</li>
|
||||
</ul>
|
||||
|
||||
<p class="note"><strong>Note:</strong> This lesson shows you how to add cards to Android Wear
|
||||
activities. Android notifications on wearable devices are also displayed as cards. For more
|
||||
information, see <a href="{@docRoot}training/wearables/notifications/index.html">Adding Wearable
|
||||
Features to Notifications</a>.</p>
|
||||
|
||||
|
||||
<h2 id="card-fragment">Create a Card Fragment</h2>
|
||||
|
||||
<p>The <code>CardFragment</code> class provides a default card layout with a title, a
|
||||
description, and an icon. Use this approach to add cards to your app if the default card layout
|
||||
shown in figure 1 meets your needs.</p>
|
||||
|
||||
<img src="{@docRoot}wear/images/05_uilib.png" width="500" height="245" alt=""/>
|
||||
<p class="img-caption"><strong>Figure 1.</strong> The default <code>CardFragment</code> layout.</p>
|
||||
|
||||
<p>To add a <code>CardFragment</code> to your app:</p>
|
||||
|
||||
<ol>
|
||||
<li>In your layout, assign an ID to the element that contains the card</li>
|
||||
<li>Create a <code>CardFragment</code> instance in your activity</li>
|
||||
<li>Use the fragment manager to add the <code>CardFragment</code> instance to its container</li>
|
||||
</ol>
|
||||
|
||||
<p>The following sample code shows the code for the screen display shown in Figure 1:</p>
|
||||
|
||||
<pre>
|
||||
<android.support.wearable.view.BoxInsetLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:background="@drawable/robot_background"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="match_parent">
|
||||
|
||||
<FrameLayout
|
||||
<strong>android:id="@+id/frame_layout"</strong>
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_box="bottom">
|
||||
|
||||
</FrameLayout>
|
||||
</android.support.wearable.view.BoxInsetLayout>
|
||||
</pre>
|
||||
|
||||
<p>The following code adds the <code>CardFragment</code> instance to the activity in Figure 1:</p>
|
||||
|
||||
<pre>
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_wear_activity2);
|
||||
|
||||
FragmentManager fragmentManager = getFragmentManager();
|
||||
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
|
||||
CardFragment cardFragment = CardFragment.create(getString(R.string.cftitle),
|
||||
getString(R.string.cfdesc),
|
||||
R.drawable.p);
|
||||
fragmentTransaction.add(R.id.frame_layout, cardFragment);
|
||||
fragmentTransaction.commit();
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>To create a card with a custom layout using <code>CardFragment</code>, extend this class
|
||||
and override its <code>onCreateContentView</code> method.</p>
|
||||
|
||||
|
||||
<h2 id="card-layout">Add a CardFrame to Your Layout</h2>
|
||||
|
||||
<p>You can also add a card directly to your layout definition, as shown in figure 2. Use this
|
||||
approach when you want to define a custom layout for the card inside a layout definition file.</p>
|
||||
|
||||
<img src="{@docRoot}wear/images/04_uilib.png" width="500" height="248" alt=""/>
|
||||
<p class="img-caption"><strong>Figure 2.</strong> Adding a <code>CardFrame</code> to your
|
||||
layout.</p>
|
||||
|
||||
<p>The following layout code sample demonstrates a vertical linear layout with two elements. You
|
||||
can create more complex layouts to fit the needs of your app.</p>
|
||||
|
||||
<pre>
|
||||
<android.support.wearable.view.BoxInsetLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:background="@drawable/robot_background"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="match_parent">
|
||||
|
||||
<<strong>android.support.wearable.view.CardScrollView</strong>
|
||||
android:id="@+id/card_scroll_view"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="match_parent"
|
||||
app:layout_box="bottom">
|
||||
|
||||
<<strong>android.support.wearable.view.CardFrame</strong>
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="fill_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="5dp">
|
||||
<TextView
|
||||
android:fontFamily="sans-serif-light"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:text="@string/custom_card"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="20sp"/>
|
||||
<TextView
|
||||
android:fontFamily="sans-serif-light"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:text="@string/description"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="14sp"/>
|
||||
</LinearLayout>
|
||||
</android.support.wearable.view.CardFrame>
|
||||
</android.support.wearable.view.CardScrollView>
|
||||
</android.support.wearable.view.BoxInsetLayout>
|
||||
</pre>
|
||||
|
||||
<p>The <code>CardScrollView</code> element in the example layout above lets you assign gravity to
|
||||
the card when its content is smaller than the container. This example aligns the card to the
|
||||
bottom of the screen:</p>
|
||||
|
||||
<pre>
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_wear_activity2);
|
||||
|
||||
CardScrollView cardScrollView =
|
||||
(CardScrollView) findViewById(R.id.card_scroll_view);
|
||||
cardScrollView.setCardGravity(Gravity.BOTTOM);
|
||||
}
|
||||
</pre>
|
||||
166
docs/html/training/wearables/ui/confirm.jd
Normal file
@@ -0,0 +1,166 @@
|
||||
page.title=Showing Confirmations
|
||||
|
||||
@jd:body
|
||||
|
||||
<div id="tb-wrapper">
|
||||
<div id="tb">
|
||||
<h2>This lesson teaches you to</h2>
|
||||
<ol>
|
||||
<li><a href="#confirmation-timers">Use Automatic Confirmation Timers</a></li>
|
||||
<li><a href="#show-confirmation">Show Confirmation Animations</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>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<p><a href="{@docRoot}design/wear/patterns.html#Countdown">Confirmations</a> in Android Wear apps
|
||||
use the whole screen or a larger portion of it than those in handheld apps. This ensures that
|
||||
users can see these confirmations by just glancing at the screen and that they have large enough
|
||||
touch targets to cancel an action.</p>
|
||||
|
||||
<p>The Wearable UI Library helps you show confirmation animations and timers in your
|
||||
Android Wear apps:</p>
|
||||
|
||||
<dl>
|
||||
<dt><em>Confirmation timers</em></dt>
|
||||
<dd>Automatic confirmation timers show users an animated timer that lets them cancel an action
|
||||
they just performed.</dd>
|
||||
<dt><em>Confirmation animations</em></dt>
|
||||
<dd>Confirmation animations give users visual feedback when they complete an action.</dd>
|
||||
</dl>
|
||||
|
||||
<p>The following sections show you how to implement these patterns.</p>
|
||||
|
||||
|
||||
<h2 id="confirmation-timers">Use Automatic Confirmation Timers</h2>
|
||||
|
||||
<div style="float:right;margin-left:25px;width:230px;margin-top:10px">
|
||||
<img src="{@docRoot}wear/images/09_uilib.png" width="230" height="230" alt=""/>
|
||||
<p class="img-caption" style="text-align:center"><strong>Figure 1:</strong>
|
||||
A confirmation timer.</p>
|
||||
</div>
|
||||
|
||||
<p>Automatic confirmation timers let users cancel an action they just performed. When the user
|
||||
performs the action, your app shows a button to cancel the action with a timer animation and
|
||||
starts the timer. The user has the option to cancel the action until the timer finishes. Your app
|
||||
gets notified if the user cancels the action and when the timer expires.</p>
|
||||
|
||||
<p>To show a confirmation timer when users complete an action in your app:</p>
|
||||
|
||||
<ol>
|
||||
<li>Add a <code>DelayedConfirmationView</code> element to your layout.</li>
|
||||
<li>Implement the <code>DelayedConfirmationListener</code> interface in your activity.</li>
|
||||
<li>Set the duration of the timer and start it when the user completes an action.</li>
|
||||
</ol>
|
||||
|
||||
<p>Add the <code>DelayedConfirmationView</code> element to your layout as follows:</p>
|
||||
|
||||
<pre>
|
||||
<android.support.wearable.view.DelayedConfirmationView
|
||||
android:id="@+id/delayed_confirm"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:src="@drawable/cancel_circle"
|
||||
app:circle_border_color="@color/lightblue"
|
||||
app:circle_border_width="4dp"
|
||||
app:circle_radius="16dp">
|
||||
</android.support.wearable.view.DelayedConfirmationView>
|
||||
</pre>
|
||||
|
||||
<p>You can assign a drawable resource to display inside the circle with the
|
||||
<code>android:src</code> attribute and configure the parameters of the circle directly on the
|
||||
layout definition.</p>
|
||||
|
||||
<p>To be notified when the timer finishes or when users tap on it, implement the corresponding
|
||||
listener methods in your activity:</p>
|
||||
|
||||
<pre>
|
||||
public class WearActivity extends Activity implements
|
||||
DelayedConfirmationView.DelayedConfirmationListener {
|
||||
|
||||
private DelayedConfirmationView mDelayedView;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_wear_activity);
|
||||
|
||||
mDelayedView =
|
||||
(DelayedConfirmationView) findViewById(R.id.delayed_confirm);
|
||||
mDelayedView.setListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTimerFinished(View view) {
|
||||
// User didn't cancel, perform the action
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTimerSelected(View view) {
|
||||
// User canceled, abort the action
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>To start the timer, add the following code to the point in your activity where users select
|
||||
an action:</p>
|
||||
|
||||
<pre>
|
||||
// Two seconds to cancel the action
|
||||
mDelayedView.setTotalTimeMs(2000);
|
||||
// Start the timer
|
||||
mDelayedView.start();
|
||||
</pre>
|
||||
|
||||
|
||||
<h2 id="show-confirmation">Show Confirmation Animations</h2>
|
||||
|
||||
<div style="float:right;margin-left:25px;width:200px">
|
||||
<img src="{@docRoot}wear/images/08_uilib.png" width="200" height="200" alt=""/>
|
||||
<p class="img-caption" style="text-align:center"><strong>Figure 2:</strong>
|
||||
A confirmation animation.</p>
|
||||
</div>
|
||||
|
||||
<p>To show a confirmation animation when users complete an action in your app, create an intent
|
||||
that starts <code>ConfirmationActivity</code> from one of your activities. You can specify
|
||||
one of the these animations with the <code>EXTRA_ANIMATION_TYPE</code> intent extra:</p>
|
||||
|
||||
<ul>
|
||||
<li><code>SUCCESS_ANIMATION</code></li>
|
||||
<li><code>FAILURE_ANIMATION</code></li>
|
||||
<li><code>OPEN_ON_PHONE_ANIMATION</code></li>
|
||||
</ul>
|
||||
|
||||
<p>You can also add a message that appears under the confirmation icon.</p>
|
||||
|
||||
<p>To use the <code>ConfirmationActivity</code> in your app, first declare this activity in your
|
||||
manifest file:</p>
|
||||
|
||||
<pre>
|
||||
<manifest>
|
||||
<application>
|
||||
...
|
||||
<activity
|
||||
android:name="android.support.wearable.activity.ConfirmationActivity">
|
||||
</activity>
|
||||
</application>
|
||||
</manifest>
|
||||
</pre>
|
||||
|
||||
<p>Then determine the result of the user action and start the activity with an intent:</p>
|
||||
|
||||
<pre>
|
||||
Intent intent = new Intent(this, ConfirmationActivity.class);
|
||||
intent.putExtra(ConfirmationActivity.EXTRA_ANIMATION_TYPE,
|
||||
ConfirmationActivity.SUCCESS_ANIMATION);
|
||||
intent.putExtra(ConfirmationActivity.EXTRA_MESSAGE,
|
||||
getString(R.string.msg_sent));
|
||||
startActivity(intent);
|
||||
</pre>
|
||||
|
||||
<p>After showing the confirmation animation, <code>ConfirmationActivity</code> finishes and your
|
||||
activity resumes.</p>
|
||||
110
docs/html/training/wearables/ui/exit.jd
Normal file
@@ -0,0 +1,110 @@
|
||||
page.title=Exiting Full-Screen Activities
|
||||
|
||||
@jd:body
|
||||
|
||||
<div id="tb-wrapper">
|
||||
<div id="tb">
|
||||
<h2>This lesson teaches you to</h2>
|
||||
<ol>
|
||||
<li><a href="#disable-swipe">Disable the Swipe-To-Dismiss Gesture</a></li>
|
||||
<li><a href="#long-press">Implement the Long Press to Dismiss Pattern</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>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<p>By default, users exit Android Wear activities by swiping from left to right. If the app
|
||||
contains horizontally scrollable content, users first have to navigate to the edge of the
|
||||
content and then swipe again from left to right to exit the app.</p>
|
||||
|
||||
<p>For more immersive experiences, like an app that can scroll a map in any direction, you can
|
||||
disable the swipe to exit gesture in your app. However, if you disable it, you must implement
|
||||
the long-press-to-dismiss UI pattern to let users exit your app using the
|
||||
<code>DismissOverlayView</code> class from the Wearable UI Library.
|
||||
You must also inform your users the first time they run your app that they can exit using
|
||||
a long press.</p>
|
||||
|
||||
<p>For design guidelines on exiting Android Wear activities, see
|
||||
<a href="{@docRoot}design/wear/structure.html#Custom">Breaking out of the card</a>.</p>
|
||||
|
||||
|
||||
<h2 id="disable-swipe">Disable the Swipe-To-Dismiss Gesture</h2>
|
||||
|
||||
<p>If the user interaction model of your app interferes with the swipe-to-dismiss gesture,
|
||||
you can disable it for your app. To disable the swipe-to-dismiss gesture in your app, extend
|
||||
the default theme and set the <code>android:windowSwipeToDismiss</code> attribute to
|
||||
<code>false</code>:</p>
|
||||
|
||||
<pre>
|
||||
<style name="AppTheme" parent="Theme.DeviceDefault">
|
||||
<item name="android:windowSwipeToDismiss">false</item>
|
||||
</style>
|
||||
</pre>
|
||||
|
||||
<p>If you disable this gesture, you must implement the long-press-to-dismiss UI pattern to let users
|
||||
exit your app, as described in the next section.</p>
|
||||
|
||||
|
||||
<h2 id="long-press">Implement the Long Press to Dismiss Pattern</h2>
|
||||
|
||||
<p>To use the <code>DissmissOverlayView</code> class in your activity, add this element to
|
||||
your layout definition such that it covers the whole screen and is placed above all other views.
|
||||
For example:</p>
|
||||
|
||||
<pre>
|
||||
<FrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="match_parent">
|
||||
|
||||
<!-- other views go here -->
|
||||
|
||||
<android.support.wearable.view.DismissOverlayView
|
||||
android:id="@+id/dismiss_overlay"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="match_parent"/>
|
||||
<FrameLayout>
|
||||
</pre>
|
||||
|
||||
<p>In your activity, obtain the <code>DismissOverlayView</code> element and set some introductory
|
||||
text. This text is shown to users the first time they run your app to inform them that they
|
||||
can exit the app using a long press gesture. Then use a <code>GestureDetector</code> to detect
|
||||
a long press:</p>
|
||||
|
||||
<pre>
|
||||
public class WearActivity extends Activity {
|
||||
|
||||
private DismissOverlayView mDismissOverlay;
|
||||
private GestureDetector mDetector;
|
||||
|
||||
public void onCreate(Bundle savedState) {
|
||||
super.onCreate(savedState);
|
||||
setContentView(R.layout.wear_activity);
|
||||
|
||||
// Obtain the DismissOverlayView element
|
||||
mDismissOverlay = (DismissOverlayView) findViewById(R.id.dismiss_overlay);
|
||||
mDismissOverlay.setIntroText(R.string.long_press_intro);
|
||||
mDismissOverlay.showIntroIfNecessary();
|
||||
|
||||
// Configure a gesture detector
|
||||
mDetector = new GestureDetector(this, new SimpleOnGestureListener() {
|
||||
public void onLongPress(MotionEvent ev) {
|
||||
mDismissOverlay.show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Capture long presses
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent ev) {
|
||||
return mDetector.onTouchEvent(ev) || super.onTouchEvent(ev);
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>When the system detects a long press gesture, <code>DismissOverlayView</code> shows an
|
||||
<strong>Exit</strong> button, which terminates your activity if the user presses it.</p>
|
||||
57
docs/html/training/wearables/ui/index.jd
Normal file
@@ -0,0 +1,57 @@
|
||||
page.title=Creating Custom UIs for Wear Devices
|
||||
|
||||
@jd:body
|
||||
|
||||
<div id="tb-wrapper">
|
||||
<div id="tb">
|
||||
<h2>Dependencies and Prerequisites</h2>
|
||||
<ul>
|
||||
<li>Android Studio 0.8 or later and Gradle 0.12 or later</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>User interfaces for wearable apps differ significantly from those built for handheld devices.
|
||||
Apps for wearables should follow the Android Wear <a href="{@docRoot}design/wear/index.html">design
|
||||
principles</a> and implement the recommended <a href="{@docRoot}design/wear/patterns.html">UI
|
||||
patterns</a>, which ensure a consistent user experience across apps that is optimized for
|
||||
wearables.</a>
|
||||
|
||||
<p>This class teaches you how to create custom UIs for your
|
||||
<a href="{@docRoot}training/wearables/apps/creating.html">wearable apps</a> and
|
||||
<a href="{@docRoot}training/wearables/apps/layouts.html#CustomNotifications">custom
|
||||
notifications</a> that look good on any Android Wear device by implementing these
|
||||
UI patterns:</p>
|
||||
|
||||
<ul>
|
||||
<li>Cards</li>
|
||||
<li>Countdowns and confirmations</li>
|
||||
<li>Long press to dismiss</li>
|
||||
<li>2D Pickers</li>
|
||||
<li>Selection lists</li>
|
||||
</ul>
|
||||
|
||||
<p>The Wearable UI Library, which is part of the Google Repository in the Android SDK,
|
||||
provides classes that help you implement these patterns and create layouts that work on
|
||||
both round and square Android Wear devices.</p>
|
||||
|
||||
<p class="note"><b>Note:</b> We recommend using Android Studio for Android Wear development
|
||||
as it provides project setup, library inclusion, and packaging conveniences that aren't available
|
||||
in ADT. This training assumes you are using Android Studio.</p>
|
||||
|
||||
<h2>Lessons</h2>
|
||||
|
||||
<dl>
|
||||
<dt><a href="{@docRoot}training/wearables/ui/layouts.html">Defining Layouts</a></dt>
|
||||
<dd>Learn how to create layouts that look good on round and square Android Wear devices.</dd>
|
||||
<dt><a href="{@docRoot}training/wearables/ui/cards.html">Creating Cards</a></dt>
|
||||
<dd>Learn how to create cards with custom layouts.</dd>
|
||||
<dt><a href="{@docRoot}training/wearables/ui/lists.html">Creating Lists</a></dt>
|
||||
<dd>Learn how to create lists that are optimized for wearable devices.</dd>
|
||||
<dt><a href="{@docRoot}training/wearables/ui/2d-picker.html">Creating a 2D Picker</a></dt>
|
||||
<dd>Learn how to implement the 2D Picker UI pattern to navigate through pages of data.</dd>
|
||||
<dt><a href="{@docRoot}training/wearables/ui/confirm.html">Showing Confirmations</a></dt>
|
||||
<dd>Learn how to display confirmation animations when users complete actions.</dd>
|
||||
<dt><a href="{@docRoot}training/wearables/ui/exit.html">Exiting Full-Screen Activities</a></dt>
|
||||
<dd>Learn how to implement the long-press-to-dismiss UI pattern to exit full-screen activities.</dd>
|
||||
</dl>
|
||||
261
docs/html/training/wearables/ui/layouts.jd
Normal file
@@ -0,0 +1,261 @@
|
||||
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>
|
||||
<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">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/hello_square" />
|
||||
</LinearLayout>
|
||||
</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> > <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><a href="/shareables/training/wearable-support-docs.zip">Download the full 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 <code>WatchViewStub</code> 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 <code>WatchViewStub</code> 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>
|
||||
<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>>
|
||||
</android.support.wearable.view.WatchViewStub>
|
||||
</pre>
|
||||
|
||||
<p>Inflate this layout in your activity:</p>
|
||||
|
||||
<pre>
|
||||
@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
|
||||
<code>WatchViewStub</code> 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>
|
||||
@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() {
|
||||
@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:250px">
|
||||
<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 <code>BoxInsetLayout</code> 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 <code>BoxInsetLayout</code> 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 <code>BoxInsetLayout</code> and works on square and
|
||||
round screens:</p>
|
||||
|
||||
<pre>
|
||||
<<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>>
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
<strong>android:padding="5dp"</strong>
|
||||
<strong>app:layout_box="all"</strong>>
|
||||
|
||||
<TextView
|
||||
android:gravity="center"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:text="@string/sometext"
|
||||
android:textColor="@color/black" />
|
||||
|
||||
<ImageButton
|
||||
android:background="@null"
|
||||
android:layout_gravity="bottom|left"
|
||||
android:layout_height="50dp"
|
||||
android:layout_width="50dp"
|
||||
android:src="@drawable/ok" />
|
||||
|
||||
<ImageButton
|
||||
android:background="@null"
|
||||
android:layout_gravity="bottom|right"
|
||||
android:layout_height="50dp"
|
||||
android:layout_width="50dp"
|
||||
android:src="@drawable/cancel" />
|
||||
</FrameLayout>
|
||||
</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 <code>BoxInsetLayout</code> 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 <code>FrameLayout</code> 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 <code>FrameLayout</code> 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>
|
||||
304
docs/html/training/wearables/ui/lists.jd
Normal file
@@ -0,0 +1,304 @@
|
||||
page.title=Creating Lists
|
||||
|
||||
@jd:body
|
||||
|
||||
<div id="tb-wrapper">
|
||||
<div id="tb">
|
||||
<h2>This lesson teaches you to</h2>
|
||||
<ol>
|
||||
<li><a href="#add-list">Add a List View</a></li>
|
||||
<li><a href="#layout-impl">Create a Layout Implementation for List Items</a></li>
|
||||
<li><a href="#layout-def">Create a Layout Definition for Items</a></li>
|
||||
<li><a href="#adapter">Create an Adapter to Populate the List</a></li>
|
||||
<li><a href="#adapter-listener">Associate the Adapter and Set a Click Listener</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>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<p>Lists let users select an item from a set of choices easily on wearable devices. This lesson
|
||||
shows you how to create lists in your Android Wear apps.</p>
|
||||
|
||||
<p>The Wearable UI Library includes the <code>WearableListView</code> class, which is a list
|
||||
implementation optimized for wearable devices..</p>
|
||||
|
||||
<p class="note"><strong>Note:</strong> The <em>Notifications</em> sample in the Android SDK
|
||||
demonstrates how to use <code>WearableListView</code> in your apps. This sample is located in
|
||||
the <code>android-sdk/samples/android-20/wearable/Notifications</code> directory.</p>
|
||||
|
||||
<p>To create a list in your Android Wear apps:</p>
|
||||
|
||||
<ol>
|
||||
<li>Add a <code>WearableListView</code> element to your activity's layout definition.</li>
|
||||
<li>Create a custom layout implementation for your list items.</li>
|
||||
<li>Use this implementation to create a layout definition file for your list items.</li>
|
||||
<div style="float:right;margin-left:25px;width:215px;margin-top:-20px">
|
||||
<img src="{@docRoot}wear/images/06_uilib.png" width="200" height="200" alt=""/>
|
||||
<p class="img-caption" style="text-align:center"><strong>Figure 3:</strong>
|
||||
A list view on Android Wear.</p>
|
||||
</div>
|
||||
<li>Create an adapter to populate the list.</li>
|
||||
<li>Assign the adapter to the <code>WearableListView</code> element.</li>
|
||||
</ol>
|
||||
|
||||
<p>These steps are described in detail in the following sections.</p>
|
||||
|
||||
|
||||
<h2 id="add-list">Add a List View</h2>
|
||||
|
||||
<p>The following layout adds a list view to an activity using a <code>BoxInsetLayout</code>, so
|
||||
the list is displayed properly on both round and square devices:</p>
|
||||
|
||||
<pre>
|
||||
<android.support.wearable.view.BoxInsetLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:background="@drawable/robot_background"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="match_parent">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/frame_layout"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="match_parent"
|
||||
app:layout_box="left|bottom|right">
|
||||
|
||||
<<strong>android.support.wearable.view.WearableListView</strong>
|
||||
android:id="@+id/wearable_list"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="match_parent">
|
||||
</android.support.wearable.view.WearableListView>
|
||||
</FrameLayout>
|
||||
</android.support.wearable.view.BoxInsetLayout>
|
||||
</pre>
|
||||
|
||||
|
||||
<h2 id="layout-impl">Create a Layout Implementation for List Items</h2>
|
||||
|
||||
<p>In many cases, each list item consists of an icon and a description. The
|
||||
<em>Notifications</em> sample from the Android SDK implements a custom layout that extends
|
||||
{@link android.widget.LinearLayout} to incorporate these two elements inside each list item.
|
||||
This layout also implements the methods in the <code>WearableListView.Item</code> interface
|
||||
to animate the item's icon and fade the text in response to events from
|
||||
<code>WearableListView</code> as the user scrolls through the list.</p>
|
||||
|
||||
<pre>
|
||||
public class WearableListItemLayout extends LinearLayout
|
||||
implements WearableListView.Item {
|
||||
|
||||
private final float mFadedTextAlpha;
|
||||
private final int mFadedCircleColor;
|
||||
private final int mChosenCircleColor;
|
||||
private ImageView mCircle;
|
||||
private float mScale;
|
||||
private TextView mName;
|
||||
|
||||
public WearableListItemLayout(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public WearableListItemLayout(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public WearableListItemLayout(Context context, AttributeSet attrs,
|
||||
int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
mFadedTextAlpha = getResources()
|
||||
.getInteger(R.integer.action_text_faded_alpha) / 100f;
|
||||
mFadedCircleColor = getResources().getColor(R.color.grey);
|
||||
mChosenCircleColor = getResources().getColor(R.color.blue);
|
||||
}
|
||||
|
||||
// Get references to the icon and text in the item layout definition
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
// These are defined in the layout file for list items
|
||||
// (see next section)
|
||||
mCircle = (ImageView) findViewById(R.id.circle);
|
||||
mName = (TextView) findViewById(R.id.name);
|
||||
}
|
||||
|
||||
// Provide scaling values for WearableListView animations
|
||||
@Override
|
||||
public float getProximityMinValue() {
|
||||
return 1f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getProximityMaxValue() {
|
||||
return 1.6f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getCurrentProximityValue() {
|
||||
return mScale;
|
||||
}
|
||||
|
||||
// Scale the icon for WearableListView animations
|
||||
@Override
|
||||
public void setScalingAnimatorValue(float scale) {
|
||||
mScale = scale;
|
||||
mCircle.setScaleX(scale);
|
||||
mCircle.setScaleY(scale);
|
||||
}
|
||||
|
||||
// Change color of the icon, remove fading from the text
|
||||
@Override
|
||||
public void onScaleUpStart() {
|
||||
mName.setAlpha(1f);
|
||||
((GradientDrawable) mCircle.getDrawable()).setColor(mChosenCircleColor);
|
||||
}
|
||||
|
||||
// Change the color of the icon, fade the text
|
||||
@Override
|
||||
public void onScaleDownStart() {
|
||||
((GradientDrawable) mCircle.getDrawable()).setColor(mFadedCircleColor);
|
||||
mName.setAlpha(mFadedTextAlpha);
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
|
||||
<h2 id="layout-def">Create a Layout Definition for Items</h2>
|
||||
|
||||
<p>After you implement a custom layout for list items, you provide a layout definition file that
|
||||
specifies the layout parameters of each of the components inside a list item. The following layout
|
||||
definition uses the custom layout implementation from the previous section and defines an icon
|
||||
and a text view whose IDs match those in the layout implementation class:</p>
|
||||
|
||||
<pre>
|
||||
<-- res/layout/list_item.xml -->
|
||||
<com.example.android.support.wearable.notifications.WearableListItemLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="80dp">
|
||||
<ImageView
|
||||
android:id="@+id/circle"
|
||||
android:layout_height="20dp"
|
||||
android:layout_margin="16dp"
|
||||
android:layout_width="20dp"
|
||||
android:src="@drawable/wl_circle"/>
|
||||
<TextView
|
||||
android:id="@+id/name"
|
||||
android:gravity="center_vertical|left"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_height="match_parent"
|
||||
android:fontFamily="sans-serif-condensed-light"
|
||||
android:lineSpacingExtra="-4sp"
|
||||
android:textColor="@color/text_color"
|
||||
android:textSize="16sp"/>
|
||||
</com.example.android.support.wearable.notifications.WearableListItemLayout>
|
||||
</pre>
|
||||
|
||||
|
||||
<h2 id="adapter">Create an Adapter to Populate the List</h2>
|
||||
|
||||
<p>The adapter populates the <code>WearableListView</code> with content. The following simple
|
||||
adapter populates the list with elements based on an array of strings:</p>
|
||||
|
||||
<pre>
|
||||
private static final class Adapter extends WearableListView.Adapter {
|
||||
private String[] mDataset;
|
||||
private final Context mContext;
|
||||
private final LayoutInflater mInflater;
|
||||
|
||||
// Provide a suitable constructor (depends on the kind of dataset)
|
||||
public Adapter(Context context, String[] dataset) {
|
||||
mContext = context;
|
||||
mInflater = LayoutInflater.from(context);
|
||||
mDataset = dataset;
|
||||
}
|
||||
|
||||
// Provide a reference to the type of views you're using
|
||||
public static class ItemViewHolder extends WearableListView.ViewHolder {
|
||||
private TextView textView;
|
||||
public ItemViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
// find the text view within the custom item's layout
|
||||
textView = (TextView) itemView.findViewById(R.id.name);
|
||||
}
|
||||
}
|
||||
|
||||
// Create new views for list items
|
||||
// (invoked by the WearableListView's layout manager)
|
||||
@Override
|
||||
public WearableListView.ViewHolder onCreateViewHolder(ViewGroup parent,
|
||||
int viewType) {
|
||||
// Inflate our custom layout for list items
|
||||
return new ItemViewHolder(mInflater.inflate(R.layout.list_item, null));
|
||||
}
|
||||
|
||||
// Replace the contents of a list item
|
||||
// Instead of creating new views, the list tries to recycle existing ones
|
||||
// (invoked by the WearableListView's layout manager)
|
||||
@Override
|
||||
public void onBindViewHolder(WearableListView.ViewHolder holder,
|
||||
int position) {
|
||||
// retrieve the text view
|
||||
ItemViewHolder itemHolder = (ItemViewHolder) holder;
|
||||
TextView view = itemHolder.textView;
|
||||
// replace text contents
|
||||
view.setText(mDataset[position]);
|
||||
// replace list item's metadata
|
||||
holder.itemView.setTag(position);
|
||||
}
|
||||
|
||||
// Return the size of your dataset
|
||||
// (invoked by the WearableListView's layout manager)
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return mDataset.length;
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
|
||||
<h2 id="adapter-listener">Associate the Adapter and Set a Click Listener</h2>
|
||||
|
||||
<p>In your activity, obtain a reference to the <code>WearableListView</code> element from
|
||||
your layout, assign an instance of the adapter to populate the list, and set a click listener
|
||||
to complete an action when the user selects a particular list item.</p>
|
||||
|
||||
<pre>
|
||||
public class WearActivity extends Activity
|
||||
implements WearableListView.ClickListener {
|
||||
|
||||
// Sample dataset for the list
|
||||
String[] elements = { "List Item 1", "List Item 2", ... };
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.my_list_activity);
|
||||
|
||||
// Get the list component from the layout of the activity
|
||||
WearableListView listView =
|
||||
(WearableListView) findViewById(R.id.wearable_list);
|
||||
|
||||
// Assign an adapter to the list
|
||||
listView.setAdapter(new Adapter(this, elements));
|
||||
|
||||
// Set a click listener
|
||||
listView.setClickListener(this);
|
||||
}
|
||||
|
||||
// WearableListView click listener
|
||||
@Override
|
||||
public void onClick(WearableListView.ViewHolder v) {
|
||||
Integer tag = (Integer) v.itemView.getTag();
|
||||
// use this data to complete some action ...
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTopEmptyRegionClick() {
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
BIN
docs/html/wear/images/01_uilib.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
docs/html/wear/images/02_uilib.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
docs/html/wear/images/03_uilib.png
Normal file
|
After Width: | Height: | Size: 70 KiB |
BIN
docs/html/wear/images/04_uilib.png
Normal file
|
After Width: | Height: | Size: 60 KiB |
BIN
docs/html/wear/images/05_uilib.png
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
docs/html/wear/images/06_uilib.png
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
docs/html/wear/images/07_uilib.png
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
docs/html/wear/images/08_uilib.png
Normal file
|
After Width: | Height: | Size: 7.3 KiB |
BIN
docs/html/wear/images/09_uilib.png
Normal file
|
After Width: | Height: | Size: 16 KiB |