Loading packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java +39 −188 Original line number Diff line number Diff line Loading @@ -38,24 +38,21 @@ import android.provider.DocumentsContract; import android.provider.DocumentsContract.Root; import android.support.annotation.LayoutRes; import android.support.annotation.Nullable; import android.text.TextUtils; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnFocusChangeListener; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.SearchView; import android.widget.SearchView.OnQueryTextListener; import android.widget.TextView; import com.android.documentsui.RecentsProvider.ResumeColumns; import com.android.documentsui.SearchManager; import com.android.documentsui.SearchManager.SearchManagerListener; import com.android.documentsui.dirlist.DirectoryFragment; import com.android.documentsui.model.DocumentInfo; import com.android.documentsui.model.DocumentStack; Loading @@ -72,7 +69,7 @@ import java.util.Collection; import java.util.List; import java.util.concurrent.Executor; public abstract class BaseActivity extends Activity { public abstract class BaseActivity extends Activity implements SearchManagerListener { static final String EXTRA_STATE = "state"; Loading @@ -91,7 +88,7 @@ public abstract class BaseActivity extends Activity { public abstract void onDocumentsPicked(List<DocumentInfo> docs); abstract void onTaskFinished(Uri... uris); abstract void onDirectoryChanged(int anim); abstract void refreshDirectory(int anim); abstract void updateActionBar(); abstract void saveStackBlocking(); abstract State buildState(); Loading Loading @@ -121,7 +118,7 @@ public abstract class BaseActivity extends Activity { } }); mDirectoryContainer = (DirectoryContainerView) findViewById(R.id.container_directory); mSearchManager = new SearchManager(); mSearchManager = new SearchManager(this); // Base classes must update result in their onCreate. setResult(Activity.RESULT_CANCELED); Loading Loading @@ -213,7 +210,7 @@ public abstract class BaseActivity extends Activity { // Otherwise we delegate loading data from disk to a task // to ensure a responsive ui. if (mRoots.isRecentsRoot(root)) { onCurrentDirectoryChanged(ANIM_SIDE); refreshCurrentRootAndDirectory(ANIM_SIDE); } else { new PickRootTask(root, true).executeOnExecutor(getExecutorForCurrentDirectory()); } Loading Loading @@ -319,19 +316,19 @@ public abstract class BaseActivity extends Activity { void openContainerDocument(DocumentInfo doc) { checkArgument(doc.isContainer()); mState.pushDocument(doc); onCurrentDirectoryChanged(ANIM_DOWN); refreshCurrentRootAndDirectory(ANIM_DOWN); } /** * Call this when directory changes. Prior to root fragment update * the (abstract) directoryChanged method will be called. * Refreshes the content of the director and the menu/action bar. * The current directory name and selection will get updated. * @param anim */ // TODO: Refactor the usage of the method - now it is called not only when the directory // changed, but also to refresh the content of the directory while searching final void onCurrentDirectoryChanged(int anim) { final void refreshCurrentRootAndDirectory(int anim) { mSearchManager.cancelSearch(); mDirectoryContainer.setDrawDisappearingFirst(anim == ANIM_DOWN); onDirectoryChanged(anim); refreshDirectory(anim); final RootsFragment roots = RootsFragment.get(getFragmentManager()); if (roots != null) { Loading @@ -340,10 +337,28 @@ public abstract class BaseActivity extends Activity { updateActionBar(); // Prevents searchView from being recreated while searching if (!mSearchManager.isSearching()) { invalidateOptionsMenu(); } /** * Called when search results changed. * Refreshes the content of the directory. It doesn't refresh elements on the action bar. * e.g. The current directory name displayed on the action bar won't get updated. */ @Override public void onSearchChanged() { mDirectoryContainer.setDrawDisappearingFirst(false); refreshDirectory(ANIM_NONE); } /** * Called when search query changed. * Updates the state object. * @param query - New query */ @Override public void onSearchQueryChanged(String query) { mState.currentSearch = query; } final List<String> getExcludedAuthorities() { Loading Loading @@ -479,7 +494,7 @@ public abstract class BaseActivity extends Activity { mDrawer.setOpen(false); } else if (size > 1) { mState.stack.pop(); onCurrentDirectoryChanged(ANIM_UP); refreshCurrentRootAndDirectory(ANIM_UP); } else { super.onBackPressed(); } Loading @@ -490,7 +505,7 @@ public abstract class BaseActivity extends Activity { // Update the restored stack to ensure we have freshest data stack.updateDocuments(getContentResolver()); mState.setStack(stack); onCurrentDirectoryChanged(ANIM_SIDE); refreshCurrentRootAndDirectory(ANIM_SIDE); } catch (FileNotFoundException e) { Log.w(mTag, "Failed to restore stack: " + e); Loading Loading @@ -579,7 +594,7 @@ public abstract class BaseActivity extends Activity { protected void onPostExecute(Void result) { if (isDestroyed()) return; mState.restored = true; onCurrentDirectoryChanged(ANIM_NONE); refreshCurrentRootAndDirectory(ANIM_NONE); onStackRestored(mRestoredStack, mExternal); } } Loading Loading @@ -659,7 +674,7 @@ public abstract class BaseActivity extends Activity { while (mState.stack.size() > position + 1) { mState.popDocument(); } onCurrentDirectoryChanged(ANIM_UP); refreshCurrentRootAndDirectory(ANIM_UP); } @Override Loading Loading @@ -731,170 +746,6 @@ public abstract class BaseActivity extends Activity { } } /** * Facade over the various search parts in the menu. */ final class SearchManager implements SearchView.OnCloseListener, OnQueryTextListener, OnClickListener, OnFocusChangeListener, DocumentsToolBar.OnActionViewCollapsedListener { private boolean mSearchExpanded; private boolean mIgnoreNextClose; private boolean mIgnoreNextCollapse; private DocumentsToolBar mActionBar; private MenuItem mMenu; private SearchView mView; public void install(DocumentsToolBar actionBar) { assert(mActionBar == null); mActionBar = actionBar; mMenu = actionBar.getSearchMenu(); mView = (SearchView) mMenu.getActionView(); mActionBar.setOnActionViewCollapsedListener(this); mView.setOnQueryTextListener(this); mView.setOnCloseListener(this); mView.setOnSearchClickListener(this); mView.setOnQueryTextFocusChangeListener(this); } /** * @param root Info about the current directory. */ void update(RootInfo root) { if (mMenu == null) { Log.d(mTag, "update called before Search MenuItem installed."); return; } if (mState.currentSearch != null) { mMenu.expandActionView(); mView.setIconified(false); mView.clearFocus(); mView.setQuery(mState.currentSearch, false); } else { mView.clearFocus(); if (!mView.isIconified()) { mIgnoreNextClose = true; mView.setIconified(true); } if (mMenu.isActionViewExpanded()) { mIgnoreNextCollapse = true; mMenu.collapseActionView(); } } showMenu(root != null && ((root.flags & Root.FLAG_SUPPORTS_SEARCH) != 0)); } void showMenu(boolean visible) { if (mMenu == null) { Log.d(mTag, "showMenu called before Search MenuItem installed."); return; } mMenu.setVisible(visible); if (!visible) { mState.currentSearch = null; } } /** * Cancels current search operation. * @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 mView.setQuery("", false); mView.setIconified(true); return true; } return false; } boolean isSearching() { return mState.currentSearch != null; } boolean isExpanded() { return mSearchExpanded; } /** * Clears the search. * @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; } mView.setBackgroundColor( getResources().getColor(android.R.color.transparent, null)); // Refresh the directory if a search was done if(mState.currentSearch != null) { mState.currentSearch = null; onCurrentDirectoryChanged(ANIM_NONE); } return false; } /** * Sets mSearchExpanded. * Called when search icon is clicked to start search. * Used to detect when the view expanded instead of onMenuItemActionExpand, because * SearchView has showAsAction set to always and onMenuItemAction* methods are not called. */ @Override public void onClick (View v) { mSearchExpanded = true; mView.setBackgroundColor( getResources().getColor(R.color.menu_search_background, null)); } @Override public boolean onQueryTextSubmit(String query) { mState.currentSearch = query; mView.clearFocus(); onCurrentDirectoryChanged(ANIM_NONE); return true; } @Override public boolean onQueryTextChange(String newText) { return false; } @Override public void onFocusChange(View v, boolean hasFocus) { if(!hasFocus) { if(mState.currentSearch == null) { mView.setIconified(true); } else if(TextUtils.isEmpty(mView.getQuery())) { cancelSearch(); } } } @Override public void onActionViewCollapsed() { updateActionBar(); } } /** * Interface providing access to current view of documents * even when all documents are not homed to the same parent. Loading packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java +4 −4 Original line number Diff line number Diff line Loading @@ -120,7 +120,7 @@ public class DocumentsActivity extends BaseActivity { setTitle(""); new RestoreStackTask().execute(); } else { onCurrentDirectoryChanged(ANIM_NONE); refreshCurrentRootAndDirectory(ANIM_NONE); } } Loading Loading @@ -332,7 +332,7 @@ public class DocumentsActivity extends BaseActivity { } @Override void onDirectoryChanged(int anim) { void refreshDirectory(int anim) { final FragmentManager fm = getFragmentManager(); final RootInfo root = getCurrentRoot(); final DocumentInfo cwd = getCurrentDirectory(); Loading @@ -353,12 +353,12 @@ public class DocumentsActivity extends BaseActivity { mState.derivedMode = mState.userMode; } } else { if (mState.currentSearch != null) { if (mSearchManager.isSearching()) { // Ongoing search DirectoryFragment.showSearch(fm, root, mState.currentSearch, anim); } else { // Normal boring directory DirectoryFragment.showNormal(fm, root, cwd, anim); DirectoryFragment.showDirectory(fm, root, cwd, anim); } } Loading packages/DocumentsUI/src/com/android/documentsui/DownloadsActivity.java +3 −3 Original line number Diff line number Diff line Loading @@ -92,7 +92,7 @@ public class DownloadsActivity extends BaseActivity { final Uri rootUri = getIntent().getData(); new RestoreRootTask(rootUri).executeOnExecutor(getExecutorForCurrentDirectory()); } else { onCurrentDirectoryChanged(ANIM_NONE); refreshCurrentRootAndDirectory(ANIM_NONE); } } Loading Loading @@ -164,7 +164,7 @@ public class DownloadsActivity extends BaseActivity { } @Override void onDirectoryChanged(int anim) { void refreshDirectory(int anim) { final FragmentManager fm = getFragmentManager(); final RootInfo root = getCurrentRoot(); final DocumentInfo cwd = getCurrentDirectory(); Loading @@ -178,7 +178,7 @@ public class DownloadsActivity extends BaseActivity { DirectoryFragment.showSearch(fm, root, mState.currentSearch, anim); } else { // Normal boring directory DirectoryFragment.showNormal(fm, root, cwd, anim); DirectoryFragment.showDirectory(fm, root, cwd, anim); } } Loading packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java +4 −4 Original line number Diff line number Diff line Loading @@ -95,7 +95,7 @@ public class FilesActivity extends BaseActivity { if (mState.restored) { if (DEBUG) Log.d(TAG, "Stack already resolved for uri: " + intent.getData()); onCurrentDirectoryChanged(ANIM_NONE); refreshCurrentRootAndDirectory(ANIM_NONE); } else if (!mState.stack.isEmpty()) { // If a non-empty stack is present in our state it was read (presumably) // from EXTRA_STACK intent extra. In this case, we'll skip other means of Loading @@ -106,7 +106,7 @@ public class FilesActivity extends BaseActivity { // don't specify a real content target. if (DEBUG) Log.d(TAG, "Launching with non-empty stack."); checkState(uri == null || LauncherActivity.isLaunchUri(uri)); onCurrentDirectoryChanged(ANIM_NONE); refreshCurrentRootAndDirectory(ANIM_NONE); } else if (DocumentsContract.isRootUri(this, uri)) { if (DEBUG) Log.d(TAG, "Launching with root URI."); // If we've got a specific root to display, restore that root using a dedicated Loading Loading @@ -288,7 +288,7 @@ public class FilesActivity extends BaseActivity { } @Override void onDirectoryChanged(int anim) { void refreshDirectory(int anim) { final FragmentManager fm = getFragmentManager(); final RootInfo root = getCurrentRoot(); final DocumentInfo cwd = getCurrentDirectory(); Loading @@ -307,7 +307,7 @@ public class FilesActivity extends BaseActivity { DirectoryFragment.showSearch(fm, root, mState.currentSearch, anim); } else { // Normal boring directory DirectoryFragment.showNormal(fm, root, cwd, anim); DirectoryFragment.showDirectory(fm, root, cwd, anim); } } } Loading packages/DocumentsUI/src/com/android/documentsui/SearchManager.java 0 → 100644 +210 −0 Original line number Diff line number Diff line /* * 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 android.provider.DocumentsContract.Root; import android.text.TextUtils; import android.util.Log; import android.view.MenuItem; 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 SearchManager implements SearchView.OnCloseListener, OnQueryTextListener, OnClickListener, OnFocusChangeListener { public interface SearchManagerListener { void onSearchChanged(); void onSearchQueryChanged(String query); } public static final String TAG = "SearchManger"; private SearchManagerListener mListener; private String currentSearch; private boolean mSearchExpanded; private boolean mIgnoreNextClose; private DocumentsToolBar mActionBar; private MenuItem mMenu; private SearchView mView; public SearchManager(SearchManagerListener listener) { mListener = listener; } public void setSearchMangerListener(SearchManagerListener listener) { mListener = listener; } public void install(DocumentsToolBar actionBar) { assert (mActionBar == null); mActionBar = actionBar; mMenu = actionBar.getSearchMenu(); mView = (SearchView) mMenu.getActionView(); mView.setOnQueryTextListener(this); mView.setOnCloseListener(this); mView.setOnSearchClickListener(this); mView.setOnQueryTextFocusChangeListener(this); } /** * @param root Info about the current directory. */ void update(RootInfo root) { if (mMenu == null) { Log.d(TAG, "update called before Search MenuItem installed."); return; } if (currentSearch != null) { mMenu.expandActionView(); mView.setIconified(false); mView.clearFocus(); mView.setQuery(currentSearch, false); } else { mView.clearFocus(); if (!mView.isIconified()) { mIgnoreNextClose = true; mView.setIconified(true); } if (mMenu.isActionViewExpanded()) { mMenu.collapseActionView(); } } showMenu(root != null && ((root.flags & Root.FLAG_SUPPORTS_SEARCH) != 0)); } void showMenu(boolean visible) { if (mMenu == null) { Log.d(TAG, "showMenu called before Search MenuItem installed."); return; } mMenu.setVisible(visible); if (!visible) { currentSearch = null; if (mListener != null) { mListener.onSearchQueryChanged(currentSearch); } } } /** * 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 mView.setQuery("", false); // Causes calling onClose(). onClose() is triggering directory content update. mView.setIconified(true); return true; } return false; } boolean isSearching() { return currentSearch != null; } boolean isExpanded() { return mSearchExpanded; } /** * Clears the search. Clears the SearchView background color. 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; } mView.setBackgroundColor( mView.getResources().getColor(android.R.color.transparent, null)); // Refresh the directory if a search was done if (currentSearch != null) { currentSearch = null; if (mListener != null) { mListener.onSearchQueryChanged(currentSearch); mListener.onSearchChanged(); } } return false; } /** * Sets mSearchExpanded. Called when search icon is clicked to start search. Used to detect when * the view expanded instead of onMenuItemActionExpand, because SearchView has showAsAction set * to always and onMenuItemAction* methods are not called. */ @Override public void onClick(View v) { mSearchExpanded = true; mView.setBackgroundColor( mView.getResources().getColor(R.color.menu_search_background, null)); } @Override public boolean onQueryTextSubmit(String query) { currentSearch = query; mView.clearFocus(); if (mListener != null) { mListener.onSearchQueryChanged(currentSearch); mListener.onSearchChanged(); } return true; } @Override public void onFocusChange(View v, boolean hasFocus) { if (!hasFocus) { if (currentSearch == null) { mView.setIconified(true); } else if (TextUtils.isEmpty(mView.getQuery())) { cancelSearch(); } } } @Override public boolean onQueryTextChange(String newText) { return false; } } Loading
packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java +39 −188 Original line number Diff line number Diff line Loading @@ -38,24 +38,21 @@ import android.provider.DocumentsContract; import android.provider.DocumentsContract.Root; import android.support.annotation.LayoutRes; import android.support.annotation.Nullable; import android.text.TextUtils; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnFocusChangeListener; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.SearchView; import android.widget.SearchView.OnQueryTextListener; import android.widget.TextView; import com.android.documentsui.RecentsProvider.ResumeColumns; import com.android.documentsui.SearchManager; import com.android.documentsui.SearchManager.SearchManagerListener; import com.android.documentsui.dirlist.DirectoryFragment; import com.android.documentsui.model.DocumentInfo; import com.android.documentsui.model.DocumentStack; Loading @@ -72,7 +69,7 @@ import java.util.Collection; import java.util.List; import java.util.concurrent.Executor; public abstract class BaseActivity extends Activity { public abstract class BaseActivity extends Activity implements SearchManagerListener { static final String EXTRA_STATE = "state"; Loading @@ -91,7 +88,7 @@ public abstract class BaseActivity extends Activity { public abstract void onDocumentsPicked(List<DocumentInfo> docs); abstract void onTaskFinished(Uri... uris); abstract void onDirectoryChanged(int anim); abstract void refreshDirectory(int anim); abstract void updateActionBar(); abstract void saveStackBlocking(); abstract State buildState(); Loading Loading @@ -121,7 +118,7 @@ public abstract class BaseActivity extends Activity { } }); mDirectoryContainer = (DirectoryContainerView) findViewById(R.id.container_directory); mSearchManager = new SearchManager(); mSearchManager = new SearchManager(this); // Base classes must update result in their onCreate. setResult(Activity.RESULT_CANCELED); Loading Loading @@ -213,7 +210,7 @@ public abstract class BaseActivity extends Activity { // Otherwise we delegate loading data from disk to a task // to ensure a responsive ui. if (mRoots.isRecentsRoot(root)) { onCurrentDirectoryChanged(ANIM_SIDE); refreshCurrentRootAndDirectory(ANIM_SIDE); } else { new PickRootTask(root, true).executeOnExecutor(getExecutorForCurrentDirectory()); } Loading Loading @@ -319,19 +316,19 @@ public abstract class BaseActivity extends Activity { void openContainerDocument(DocumentInfo doc) { checkArgument(doc.isContainer()); mState.pushDocument(doc); onCurrentDirectoryChanged(ANIM_DOWN); refreshCurrentRootAndDirectory(ANIM_DOWN); } /** * Call this when directory changes. Prior to root fragment update * the (abstract) directoryChanged method will be called. * Refreshes the content of the director and the menu/action bar. * The current directory name and selection will get updated. * @param anim */ // TODO: Refactor the usage of the method - now it is called not only when the directory // changed, but also to refresh the content of the directory while searching final void onCurrentDirectoryChanged(int anim) { final void refreshCurrentRootAndDirectory(int anim) { mSearchManager.cancelSearch(); mDirectoryContainer.setDrawDisappearingFirst(anim == ANIM_DOWN); onDirectoryChanged(anim); refreshDirectory(anim); final RootsFragment roots = RootsFragment.get(getFragmentManager()); if (roots != null) { Loading @@ -340,10 +337,28 @@ public abstract class BaseActivity extends Activity { updateActionBar(); // Prevents searchView from being recreated while searching if (!mSearchManager.isSearching()) { invalidateOptionsMenu(); } /** * Called when search results changed. * Refreshes the content of the directory. It doesn't refresh elements on the action bar. * e.g. The current directory name displayed on the action bar won't get updated. */ @Override public void onSearchChanged() { mDirectoryContainer.setDrawDisappearingFirst(false); refreshDirectory(ANIM_NONE); } /** * Called when search query changed. * Updates the state object. * @param query - New query */ @Override public void onSearchQueryChanged(String query) { mState.currentSearch = query; } final List<String> getExcludedAuthorities() { Loading Loading @@ -479,7 +494,7 @@ public abstract class BaseActivity extends Activity { mDrawer.setOpen(false); } else if (size > 1) { mState.stack.pop(); onCurrentDirectoryChanged(ANIM_UP); refreshCurrentRootAndDirectory(ANIM_UP); } else { super.onBackPressed(); } Loading @@ -490,7 +505,7 @@ public abstract class BaseActivity extends Activity { // Update the restored stack to ensure we have freshest data stack.updateDocuments(getContentResolver()); mState.setStack(stack); onCurrentDirectoryChanged(ANIM_SIDE); refreshCurrentRootAndDirectory(ANIM_SIDE); } catch (FileNotFoundException e) { Log.w(mTag, "Failed to restore stack: " + e); Loading Loading @@ -579,7 +594,7 @@ public abstract class BaseActivity extends Activity { protected void onPostExecute(Void result) { if (isDestroyed()) return; mState.restored = true; onCurrentDirectoryChanged(ANIM_NONE); refreshCurrentRootAndDirectory(ANIM_NONE); onStackRestored(mRestoredStack, mExternal); } } Loading Loading @@ -659,7 +674,7 @@ public abstract class BaseActivity extends Activity { while (mState.stack.size() > position + 1) { mState.popDocument(); } onCurrentDirectoryChanged(ANIM_UP); refreshCurrentRootAndDirectory(ANIM_UP); } @Override Loading Loading @@ -731,170 +746,6 @@ public abstract class BaseActivity extends Activity { } } /** * Facade over the various search parts in the menu. */ final class SearchManager implements SearchView.OnCloseListener, OnQueryTextListener, OnClickListener, OnFocusChangeListener, DocumentsToolBar.OnActionViewCollapsedListener { private boolean mSearchExpanded; private boolean mIgnoreNextClose; private boolean mIgnoreNextCollapse; private DocumentsToolBar mActionBar; private MenuItem mMenu; private SearchView mView; public void install(DocumentsToolBar actionBar) { assert(mActionBar == null); mActionBar = actionBar; mMenu = actionBar.getSearchMenu(); mView = (SearchView) mMenu.getActionView(); mActionBar.setOnActionViewCollapsedListener(this); mView.setOnQueryTextListener(this); mView.setOnCloseListener(this); mView.setOnSearchClickListener(this); mView.setOnQueryTextFocusChangeListener(this); } /** * @param root Info about the current directory. */ void update(RootInfo root) { if (mMenu == null) { Log.d(mTag, "update called before Search MenuItem installed."); return; } if (mState.currentSearch != null) { mMenu.expandActionView(); mView.setIconified(false); mView.clearFocus(); mView.setQuery(mState.currentSearch, false); } else { mView.clearFocus(); if (!mView.isIconified()) { mIgnoreNextClose = true; mView.setIconified(true); } if (mMenu.isActionViewExpanded()) { mIgnoreNextCollapse = true; mMenu.collapseActionView(); } } showMenu(root != null && ((root.flags & Root.FLAG_SUPPORTS_SEARCH) != 0)); } void showMenu(boolean visible) { if (mMenu == null) { Log.d(mTag, "showMenu called before Search MenuItem installed."); return; } mMenu.setVisible(visible); if (!visible) { mState.currentSearch = null; } } /** * Cancels current search operation. * @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 mView.setQuery("", false); mView.setIconified(true); return true; } return false; } boolean isSearching() { return mState.currentSearch != null; } boolean isExpanded() { return mSearchExpanded; } /** * Clears the search. * @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; } mView.setBackgroundColor( getResources().getColor(android.R.color.transparent, null)); // Refresh the directory if a search was done if(mState.currentSearch != null) { mState.currentSearch = null; onCurrentDirectoryChanged(ANIM_NONE); } return false; } /** * Sets mSearchExpanded. * Called when search icon is clicked to start search. * Used to detect when the view expanded instead of onMenuItemActionExpand, because * SearchView has showAsAction set to always and onMenuItemAction* methods are not called. */ @Override public void onClick (View v) { mSearchExpanded = true; mView.setBackgroundColor( getResources().getColor(R.color.menu_search_background, null)); } @Override public boolean onQueryTextSubmit(String query) { mState.currentSearch = query; mView.clearFocus(); onCurrentDirectoryChanged(ANIM_NONE); return true; } @Override public boolean onQueryTextChange(String newText) { return false; } @Override public void onFocusChange(View v, boolean hasFocus) { if(!hasFocus) { if(mState.currentSearch == null) { mView.setIconified(true); } else if(TextUtils.isEmpty(mView.getQuery())) { cancelSearch(); } } } @Override public void onActionViewCollapsed() { updateActionBar(); } } /** * Interface providing access to current view of documents * even when all documents are not homed to the same parent. Loading
packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java +4 −4 Original line number Diff line number Diff line Loading @@ -120,7 +120,7 @@ public class DocumentsActivity extends BaseActivity { setTitle(""); new RestoreStackTask().execute(); } else { onCurrentDirectoryChanged(ANIM_NONE); refreshCurrentRootAndDirectory(ANIM_NONE); } } Loading Loading @@ -332,7 +332,7 @@ public class DocumentsActivity extends BaseActivity { } @Override void onDirectoryChanged(int anim) { void refreshDirectory(int anim) { final FragmentManager fm = getFragmentManager(); final RootInfo root = getCurrentRoot(); final DocumentInfo cwd = getCurrentDirectory(); Loading @@ -353,12 +353,12 @@ public class DocumentsActivity extends BaseActivity { mState.derivedMode = mState.userMode; } } else { if (mState.currentSearch != null) { if (mSearchManager.isSearching()) { // Ongoing search DirectoryFragment.showSearch(fm, root, mState.currentSearch, anim); } else { // Normal boring directory DirectoryFragment.showNormal(fm, root, cwd, anim); DirectoryFragment.showDirectory(fm, root, cwd, anim); } } Loading
packages/DocumentsUI/src/com/android/documentsui/DownloadsActivity.java +3 −3 Original line number Diff line number Diff line Loading @@ -92,7 +92,7 @@ public class DownloadsActivity extends BaseActivity { final Uri rootUri = getIntent().getData(); new RestoreRootTask(rootUri).executeOnExecutor(getExecutorForCurrentDirectory()); } else { onCurrentDirectoryChanged(ANIM_NONE); refreshCurrentRootAndDirectory(ANIM_NONE); } } Loading Loading @@ -164,7 +164,7 @@ public class DownloadsActivity extends BaseActivity { } @Override void onDirectoryChanged(int anim) { void refreshDirectory(int anim) { final FragmentManager fm = getFragmentManager(); final RootInfo root = getCurrentRoot(); final DocumentInfo cwd = getCurrentDirectory(); Loading @@ -178,7 +178,7 @@ public class DownloadsActivity extends BaseActivity { DirectoryFragment.showSearch(fm, root, mState.currentSearch, anim); } else { // Normal boring directory DirectoryFragment.showNormal(fm, root, cwd, anim); DirectoryFragment.showDirectory(fm, root, cwd, anim); } } Loading
packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java +4 −4 Original line number Diff line number Diff line Loading @@ -95,7 +95,7 @@ public class FilesActivity extends BaseActivity { if (mState.restored) { if (DEBUG) Log.d(TAG, "Stack already resolved for uri: " + intent.getData()); onCurrentDirectoryChanged(ANIM_NONE); refreshCurrentRootAndDirectory(ANIM_NONE); } else if (!mState.stack.isEmpty()) { // If a non-empty stack is present in our state it was read (presumably) // from EXTRA_STACK intent extra. In this case, we'll skip other means of Loading @@ -106,7 +106,7 @@ public class FilesActivity extends BaseActivity { // don't specify a real content target. if (DEBUG) Log.d(TAG, "Launching with non-empty stack."); checkState(uri == null || LauncherActivity.isLaunchUri(uri)); onCurrentDirectoryChanged(ANIM_NONE); refreshCurrentRootAndDirectory(ANIM_NONE); } else if (DocumentsContract.isRootUri(this, uri)) { if (DEBUG) Log.d(TAG, "Launching with root URI."); // If we've got a specific root to display, restore that root using a dedicated Loading Loading @@ -288,7 +288,7 @@ public class FilesActivity extends BaseActivity { } @Override void onDirectoryChanged(int anim) { void refreshDirectory(int anim) { final FragmentManager fm = getFragmentManager(); final RootInfo root = getCurrentRoot(); final DocumentInfo cwd = getCurrentDirectory(); Loading @@ -307,7 +307,7 @@ public class FilesActivity extends BaseActivity { DirectoryFragment.showSearch(fm, root, mState.currentSearch, anim); } else { // Normal boring directory DirectoryFragment.showNormal(fm, root, cwd, anim); DirectoryFragment.showDirectory(fm, root, cwd, anim); } } } Loading
packages/DocumentsUI/src/com/android/documentsui/SearchManager.java 0 → 100644 +210 −0 Original line number Diff line number Diff line /* * 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 android.provider.DocumentsContract.Root; import android.text.TextUtils; import android.util.Log; import android.view.MenuItem; 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 SearchManager implements SearchView.OnCloseListener, OnQueryTextListener, OnClickListener, OnFocusChangeListener { public interface SearchManagerListener { void onSearchChanged(); void onSearchQueryChanged(String query); } public static final String TAG = "SearchManger"; private SearchManagerListener mListener; private String currentSearch; private boolean mSearchExpanded; private boolean mIgnoreNextClose; private DocumentsToolBar mActionBar; private MenuItem mMenu; private SearchView mView; public SearchManager(SearchManagerListener listener) { mListener = listener; } public void setSearchMangerListener(SearchManagerListener listener) { mListener = listener; } public void install(DocumentsToolBar actionBar) { assert (mActionBar == null); mActionBar = actionBar; mMenu = actionBar.getSearchMenu(); mView = (SearchView) mMenu.getActionView(); mView.setOnQueryTextListener(this); mView.setOnCloseListener(this); mView.setOnSearchClickListener(this); mView.setOnQueryTextFocusChangeListener(this); } /** * @param root Info about the current directory. */ void update(RootInfo root) { if (mMenu == null) { Log.d(TAG, "update called before Search MenuItem installed."); return; } if (currentSearch != null) { mMenu.expandActionView(); mView.setIconified(false); mView.clearFocus(); mView.setQuery(currentSearch, false); } else { mView.clearFocus(); if (!mView.isIconified()) { mIgnoreNextClose = true; mView.setIconified(true); } if (mMenu.isActionViewExpanded()) { mMenu.collapseActionView(); } } showMenu(root != null && ((root.flags & Root.FLAG_SUPPORTS_SEARCH) != 0)); } void showMenu(boolean visible) { if (mMenu == null) { Log.d(TAG, "showMenu called before Search MenuItem installed."); return; } mMenu.setVisible(visible); if (!visible) { currentSearch = null; if (mListener != null) { mListener.onSearchQueryChanged(currentSearch); } } } /** * 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 mView.setQuery("", false); // Causes calling onClose(). onClose() is triggering directory content update. mView.setIconified(true); return true; } return false; } boolean isSearching() { return currentSearch != null; } boolean isExpanded() { return mSearchExpanded; } /** * Clears the search. Clears the SearchView background color. 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; } mView.setBackgroundColor( mView.getResources().getColor(android.R.color.transparent, null)); // Refresh the directory if a search was done if (currentSearch != null) { currentSearch = null; if (mListener != null) { mListener.onSearchQueryChanged(currentSearch); mListener.onSearchChanged(); } } return false; } /** * Sets mSearchExpanded. Called when search icon is clicked to start search. Used to detect when * the view expanded instead of onMenuItemActionExpand, because SearchView has showAsAction set * to always and onMenuItemAction* methods are not called. */ @Override public void onClick(View v) { mSearchExpanded = true; mView.setBackgroundColor( mView.getResources().getColor(R.color.menu_search_background, null)); } @Override public boolean onQueryTextSubmit(String query) { currentSearch = query; mView.clearFocus(); if (mListener != null) { mListener.onSearchQueryChanged(currentSearch); mListener.onSearchChanged(); } return true; } @Override public void onFocusChange(View v, boolean hasFocus) { if (!hasFocus) { if (currentSearch == null) { mView.setIconified(true); } else if (TextUtils.isEmpty(mView.getQuery())) { cancelSearch(); } } } @Override public boolean onQueryTextChange(String newText) { return false; } }