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