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@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 @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 @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 @Override 113 public ObjectAdapter getResultsAdapter() { 114 return mRowsAdapter; 115 } 116 117 @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 @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