SearchFragment.java revision 17993c442c26161f684d6c0c6867a746f3148548
1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 * in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the License 10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 * or implied. See the License for the specific language governing permissions and limitations under 12 * the License. 13 */ 14package android.support.v17.leanback.app; 15 16import android.app.Fragment; 17import android.os.Bundle; 18import android.os.Handler; 19import android.support.v17.leanback.widget.ObjectAdapter; 20import android.support.v17.leanback.widget.OnItemClickedListener; 21import android.support.v17.leanback.widget.OnItemSelectedListener; 22import android.support.v17.leanback.widget.SearchBar; 23import android.view.LayoutInflater; 24import android.view.View; 25import android.view.ViewGroup; 26import android.widget.FrameLayout; 27import android.widget.RelativeLayout; 28import android.support.v17.leanback.R; 29 30/** 31 * A fragment to handle searches 32 */ 33public class SearchFragment extends Fragment { 34 private static final String TAG = SearchFragment.class.getSimpleName(); 35 private static final String ARG_QUERY = SearchFragment.class.getCanonicalName() + ".query"; 36 37 /** 38 * Search API exposed to application 39 */ 40 public static interface SearchResultProvider { 41 /** 42 * When using the SearchFragment, this is the entry point for the application 43 * to receive the search query and provide the corresponding results. 44 * 45 * The returned ObjectAdapter can be populated asynchronously. 46 * 47 * As results are retrieved, the application should use the data set notification methods 48 * on the ObjectAdapter to instruct the SearchFragment to update the results. 49 * 50 * @param searchQuery The search query entered by the user. 51 * @return An ObjectAdapter containing the structured results for the provided search query. 52 */ 53 public ObjectAdapter results(String searchQuery); 54 } 55 56 private final RowsFragment mRowsFragment = new RowsFragment(); 57 private final Handler mHandler = new Handler(); 58 59 private RelativeLayout mSearchFrame; 60 private SearchBar mSearchBar; 61 private FrameLayout mResultsFrame; 62 private SearchResultProvider mProvider; 63 private String mPendingQuery = null; 64 65 /** 66 * @param args Bundle to use for the arguments, if null a new Bundle will be created. 67 */ 68 public static Bundle createArgs(Bundle args, String query) { 69 if (args == null) { 70 args = new Bundle(); 71 } 72 args.putString(ARG_QUERY, query); 73 return args; 74 } 75 76 /** 77 * Create a search fragment with a given search query to start with 78 * 79 * You should only use this if you need to start the search fragment with a pre-filled query 80 * 81 * @param query the search query to start with 82 * @return a new SearchFragment 83 */ 84 public static SearchFragment newInstance(String query) { 85 SearchFragment fragment = new SearchFragment(); 86 Bundle args = createArgs(null, query); 87 fragment.setArguments(args); 88 return fragment; 89 } 90 91 @Override 92 public void onCreate(Bundle savedInstanceState) { 93 super.onCreate(savedInstanceState); 94 } 95 96 @Override 97 public View onCreateView(LayoutInflater inflater, ViewGroup container, 98 Bundle savedInstanceState) { 99 View root = inflater.inflate(R.layout.lb_search_fragment, container, false); 100 101 mSearchFrame = (RelativeLayout) root.findViewById(R.id.lb_search_frame); 102 mResultsFrame = (FrameLayout) root.findViewById(R.id.lb_results_frame); 103 mSearchBar = (SearchBar) mSearchFrame.findViewById(R.id.lb_search_bar); 104 mSearchBar.setSearchBarListener(new SearchBar.SearchBarListener() { 105 @Override 106 public void onSearchQueryChanged(String searchQuery) { 107 if (null != mProvider) { 108 retrieveResults(searchQuery); 109 } else { 110 mPendingQuery = searchQuery; 111 } 112 } 113 }); 114 Bundle args = getArguments(); 115 if (null != args) { 116 String query = args.getString(ARG_QUERY, ""); 117 mSearchBar.setSearchQuery(query); 118 } 119 120 // Inject the RowsFragment in the results container 121 getChildFragmentManager().beginTransaction() 122 .replace(R.id.lb_results_container, mRowsFragment).commit(); 123 return root; 124 } 125 126 /** 127 * Set the search provider, which is responsible for returning items given 128 * a search term 129 * 130 * @param searchResultProvider the search provider 131 */ 132 public void setSearchResultProvider(SearchResultProvider searchResultProvider) { 133 mProvider = searchResultProvider; 134 onSetSearchResultProvider(); 135 } 136 137 /** 138 * Sets an item selection listener. 139 * @param listener the item selection listener 140 */ 141 public void setOnItemSelectedListener(OnItemSelectedListener listener) { 142 mRowsFragment.setOnItemSelectedListener(listener); 143 } 144 145 /** 146 * Sets an item clicked listener. 147 */ 148 public void setOnItemClickedListener(OnItemClickedListener listener) { 149 mRowsFragment.setOnItemClickedListener(listener); 150 } 151 152 /** 153 * Set the visibility of titles/hovercard of browse rows. 154 */ 155 public void setExpand(boolean expand) { 156 mRowsFragment.setExpand(expand); 157 } 158 159 private void retrieveResults(String searchQuery) { 160 ObjectAdapter adapter = mProvider.results(searchQuery); 161 mRowsFragment.setAdapter(adapter); 162 mResultsFrame.setVisibility(View.VISIBLE); 163 } 164 165 private void onSetSearchResultProvider() { 166 executePendingQuery(); 167 } 168 169 private void executePendingQuery() { 170 if (null != mPendingQuery) { 171 mHandler.post(new Runnable() { 172 @Override 173 public void run() { 174 retrieveResults(mPendingQuery); 175 mPendingQuery = null; 176 } 177 }); 178 } 179 } 180 181} 182