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