Home | History | Annotate | Download | only in ui
      1 page.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
     25 Wear allows users to navigate and choose from a set of items shown as pages. The Wearable UI
     26 Library lets you easily implement this pattern using a page grid, which is a layout manager
     27 that 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>
     31 element to the layout of your activity and implement an adapter that provides a set of pages by
     32 extending the
     33 <a href="{@docRoot}reference/android/support/wearable/view/FragmentGridPagerAdapter.html"><code>FragmentGridPagerAdapter</code></a>
     34 class.</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>
     41 element to your layout definition as follows:</p>
     42 
     43 <pre>
     44 &lt;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
     53 your 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>
     60 component. To implement this adapter, you extend the
     61 <a href="{@docRoot}reference/android/support/wearable/view/FragmentGridPagerAdapter.html"><code>FragmentGridPagerAdapter</code></a>
     62 class from the Wearable UI Library</p>
     63 
     64 <p>The following snippet shows how to provide a set of static cards with custom background
     65 images:</p>
     66 
     67 <pre>
     68 public 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>
    102 and
    103 <a href="{@docRoot}reference/android/support/wearable/view/GridPagerAdapter.html#getBackgroundForRow(int)"><code>getBackgroundForRow()</code></a>
    104 to retrieve the content to display for each row:</p>
    105 
    106 <pre>
    107 // Obtain the UI fragment at the specified position
    108 &#64;Override
    109 public 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 &#64;Override
    127 public 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
    135 in the grid:
    136 </p>
    137 
    138 <pre>
    139 // Obtain the background image for the specific page
    140 &#64;Override
    141 public 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>
    154 method tells the adapter how many rows of content are
    155 available, and the
    156 <a href="{@docRoot}reference/android/support/wearable/view/GridPagerAdapter.html#getColumnCount(int)"><code>getColumnCount()</code></a>
    157 method 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 &#64;Override
    162 public int getRowCount() {
    163     return PAGES.length;
    164 }
    165 
    166 // Obtain the number of pages (horizontal)
    167 &#64;Override
    168 public 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
    174 by the adapter is of type
    175 <a href="{@docRoot}reference/android/app/Fragment.html"><code>Fragment</code></a>.
    176 In this example, each page is a
    177 <a href="{@docRoot}reference/android/support/wearable/view/CardFragment.html"><code>CardFragment</code></a>
    178 instance that uses one of the default card layouts. However, you can combine different types of
    179 pages in the same 2D picker, such as cards, action icons, and custom layouts depending on your use
    180 cases.</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>
    185 The <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
    189 colums 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>
    191 component 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>
    195 class provides support for scrolling in cards whose content does not fit
    196 the device screen. This example configures each card to expand as required, so users can scroll
    197 through the card's content. When users reach the end of a scrollable card, a swipe in the same
    198 direction 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>
    202 method. When users swipe to navigate across pages, the
    203 <a href="{@docRoot}reference/android/support/wearable/view/GridViewPager.html"><code>GridViewPager</code></a>
    204 class 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>
    210 component:</p>
    211 
    212 <pre style="clear:both">
    213 public class MainActivity extends Activity {
    214 
    215     &#64;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