summaryrefslogtreecommitdiffstats
path: root/docs/html/training/tv/discovery/in-app-search.jd
blob: fb7c097a0ff23b96d3ea0a05de067ec6e704dde6 (plain)
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
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>