• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1page.title=Creating a 2D Picker
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-page-grid">Add a Page Grid</a></li>
10  <li><a href="#implement-adapter">Implement a Page Adapter</a></li>
11</ol>
12<h2>You should also read</h2>
13<ul>
14  <li><a href="{@docRoot}design/wear/index.html">Android Wear Design Principles</a></li>
15</ul>
16</div>
17</div>
18
19<p>The <a href="{@docRoot}design/wear/structure.html#2DPicker">2D Picker</a> pattern in Android
20Wear allows users to navigate and choose from a set of items shown as pages. The Wearable UI
21Library lets you easily implement this pattern using a page grid, which is a layout manager
22that allows users to scroll vertically and horizontally through pages of data.</p>
23
24<p>To implement this pattern, you add a <code>GridViewPager</code> element to the layout
25of your activity and implement an adapter that provides a set of pages by extending
26the <code>FragmentGridPagerAdapter</code> class.</p>
27
28<p class="note"><strong>Note:</strong> The <em>GridViewPager</em> sample in the Android SDK
29demonstrates how to use the <code>GridViewPager</code> layout in your apps. This sample is
30located in the <code>android-sdk/samples/android-20/wearable/GridViewPager</code> directory.</p>
31
32
33<h2 id="add-page-grid">Add a Page Grid</h2>
34
35<p>Add a <code>GridViewPager</code> element to your layout definition as follows:</p>
36
37<pre>
38&lt;android.support.wearable.view.GridViewPager
39    xmlns:android="http://schemas.android.com/apk/res/android"
40    android:id="@+id/pager"
41    android:layout_width="match_parent"
42    android:layout_height="match_parent" />
43</pre>
44
45<p>You can use any of the techniques described in
46<a href="{@docRoot}training/wearables/ui/layouts.html">Defining Layouts</a> to ensure that
47your 2D picker works on both round and square devices.</p>
48
49
50<h2 id="implement-adapter">Implement a Page Adapter</h2>
51
52<p>A page adapter provides a set of pages to populate a <code>GridViewPager</code> component. To
53implement this adapter, you extend the <code>FragmentGridPageAdapter</code> class from the
54Wearable UI Library</p>
55
56<p>For example, the <em>GridViewPager</em> sample in the Android SDK contains
57the following adapter implementation that provides a set of static cards with custom background
58images:</p>
59
60<pre>
61public class SampleGridPagerAdapter extends FragmentGridPagerAdapter {
62
63    private final Context mContext;
64
65    public SampleGridPagerAdapter(Context ctx, FragmentManager fm) {
66        super(fm);
67        mContext = ctx;
68    }
69
70    static final int[] BG_IMAGES = new int[] {
71            R.drawable.debug_background_1, ...
72            R.drawable.debug_background_5
73    };
74
75    // A simple container for static data in each page
76    private static class Page {
77        // static resources
78        int titleRes;
79        int textRes;
80        int iconRes;
81        ...
82    }
83
84    // Create a static set of pages in a 2D array
85    private final Page[][] PAGES = { ... };
86
87    // Override methods in FragmentGridPagerAdapter
88    ...
89}
90</pre>
91
92<p>The picker calls <code>getFragment</code> and <code>getBackground</code> to retrieve the content
93to display at each position of the grid:</p>
94
95<pre>
96// Obtain the UI fragment at the specified position
97&#64;Override
98public Fragment getFragment(int row, int col) {
99    Page page = PAGES[row][col];
100    String title =
101        page.titleRes != 0 ? mContext.getString(page.titleRes) : null;
102    String text =
103        page.textRes != 0 ? mContext.getString(page.textRes) : null;
104    CardFragment fragment = CardFragment.create(title, text, page.iconRes);
105
106    // Advanced settings (card gravity, card expansion/scrolling)
107    fragment.setCardGravity(page.cardGravity);
108    fragment.setExpansionEnabled(page.expansionEnabled);
109    fragment.setExpansionDirection(page.expansionDirection);
110    fragment.setExpansionFactor(page.expansionFactor);
111    return fragment;
112}
113
114// Obtain the background image for the page at the specified position
115&#64;Override
116public ImageReference getBackground(int row, int column) {
117    return ImageReference.forDrawable(BG_IMAGES[row % BG_IMAGES.length]);
118}
119</pre>
120
121<p>The <code>getRowCount</code> method tells the picker how many rows of content are
122available, and the <code>getColumnCount</code> method tells the picker how many columns
123of content are available for each of the rows.</p>
124
125<pre>
126// Obtain the number of pages (vertical)
127&#64;Override
128public int getRowCount() {
129    return PAGES.length;
130}
131
132// Obtain the number of pages (horizontal)
133&#64;Override
134public int getColumnCount(int rowNum) {
135    return PAGES[rowNum].length;
136}
137</pre>
138
139<p>The adapter implementation details depend on your particular set of pages. Each page provided
140by the adapter is of type <code>Fragment</code>. In this example, each page is a
141<code>CardFragment</code> instance that uses one of the default card layouts. However, you can
142combine different types of pages in the same 2D picker, such as cards, action icons, and custom
143layouts depending on your use cases.</p>
144
145<div style="float:right;margin-left:25px;width:250px">
146<img src="{@docRoot}wear/images/07_uilib.png" width="250" height="250" alt=""/>
147<p class="img-caption" style="text-align:center"><strong>Figure 1:</strong>
148The <em>GridViewPager</em> sample.</p>
149</div>
150
151<p>Not all rows need to have the same number of pages. Notice that in this example the number of
152colums is different for each row. You can also use a <code>GridViewPager</code> component to
153implement a 1D picker with only one row or only one column.</p>
154
155<p><code>GridViewPager</code> provides support for scrolling in cards whose content does not fit
156the device screen. This example configures each card to expand as required, so users can scroll
157through the card's content. When users reach the end of a scrollable card, a swipe in the same
158direction shows the next page on the grid, if one is available.</p>
159
160<p>You can specify a custom background for each page with the <code>getBackground()</code> method.
161When users swipe to navigate across pages, <code>GridViewPager</code> applies parallax
162and crossfade effects between different backgrounds automatically.</p>
163
164<h3>Assign an adapter instance to the page grid</h3>
165
166<p>In your activity, assign an instance of your adapter implementation to the
167<code>GridViewPager</code> component:</p>
168
169<pre>
170public class MainActivity extends Activity {
171
172    &#64;Override
173    protected void onCreate(Bundle savedInstanceState) {
174        super.onCreate(savedInstanceState);
175        setContentView(R.layout.activity_main);
176        ...
177        final GridViewPager pager = (GridViewPager) findViewById(R.id.pager);
178        pager.setAdapter(new SampleGridPagerAdapter(this, getFragmentManager()));
179    }
180}
181</pre>
182