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