• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1page.title=Searching within TV Apps
2page.tags="leanback"
3
4trainingnavtop=true
5
6@jd:body
7
8<div id="tb-wrapper">
9<div id="tb">
10  <h2>This lesson teaches you to</h2>
11  <ol>
12    <li><a href="#add-search-action">Add a Search Action</a></li>
13    <li><a href="#add-search-ui">Add Search Input and Results</a></li>
14  </ol>
15
16</div>
17</div>
18
19
20<p>
21  Users frequently have specific content in mind when using a media app on TV. If your app contains
22  a large catalog of content, browsing for a specific title may not be the most efficient way for
23  users to find what they are looking for. A search interface can help your users get to the
24  content they want faster than browsing.
25</p>
26
27<p>
28  The <a href="{@docRoot}tools/support-library/features.html#v17-leanback">Leanback support
29  library</a> provides a set of classes to enable a standard search interface within your app that
30  is consistent with other search functions on TV and provides features such as voice input.
31</p>
32
33<p>
34  This lesson discusses how to provide a search interface in your app using Leanback support
35  library classes.
36</p>
37
38
39<h2 id="add-search-action">Add a Search Action</h2>
40
41<p>
42  When you use the {@link android.support.v17.leanback.app.BrowseFragment} class for a media
43  browsing interface, you can enable a search interface as a standard part of the user
44  interface. The search interface is an icon that appears in the layout when you set {@link
45  android.view.View.OnClickListener} on the {@link android.support.v17.leanback.app.BrowseFragment}
46  object. The following sample code demonstrates this technique.
47</p>
48
49<pre>
50&#64;Override
51public void onCreate(Bundle savedInstanceState) {
52    super.onCreate(savedInstanceState);
53    setContentView(R.layout.browse_activity);
54
55    mBrowseFragment = (BrowseFragment)
56            getFragmentManager().findFragmentById(R.id.browse_fragment);
57
58    ...
59
60    mBrowseFragment.setOnSearchClickedListener(new View.OnClickListener() {
61        &#64;Override
62        public void onClick(View view) {
63            Intent intent = new Intent(BrowseActivity.this, SearchActivity.class);
64            startActivity(intent);
65        }
66    });
67
68    mBrowseFragment.setAdapter(buildAdapter());
69}
70</pre>
71
72<p class="note">
73  <strong>Note:</strong> You can set the color of the search icon using the
74  {@link android.support.v17.leanback.app.BrowseFragment#setSearchAffordanceColor}.
75</p>
76
77
78<h2 id="add-search-ui">Add a Search Input and Results</h2>
79
80<p>
81  When a user selects the search icon, the system invokes a search activity via the defined intent.
82  Your search activity should use a linear layout containing a {@link
83  android.support.v17.leanback.app.SearchFragment}. This fragment must also implement the {@link
84  android.support.v17.leanback.app.SearchFragment.SearchResultProvider} interface in order to
85  display the results of a search.
86</p>
87
88<p>
89  The following code sample shows how to extend the {@link
90  android.support.v17.leanback.app.SearchFragment} class to provide a search interface and results:
91</p>
92
93<pre>
94public class MySearchFragment extends SearchFragment
95        implements SearchFragment.SearchResultProvider {
96
97    private static final int SEARCH_DELAY_MS = 300;
98    private ArrayObjectAdapter mRowsAdapter;
99    private Handler mHandler = new Handler();
100    private SearchRunnable mDelayedLoad;
101
102    &#64;Override
103    public void onCreate(Bundle savedInstanceState) {
104        super.onCreate(savedInstanceState);
105
106        mRowsAdapter = new ArrayObjectAdapter(new ListRowPresenter());
107        setSearchResultProvider(this);
108        setOnItemClickedListener(getDefaultItemClickedListener());
109        mDelayedLoad = new SearchRunnable();
110    }
111
112    &#64;Override
113    public ObjectAdapter getResultsAdapter() {
114        return mRowsAdapter;
115    }
116
117    &#64;Override
118    public boolean onQueryTextChange(String newQuery) {
119        mRowsAdapter.clear();
120        if (!TextUtils.isEmpty(newQuery)) {
121            mDelayedLoad.setSearchQuery(newQuery);
122            mHandler.removeCallbacks(mDelayedLoad);
123            mHandler.postDelayed(mDelayedLoad, SEARCH_DELAY_MS);
124        }
125        return true;
126    }
127
128    &#64;Override
129    public boolean onQueryTextSubmit(String query) {
130        mRowsAdapter.clear();
131        if (!TextUtils.isEmpty(query)) {
132            mDelayedLoad.setSearchQuery(query);
133            mHandler.removeCallbacks(mDelayedLoad);
134            mHandler.postDelayed(mDelayedLoad, SEARCH_DELAY_MS);
135        }
136        return true;
137    }
138}
139</pre>
140
141<p>
142  The example code shown above is meant to be used with a separate {@code SearchRunnable} class
143  that runs the search query on a separate thread. This technique keeps potentially slow-running
144  queries from blocking the main user interface thread.
145</p>
146