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>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
     20 Wear allows users to navigate and choose from a set of items shown as pages. The Wearable UI
     21 Library lets you easily implement this pattern using a page grid, which is a layout manager
     22 that 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
     25 of your activity and implement an adapter that provides a set of pages by extending
     26 the <code>FragmentGridPagerAdapter</code> class.</p>
     27 
     28 <p class="note"><strong>Note:</strong> The <em>GridViewPager</em> sample in the Android SDK
     29 demonstrates how to use the <code>GridViewPager</code> layout in your apps. This sample is
     30 located 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
     47 your 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
     53 implement this adapter, you extend the <code>FragmentGridPageAdapter</code> class from the
     54 Wearable UI Library</p>
     55 
     56 <p>For example, the <em>GridViewPager</em> sample in the Android SDK contains
     57 the following adapter implementation that provides a set of static cards with custom background
     58 images:</p>
     59 
     60 <pre>
     61 public 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
     93 to display at each position of the grid:</p>
     94 
     95 <pre>
     96 // Obtain the UI fragment at the specified position
     97 &#64;Override
     98 public 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
    116 public 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
    122 available, and the <code>getColumnCount</code> method tells the picker how many columns
    123 of content are available for each of the rows.</p>
    124 
    125 <pre>
    126 // Obtain the number of pages (vertical)
    127 &#64;Override
    128 public int getRowCount() {
    129     return PAGES.length;
    130 }
    131 
    132 // Obtain the number of pages (horizontal)
    133 &#64;Override
    134 public 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
    140 by 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
    142 combine different types of pages in the same 2D picker, such as cards, action icons, and custom
    143 layouts 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>
    148 The <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
    152 colums is different for each row. You can also use a <code>GridViewPager</code> component to
    153 implement 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
    156 the device screen. This example configures each card to expand as required, so users can scroll
    157 through the card's content. When users reach the end of a scrollable card, a swipe in the same
    158 direction 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.
    161 When users swipe to navigate across pages, <code>GridViewPager</code> applies parallax
    162 and 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>
    170 public 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