SearchViewManager.java revision f6a31d319f3e08d26ca4c0fbfb5803056bafb243
1/* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.documentsui; 18 19import android.provider.DocumentsContract.Root; 20import android.text.TextUtils; 21import android.util.Log; 22import android.view.MenuItem; 23import android.view.View; 24import android.view.View.OnClickListener; 25import android.view.View.OnFocusChangeListener; 26import android.widget.SearchView; 27import android.widget.SearchView.OnQueryTextListener; 28 29import com.android.documentsui.model.RootInfo; 30 31/** 32 * Manages searching UI behavior. 33 */ 34final class SearchManager implements 35 SearchView.OnCloseListener, OnQueryTextListener, OnClickListener, OnFocusChangeListener { 36 37 public interface SearchManagerListener { 38 void onSearchChanged(); 39 40 void onSearchQueryChanged(String query); 41 } 42 43 public static final String TAG = "SearchManger"; 44 45 private SearchManagerListener mListener; 46 private String currentSearch; 47 private boolean mSearchExpanded; 48 private boolean mIgnoreNextClose; 49 50 private DocumentsToolBar mActionBar; 51 private MenuItem mMenu; 52 private SearchView mView; 53 54 public SearchManager(SearchManagerListener listener) { 55 mListener = listener; 56 } 57 58 public void setSearchMangerListener(SearchManagerListener listener) { 59 mListener = listener; 60 } 61 62 public void install(DocumentsToolBar actionBar) { 63 assert (mActionBar == null); 64 mActionBar = actionBar; 65 mMenu = actionBar.getSearchMenu(); 66 mView = (SearchView) mMenu.getActionView(); 67 68 mView.setOnQueryTextListener(this); 69 mView.setOnCloseListener(this); 70 mView.setOnSearchClickListener(this); 71 mView.setOnQueryTextFocusChangeListener(this); 72 } 73 74 /** 75 * @param root Info about the current directory. 76 */ 77 void update(RootInfo root) { 78 if (mMenu == null) { 79 Log.d(TAG, "update called before Search MenuItem installed."); 80 return; 81 } 82 83 if (currentSearch != null) { 84 mMenu.expandActionView(); 85 86 mView.setIconified(false); 87 mView.clearFocus(); 88 mView.setQuery(currentSearch, false); 89 } else { 90 mView.clearFocus(); 91 if (!mView.isIconified()) { 92 mIgnoreNextClose = true; 93 mView.setIconified(true); 94 } 95 96 if (mMenu.isActionViewExpanded()) { 97 mMenu.collapseActionView(); 98 } 99 } 100 101 showMenu(root != null 102 && ((root.flags & Root.FLAG_SUPPORTS_SEARCH) != 0)); 103 } 104 105 void showMenu(boolean visible) { 106 if (mMenu == null) { 107 Log.d(TAG, "showMenu called before Search MenuItem installed."); 108 return; 109 } 110 111 mMenu.setVisible(visible); 112 if (!visible) { 113 currentSearch = null; 114 if (mListener != null) { 115 mListener.onSearchQueryChanged(currentSearch); 116 } 117 } 118 } 119 120 /** 121 * Cancels current search operation. Triggers clearing and collapsing the SearchView. 122 * 123 * @return True if it cancels search. False if it does not operate search currently. 124 */ 125 boolean cancelSearch() { 126 if (isExpanded() || isSearching()) { 127 // If the query string is not empty search view won't get iconified 128 mView.setQuery("", false); 129 // Causes calling onClose(). onClose() is triggering directory content update. 130 mView.setIconified(true); 131 return true; 132 } 133 return false; 134 } 135 136 boolean isSearching() { 137 return currentSearch != null; 138 } 139 140 boolean isExpanded() { 141 return mSearchExpanded; 142 } 143 144 /** 145 * Clears the search. Clears the SearchView background color. Triggers refreshing of the 146 * directory content. 147 * @return True if the default behavior of clearing/dismissing SearchView should be overridden. 148 * False otherwise. 149 */ 150 @Override 151 public boolean onClose() { 152 mSearchExpanded = false; 153 if (mIgnoreNextClose) { 154 mIgnoreNextClose = false; 155 return false; 156 } 157 158 mView.setBackgroundColor( 159 mView.getResources().getColor(android.R.color.transparent, null)); 160 161 // Refresh the directory if a search was done 162 if (currentSearch != null) { 163 currentSearch = null; 164 if (mListener != null) { 165 mListener.onSearchQueryChanged(currentSearch); 166 mListener.onSearchChanged(); 167 } 168 } 169 return false; 170 } 171 172 /** 173 * Sets mSearchExpanded. Called when search icon is clicked to start search. Used to detect when 174 * the view expanded instead of onMenuItemActionExpand, because SearchView has showAsAction set 175 * to always and onMenuItemAction* methods are not called. 176 */ 177 @Override 178 public void onClick(View v) { 179 mSearchExpanded = true; 180 mView.setBackgroundColor( 181 mView.getResources().getColor(R.color.menu_search_background, null)); 182 } 183 184 @Override 185 public boolean onQueryTextSubmit(String query) { 186 currentSearch = query; 187 mView.clearFocus(); 188 if (mListener != null) { 189 mListener.onSearchQueryChanged(currentSearch); 190 mListener.onSearchChanged(); 191 } 192 return true; 193 } 194 195 @Override 196 public void onFocusChange(View v, boolean hasFocus) { 197 if (!hasFocus) { 198 if (currentSearch == null) { 199 mView.setIconified(true); 200 } else if (TextUtils.isEmpty(mView.getQuery())) { 201 cancelSearch(); 202 } 203 } 204 } 205 206 @Override 207 public boolean onQueryTextChange(String newText) { 208 return false; 209 } 210} 211