297 lines
8.6 KiB
Java
297 lines
8.6 KiB
Java
/*
|
|
* Copyright (C) 2013 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package com.android.documentsui;
|
|
|
|
import static com.android.documentsui.Shared.DEBUG;
|
|
|
|
import android.annotation.Nullable;
|
|
import android.os.Bundle;
|
|
import android.provider.DocumentsContract.Root;
|
|
import android.text.TextUtils;
|
|
import android.util.Log;
|
|
import android.view.Menu;
|
|
import android.view.MenuItem;
|
|
import android.view.MenuItem.OnActionExpandListener;
|
|
import android.view.View;
|
|
import android.view.View.OnClickListener;
|
|
import android.view.View.OnFocusChangeListener;
|
|
import android.widget.SearchView;
|
|
import android.widget.SearchView.OnQueryTextListener;
|
|
|
|
import com.android.documentsui.model.RootInfo;
|
|
|
|
/**
|
|
* Manages searching UI behavior.
|
|
*/
|
|
final class SearchViewManager implements
|
|
SearchView.OnCloseListener, OnQueryTextListener, OnClickListener, OnFocusChangeListener,
|
|
OnActionExpandListener {
|
|
|
|
public interface SearchManagerListener {
|
|
void onSearchChanged(@Nullable String query);
|
|
void onSearchFinished();
|
|
}
|
|
|
|
public static final String TAG = "SearchManger";
|
|
|
|
private SearchManagerListener mListener;
|
|
private boolean mSearchExpanded;
|
|
private String mCurrentSearch;
|
|
private boolean mIgnoreNextClose;
|
|
private boolean mFullBar;
|
|
|
|
private DocumentsToolbar mActionBar;
|
|
private MenuItem mMenuItem;
|
|
private SearchView mSearchView;
|
|
|
|
public SearchViewManager(SearchManagerListener listener, @Nullable Bundle savedState) {
|
|
mListener = listener;
|
|
mCurrentSearch = savedState != null ? savedState.getString(Shared.EXTRA_QUERY) : null;
|
|
}
|
|
|
|
public void setSearchMangerListener(SearchManagerListener listener) {
|
|
mListener = listener;
|
|
}
|
|
|
|
public void install(DocumentsToolbar actionBar, boolean isFullBarSearch) {
|
|
mActionBar = actionBar;
|
|
mMenuItem = actionBar.getSearchMenu();
|
|
mSearchView = (SearchView) mMenuItem.getActionView();
|
|
|
|
mSearchView.setOnQueryTextListener(this);
|
|
mSearchView.setOnCloseListener(this);
|
|
mSearchView.setOnSearchClickListener(this);
|
|
mSearchView.setOnQueryTextFocusChangeListener(this);
|
|
|
|
mFullBar = isFullBarSearch;
|
|
if (mFullBar) {
|
|
mMenuItem.setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW
|
|
| MenuItem.SHOW_AS_ACTION_ALWAYS);
|
|
mMenuItem.setOnActionExpandListener(this);
|
|
}
|
|
|
|
restoreSearch();
|
|
}
|
|
|
|
/**
|
|
* Used to hide menu icons, when the search is being restored. Needed because search restoration
|
|
* is done before onPrepareOptionsMenu(Menu menu) that is overriding the icons visibility.
|
|
*/
|
|
public void updateMenu() {
|
|
if (isSearching() && mFullBar) {
|
|
Menu menu = mActionBar.getMenu();
|
|
menu.setGroupVisible(R.id.group_hide_when_searching, false);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param root Info about the current directory.
|
|
*/
|
|
void update(RootInfo root) {
|
|
if (mMenuItem == null) {
|
|
if (DEBUG) Log.d(TAG, "update called before Search MenuItem installed.");
|
|
return;
|
|
}
|
|
|
|
if (mCurrentSearch != null) {
|
|
mMenuItem.expandActionView();
|
|
|
|
mSearchView.setIconified(false);
|
|
mSearchView.clearFocus();
|
|
mSearchView.setQuery(mCurrentSearch, false);
|
|
} else {
|
|
mSearchView.clearFocus();
|
|
if (!mSearchView.isIconified()) {
|
|
mIgnoreNextClose = true;
|
|
mSearchView.setIconified(true);
|
|
}
|
|
|
|
if (mMenuItem.isActionViewExpanded()) {
|
|
mMenuItem.collapseActionView();
|
|
}
|
|
}
|
|
|
|
showMenu(root != null
|
|
&& ((root.flags & Root.FLAG_SUPPORTS_SEARCH) != 0));
|
|
}
|
|
|
|
void showMenu(boolean visible) {
|
|
if (mMenuItem == null) {
|
|
if (DEBUG) Log.d(TAG, "showMenu called before Search MenuItem installed.");
|
|
return;
|
|
}
|
|
|
|
if (!visible) {
|
|
mCurrentSearch = null;
|
|
}
|
|
|
|
mMenuItem.setVisible(visible);
|
|
}
|
|
|
|
/**
|
|
* Cancels current search operation. Triggers clearing and collapsing the SearchView.
|
|
*
|
|
* @return True if it cancels search. False if it does not operate search currently.
|
|
*/
|
|
boolean cancelSearch() {
|
|
if (isExpanded() || isSearching()) {
|
|
// If the query string is not empty search view won't get iconified
|
|
mSearchView.setQuery("", false);
|
|
|
|
if (mFullBar) {
|
|
onClose();
|
|
} else {
|
|
// Causes calling onClose(). onClose() is triggering directory content update.
|
|
mSearchView.setIconified(true);
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Sets search view into the searching state. Used to restore state after device orientation
|
|
* change.
|
|
*/
|
|
private void restoreSearch() {
|
|
if (isSearching()) {
|
|
if(mFullBar) {
|
|
mMenuItem.expandActionView();
|
|
} else {
|
|
mSearchView.setIconified(false);
|
|
}
|
|
onSearchExpanded();
|
|
mSearchView.setQuery(mCurrentSearch, false);
|
|
mSearchView.clearFocus();
|
|
}
|
|
}
|
|
|
|
private void onSearchExpanded() {
|
|
mSearchExpanded = true;
|
|
if(mFullBar) {
|
|
Menu menu = mActionBar.getMenu();
|
|
menu.setGroupVisible(R.id.group_hide_when_searching, false);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Clears the search. Triggers refreshing of the directory content.
|
|
* @return True if the default behavior of clearing/dismissing SearchView should be overridden.
|
|
* False otherwise.
|
|
*/
|
|
@Override
|
|
public boolean onClose() {
|
|
mSearchExpanded = false;
|
|
if (mIgnoreNextClose) {
|
|
mIgnoreNextClose = false;
|
|
return false;
|
|
}
|
|
|
|
// Refresh the directory if a search was done
|
|
if (mCurrentSearch != null) {
|
|
mCurrentSearch = null;
|
|
if (mListener != null) {
|
|
mListener.onSearchChanged(mCurrentSearch);
|
|
}
|
|
}
|
|
|
|
if(mFullBar) {
|
|
mMenuItem.collapseActionView();
|
|
}
|
|
mListener.onSearchFinished();
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Called when owning activity is saving state to be used to restore state during creation.
|
|
* @param state Bundle to save state too
|
|
*/
|
|
public void onSaveInstanceState(Bundle state) {
|
|
state.putString(Shared.EXTRA_QUERY, mCurrentSearch);
|
|
}
|
|
|
|
/**
|
|
* Sets mSearchExpanded. Called when search icon is clicked to start search for both search view
|
|
* modes.
|
|
*/
|
|
@Override
|
|
public void onClick(View v) {
|
|
onSearchExpanded();
|
|
}
|
|
|
|
@Override
|
|
public boolean onQueryTextSubmit(String query) {
|
|
mCurrentSearch = query;
|
|
mSearchView.clearFocus();
|
|
if (mListener != null) {
|
|
mListener.onSearchChanged(mCurrentSearch);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Used to detect and handle back button pressed event when search is expanded.
|
|
*/
|
|
@Override
|
|
public void onFocusChange(View v, boolean hasFocus) {
|
|
if (!hasFocus) {
|
|
if (mCurrentSearch == null) {
|
|
mSearchView.setIconified(true);
|
|
} else if (TextUtils.isEmpty(mSearchView.getQuery())) {
|
|
cancelSearch();
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean onQueryTextChange(String newText) {
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public boolean onMenuItemActionCollapse(MenuItem item) {
|
|
Menu menu = mActionBar.getMenu();
|
|
menu.setGroupVisible(R.id.group_hide_when_searching, true);
|
|
|
|
// Handles case when search view is collapsed by using the arrow on the left of the bar
|
|
if (isExpanded() || isSearching()) {
|
|
cancelSearch();
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public boolean onMenuItemActionExpand(MenuItem item) {
|
|
return true;
|
|
}
|
|
|
|
String getCurrentSearch() {
|
|
return mCurrentSearch;
|
|
}
|
|
|
|
boolean isSearching() {
|
|
return mCurrentSearch != null;
|
|
}
|
|
|
|
boolean isExpanded() {
|
|
return mSearchExpanded;
|
|
}
|
|
|
|
}
|