blob: fb7c097a0ff23b96d3ea0a05de067ec6e704dde6 [file] [log] [blame]
page.title=Searching within TV Apps
page.tags=tv, leanback
helpoutsWidget=true
trainingnavtop=true
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>This lesson teaches you to</h2>
<ol>
<li><a href="#add-search-action">Add a Search Action</a></li>
<li><a href="#add-search-ui">Add Search Input and Results</a></li>
</ol>
</div>
</div>
<p>
Users frequently have specific content in mind when using a media app on TV. If your app contains
a large catalog of content, browsing for a specific title may not be the most efficient way for
users to find what they are looking for. A search interface can help your users get to the
content they want faster than browsing.
</p>
<p>
The <a href="{@docRoot}tools/support-library/features.html#v17-leanback">Leanback support
library</a> provides a set of classes to enable a standard search interface within your app that
is consistent with other search functions on TV and provides features such as voice input.
</p>
<p>
This lesson discusses how to provide a search interface in your app using Leanback support
library classes.
</p>
<h2 id="add-search-action">Add a Search Action</h2>
<p>
When you use the {@link android.support.v17.leanback.app.BrowseFragment} class for a media
browsing interface, you can enable a search interface as a standard part of the user
interface. The search interface is an icon that appears in the layout when you set {@link
android.view.View.OnClickListener} on the {@link android.support.v17.leanback.app.BrowseFragment}
object. The following sample code demonstrates this technique.
</p>
<pre>
&#64;Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.browse_activity);
mBrowseFragment = (BrowseFragment)
getFragmentManager().findFragmentById(R.id.browse_fragment);
...
mBrowseFragment.setOnSearchClickedListener(new View.OnClickListener() {
&#64;Override
public void onClick(View view) {
Intent intent = new Intent(BrowseActivity.this, SearchActivity.class);
startActivity(intent);
}
});
mBrowseFragment.setAdapter(buildAdapter());
}
</pre>
<p class="note">
<strong>Note:</strong> You can set the color of the search icon using the
{@link android.support.v17.leanback.app.BrowseFragment#setSearchAffordanceColor}.
</p>
<h2 id="add-search-ui">Add a Search Input and Results</h2>
<p>
When a user selects the search icon, the system invokes a search activity via the defined intent.
Your search activity should use a linear layout containing a {@link
android.support.v17.leanback.app.SearchFragment}. This fragment must also implement the {@link
android.support.v17.leanback.app.SearchFragment.SearchResultProvider} interface in order to
display the results of a search.
</p>
<p>
The following code sample shows how to extend the {@link
android.support.v17.leanback.app.SearchFragment} class to provide a search interface and results:
</p>
<pre>
public class MySearchFragment extends SearchFragment
implements SearchFragment.SearchResultProvider {
private static final int SEARCH_DELAY_MS = 300;
private ArrayObjectAdapter mRowsAdapter;
private Handler mHandler = new Handler();
private SearchRunnable mDelayedLoad;
&#64;Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mRowsAdapter = new ArrayObjectAdapter(new ListRowPresenter());
setSearchResultProvider(this);
setOnItemClickedListener(getDefaultItemClickedListener());
mDelayedLoad = new SearchRunnable();
}
&#64;Override
public ObjectAdapter getResultsAdapter() {
return mRowsAdapter;
}
&#64;Override
public boolean onQueryTextChange(String newQuery) {
mRowsAdapter.clear();
if (!TextUtils.isEmpty(newQuery)) {
mDelayedLoad.setSearchQuery(newQuery);
mHandler.removeCallbacks(mDelayedLoad);
mHandler.postDelayed(mDelayedLoad, SEARCH_DELAY_MS);
}
return true;
}
&#64;Override
public boolean onQueryTextSubmit(String query) {
mRowsAdapter.clear();
if (!TextUtils.isEmpty(query)) {
mDelayedLoad.setSearchQuery(query);
mHandler.removeCallbacks(mDelayedLoad);
mHandler.postDelayed(mDelayedLoad, SEARCH_DELAY_MS);
}
return true;
}
}
</pre>
<p>
The example code shown above is meant to be used with a separate {@code SearchRunnable} class
that runs the search query on a separate thread. This technique keeps potentially slow-running
queries from blocking the main user interface thread.
</p>