1page.title=Creating a Catalog Browser
2page.tags=tv, browsefragment, presenter, backgroundmanager
3helpoutsWidget=true
4
5trainingnavtop=true
6
7@jd:body
8
9<div id="tb-wrapper">
10<div id="tb">
11  <h2>This lesson teaches you to</h2>
12  <ol>
13    <li><a href="#layout">Create a Media Browse Layout</a></li>
14    <li><a href="#lists">Display Media Lists</a></li>
15    <li><a href="#background">Update the Background</a></li>
16  </ol>
17
18</div>
19</div>
20
21<p>
22  Media apps that run on TV need to allow users to browse its content offerings, make a
23  selection, and start playing content. The content browsing experience for apps of this type
24  should be simple and intuitive, as well as visually pleasing and engaging.
25</p>
26
27<p>
28  This lesson discusses how to use the classes provided by the <a href=
29  "{@docRoot}tools/support-library/features.html#v17-leanback">v17 leanback support library</a> to
30  implement a user interface for browsing music or videos from your app's media catalog.
31</p>
32
33
34<h2 id="layout">Create a Media Browse Layout</h2>
35
36<p>
37  The {@link android.support.v17.leanback.app.BrowseFragment} class in the leanback library
38  allows you to create a primary layout for browsing categories and rows of media items with a
39  minimum of code. The following example shows how to create a layout that contains a {@link
40  android.support.v17.leanback.app.BrowseFragment}:
41</p>
42
43<pre>
44&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
45  android:layout_width=&quot;match_parent&quot;
46  android:layout_height=&quot;match_parent&quot;
47  android:orientation=&quot;vertical&quot;
48  &gt;
49
50  &lt;fragment
51      <strong>android:name="android.support.v17.leanback.app.BrowseFragment"</strong>
52      android:id=&quot;@+id/browse_fragment&quot;
53      android:layout_width=&quot;match_parent&quot;
54      android:layout_height=&quot;match_parent&quot;
55      /&gt;
56&lt;/LinearLayout&gt;
57</pre>
58
59<p>
60  In order to work with this layout in an activity, retrieve the {@link
61  android.support.v17.leanback.app.BrowseFragment} element from the layout. Use the methods in this
62  class to set display parameters such as the icon, title, and whether category headers are enabled.
63  The following code sample demonstrates how to set the layout parameters for a {@link
64  android.support.v17.leanback.app.BrowseFragment} in a layout:
65</p>
66
67<pre>
68public class BrowseMediaActivity extends Activity {
69
70    public static final String TAG ="BrowseActivity";
71
72    protected BrowseFragment mBrowseFragment;
73
74    &#64;Override
75    protected void onCreate(Bundle savedInstanceState) {
76        super.onCreate(savedInstanceState);
77        setContentView(R.layout.browse_fragment);
78
79        final FragmentManager fragmentManager = getFragmentManager();
80        <strong>mBrowseFragment = (BrowseFragment) fragmentManager.findFragmentById(
81                R.id.browse_fragment);</strong>
82
83        // Set display parameters for the BrowseFragment
84        mBrowseFragment.setHeadersState(BrowseFragment.HEADERS_ENABLED);
85        mBrowseFragment.setTitle(getString(R.string.app_name));
86        mBrowseFragment.setBadgeDrawable(getResources().getDrawable(
87                R.drawable.ic_launcher));
88        mBrowseFragment.setBrowseParams(params);
89
90    }
91}
92</pre>
93
94
95<h2 id="lists">Displaying Media Lists</h2>
96
97<p>
98  The {@link android.support.v17.leanback.app.BrowseFragment} allows you to define and display
99  browsable media content categories and media items from a media catalog using adapters and
100  presenters. Adapters enable you to connect to local or online data sources that contain your
101  media catalog information. Presenters hold data about media items and provide layout information
102  for displaying an item on screen.
103</p>
104
105<p>
106  The following example code shows an implementation of a {@link
107  android.support.v17.leanback.widget.Presenter} for displaying string data:
108</p>
109
110<pre>
111public class StringPresenter extends Presenter {
112    private static final String TAG = "StringPresenter";
113
114    public ViewHolder onCreateViewHolder(ViewGroup parent) {
115        TextView textView = new TextView(parent.getContext());
116        textView.setFocusable(true);
117        textView.setFocusableInTouchMode(true);
118        textView.setBackground(
119                parent.getContext().getResources().getDrawable(R.drawable.text_bg));
120        return new ViewHolder(textView);
121    }
122
123    public void onBindViewHolder(ViewHolder viewHolder, Object item) {
124        ((TextView) viewHolder.view).setText(item.toString());
125    }
126
127    public void onUnbindViewHolder(ViewHolder viewHolder) {
128        // no op
129    }
130}
131</pre>
132
133<p>
134  Once you have constructed a presenter class for your media items, you can build and attach an
135  adapter to the {@link android.support.v17.leanback.app.BrowseFragment} to display those items on
136  screen for browsing by the user. The following example code demonstrates how to construct an
137  adapter to display categories and items in those categories using the {@code StringPresenter}
138  class shown in the previous code example:
139</p>
140
141<pre>
142private ArrayObjectAdapter mRowsAdapter;
143private static final int NUM_ROWS = 4;
144
145&#64;Override
146protected void onCreate(Bundle savedInstanceState) {
147    ...
148
149    buildRowsAdapter();
150}
151
152private void buildRowsAdapter() {
153    mRowsAdapter = new ArrayObjectAdapter(new ListRowPresenter());
154
155    for (int i = 0; i &lt; NUM_ROWS; ++i) {
156        ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(
157                new StringPresenter());
158        listRowAdapter.add("Media Item 1");
159        listRowAdapter.add("Media Item 2");
160        listRowAdapter.add("Media Item 3");
161        HeaderItem header = new HeaderItem(i, "Category " + i, null);
162        mRowsAdapter.add(new ListRow(header, listRowAdapter));
163    }
164
165    mBrowseFragment.setAdapter(mRowsAdapter);
166}
167</pre>
168
169<p>
170  This example shows a static implementation of the adapters. A typical media browsing application
171  uses data from an online database or web service. For an example of a browsing application that
172  uses data retrieved from the web, see the
173  <a href="http://github.com/googlesamples/androidtv-leanback">Android TV</a> sample app.
174</p>
175
176<h2 id="background">Update the Background</h2>
177
178<p>
179  In order to add visual interest to a media-browsing app on TV, you can update the background
180  image as users browse through content. This technique can make interaction with your app feel
181  more cinematic and enjoyable for users.
182</p>
183
184<p>
185  The Leanback support library provides a {@link android.support.v17.leanback.app.BackgroundManager}
186  class for changing the background of your TV app activity. The following example shows how to
187  create a simple method for updating the background within your TV app activity:
188</p>
189
190<pre>
191protected void updateBackground(Drawable drawable) {
192    BackgroundManager.getInstance(this).setDrawable(drawable);
193}
194</pre>
195
196<p>
197  Many of the existing media-browse apps automatically update the background as the user navigates
198  through media listings. In order to do this, you can set up a selection listener to automatically
199  update the background based on the user's current selection. The following example shows you how
200  to set up an {@link android.support.v17.leanback.widget.OnItemViewSelectedListener} class to
201  catch selection events and update the background:
202</p>
203
204<pre>
205protected void clearBackground() {
206    BackgroundManager.getInstance(this).setDrawable(mDefaultBackground);
207}
208
209protected OnItemViewSelectedListener getDefaultItemViewSelectedListener() {
210    return new OnItemViewSelectedListener() {
211        &#64;Override
212        public void onItemSelected(Object item, Row row) {
213            if (item instanceof Movie ) {
214                URI uri = ((Movie)item).getBackdropURI();
215                updateBackground(uri);
216            } else {
217                clearBackground();
218            }
219        }
220    };
221}
222</pre>
223
224<p class="note">
225  <strong>Note:</strong> The implementation above is a simple example shown for purposes of
226  illustration. When creating this function in your own app, you should consider running the
227  background update action in a separate thread for better performance. In addition, if you are
228  planning on updating the background in response to users scrolling through items, consider adding
229  a time to delay a background image update until the user settles on an item. This technique avoids
230  excessive background image updates.
231</p>
232