Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8788dadd authored by Aga Wronska's avatar Aga Wronska
Browse files

Refactor SearchManager:

- Move SearchManager out of BaseActivity.
- Refactor usage of onCurrentDirectoryChanged(int anim).
- Cancel search when directory changes.
- Enable testing for cancelling search when directory changes.
- Avoid recreating action bar when only the content of the directory is
  changed.

BUG=26495573

Change-Id: I1400090fcb529ad3905018d1640fdb7416542989
parent 4654b522
Loading
Loading
Loading
Loading
+39 −188
Original line number Original line Diff line number Diff line
@@ -38,24 +38,21 @@ import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Root;
import android.provider.DocumentsContract.Root;
import android.support.annotation.LayoutRes;
import android.support.annotation.LayoutRes;
import android.support.annotation.Nullable;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.Log;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MenuItem;
import android.view.View;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnFocusChangeListener;
import android.view.ViewGroup;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.BaseAdapter;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ImageView;
import android.widget.SearchView;
import android.widget.SearchView.OnQueryTextListener;
import android.widget.TextView;
import android.widget.TextView;


import com.android.documentsui.RecentsProvider.ResumeColumns;
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.dirlist.DirectoryFragment;
import com.android.documentsui.model.DocumentInfo;
import com.android.documentsui.model.DocumentInfo;
import com.android.documentsui.model.DocumentStack;
import com.android.documentsui.model.DocumentStack;
@@ -72,7 +69,7 @@ import java.util.Collection;
import java.util.List;
import java.util.List;
import java.util.concurrent.Executor;
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";
    static final String EXTRA_STATE = "state";


@@ -91,7 +88,7 @@ public abstract class BaseActivity extends Activity {
    public abstract void onDocumentsPicked(List<DocumentInfo> docs);
    public abstract void onDocumentsPicked(List<DocumentInfo> docs);


    abstract void onTaskFinished(Uri... uris);
    abstract void onTaskFinished(Uri... uris);
    abstract void onDirectoryChanged(int anim);
    abstract void refreshDirectory(int anim);
    abstract void updateActionBar();
    abstract void updateActionBar();
    abstract void saveStackBlocking();
    abstract void saveStackBlocking();
    abstract State buildState();
    abstract State buildState();
@@ -121,7 +118,7 @@ public abstract class BaseActivity extends Activity {
                    }
                    }
                });
                });
        mDirectoryContainer = (DirectoryContainerView) findViewById(R.id.container_directory);
        mDirectoryContainer = (DirectoryContainerView) findViewById(R.id.container_directory);
        mSearchManager = new SearchManager();
        mSearchManager = new SearchManager(this);


        // Base classes must update result in their onCreate.
        // Base classes must update result in their onCreate.
        setResult(Activity.RESULT_CANCELED);
        setResult(Activity.RESULT_CANCELED);
@@ -213,7 +210,7 @@ public abstract class BaseActivity extends Activity {
        // Otherwise we delegate loading data from disk to a task
        // Otherwise we delegate loading data from disk to a task
        // to ensure a responsive ui.
        // to ensure a responsive ui.
        if (mRoots.isRecentsRoot(root)) {
        if (mRoots.isRecentsRoot(root)) {
            onCurrentDirectoryChanged(ANIM_SIDE);
            refreshCurrentRootAndDirectory(ANIM_SIDE);
        } else {
        } else {
            new PickRootTask(root, true).executeOnExecutor(getExecutorForCurrentDirectory());
            new PickRootTask(root, true).executeOnExecutor(getExecutorForCurrentDirectory());
        }
        }
@@ -319,19 +316,19 @@ public abstract class BaseActivity extends Activity {
    void openContainerDocument(DocumentInfo doc) {
    void openContainerDocument(DocumentInfo doc) {
        checkArgument(doc.isContainer());
        checkArgument(doc.isContainer());
        mState.pushDocument(doc);
        mState.pushDocument(doc);
        onCurrentDirectoryChanged(ANIM_DOWN);
        refreshCurrentRootAndDirectory(ANIM_DOWN);
    }
    }


    /**
    /**
     * Call this when directory changes. Prior to root fragment update
     * Refreshes the content of the director and the menu/action bar.
     * the (abstract) directoryChanged method will be called.
     * The current directory name and selection will get updated.
     * @param anim
     * @param anim
     */
     */
    // TODO: Refactor the usage of the method - now it is called not only when the directory
    final void refreshCurrentRootAndDirectory(int anim) {
    // changed, but also to refresh the content of the directory while searching
        mSearchManager.cancelSearch();
    final void onCurrentDirectoryChanged(int anim) {

        mDirectoryContainer.setDrawDisappearingFirst(anim == ANIM_DOWN);
        mDirectoryContainer.setDrawDisappearingFirst(anim == ANIM_DOWN);
        onDirectoryChanged(anim);
        refreshDirectory(anim);


        final RootsFragment roots = RootsFragment.get(getFragmentManager());
        final RootsFragment roots = RootsFragment.get(getFragmentManager());
        if (roots != null) {
        if (roots != null) {
@@ -340,10 +337,28 @@ public abstract class BaseActivity extends Activity {


        updateActionBar();
        updateActionBar();


        // Prevents searchView from being recreated while searching
        if (!mSearchManager.isSearching()) {
        invalidateOptionsMenu();
        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() {
    final List<String> getExcludedAuthorities() {
@@ -479,7 +494,7 @@ public abstract class BaseActivity extends Activity {
            mDrawer.setOpen(false);
            mDrawer.setOpen(false);
        } else if (size > 1) {
        } else if (size > 1) {
            mState.stack.pop();
            mState.stack.pop();
            onCurrentDirectoryChanged(ANIM_UP);
            refreshCurrentRootAndDirectory(ANIM_UP);
        } else {
        } else {
            super.onBackPressed();
            super.onBackPressed();
        }
        }
@@ -490,7 +505,7 @@ public abstract class BaseActivity extends Activity {
            // Update the restored stack to ensure we have freshest data
            // Update the restored stack to ensure we have freshest data
            stack.updateDocuments(getContentResolver());
            stack.updateDocuments(getContentResolver());
            mState.setStack(stack);
            mState.setStack(stack);
            onCurrentDirectoryChanged(ANIM_SIDE);
            refreshCurrentRootAndDirectory(ANIM_SIDE);


        } catch (FileNotFoundException e) {
        } catch (FileNotFoundException e) {
            Log.w(mTag, "Failed to restore stack: " + e);
            Log.w(mTag, "Failed to restore stack: " + e);
@@ -579,7 +594,7 @@ public abstract class BaseActivity extends Activity {
        protected void onPostExecute(Void result) {
        protected void onPostExecute(Void result) {
            if (isDestroyed()) return;
            if (isDestroyed()) return;
            mState.restored = true;
            mState.restored = true;
            onCurrentDirectoryChanged(ANIM_NONE);
            refreshCurrentRootAndDirectory(ANIM_NONE);
            onStackRestored(mRestoredStack, mExternal);
            onStackRestored(mRestoredStack, mExternal);
        }
        }
    }
    }
@@ -659,7 +674,7 @@ public abstract class BaseActivity extends Activity {
            while (mState.stack.size() > position + 1) {
            while (mState.stack.size() > position + 1) {
                mState.popDocument();
                mState.popDocument();
            }
            }
            onCurrentDirectoryChanged(ANIM_UP);
            refreshCurrentRootAndDirectory(ANIM_UP);
        }
        }


        @Override
        @Override
@@ -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
     * Interface providing access to current view of documents
     * even when all documents are not homed to the same parent.
     * even when all documents are not homed to the same parent.
+4 −4
Original line number Original line Diff line number Diff line
@@ -120,7 +120,7 @@ public class DocumentsActivity extends BaseActivity {
            setTitle("");
            setTitle("");
            new RestoreStackTask().execute();
            new RestoreStackTask().execute();
        } else {
        } else {
            onCurrentDirectoryChanged(ANIM_NONE);
            refreshCurrentRootAndDirectory(ANIM_NONE);
        }
        }
    }
    }


@@ -332,7 +332,7 @@ public class DocumentsActivity extends BaseActivity {
    }
    }


    @Override
    @Override
    void onDirectoryChanged(int anim) {
    void refreshDirectory(int anim) {
        final FragmentManager fm = getFragmentManager();
        final FragmentManager fm = getFragmentManager();
        final RootInfo root = getCurrentRoot();
        final RootInfo root = getCurrentRoot();
        final DocumentInfo cwd = getCurrentDirectory();
        final DocumentInfo cwd = getCurrentDirectory();
@@ -353,12 +353,12 @@ public class DocumentsActivity extends BaseActivity {
                mState.derivedMode = mState.userMode;
                mState.derivedMode = mState.userMode;
            }
            }
        } else {
        } else {
            if (mState.currentSearch != null) {
            if (mSearchManager.isSearching()) {
                // Ongoing search
                // Ongoing search
                DirectoryFragment.showSearch(fm, root, mState.currentSearch, anim);
                DirectoryFragment.showSearch(fm, root, mState.currentSearch, anim);
            } else {
            } else {
                // Normal boring directory
                // Normal boring directory
                DirectoryFragment.showNormal(fm, root, cwd, anim);
                DirectoryFragment.showDirectory(fm, root, cwd, anim);
            }
            }
        }
        }


+3 −3
Original line number Original line Diff line number Diff line
@@ -92,7 +92,7 @@ public class DownloadsActivity extends BaseActivity {
            final Uri rootUri = getIntent().getData();
            final Uri rootUri = getIntent().getData();
            new RestoreRootTask(rootUri).executeOnExecutor(getExecutorForCurrentDirectory());
            new RestoreRootTask(rootUri).executeOnExecutor(getExecutorForCurrentDirectory());
        } else {
        } else {
            onCurrentDirectoryChanged(ANIM_NONE);
            refreshCurrentRootAndDirectory(ANIM_NONE);
        }
        }
    }
    }


@@ -164,7 +164,7 @@ public class DownloadsActivity extends BaseActivity {
    }
    }


    @Override
    @Override
    void onDirectoryChanged(int anim) {
    void refreshDirectory(int anim) {
        final FragmentManager fm = getFragmentManager();
        final FragmentManager fm = getFragmentManager();
        final RootInfo root = getCurrentRoot();
        final RootInfo root = getCurrentRoot();
        final DocumentInfo cwd = getCurrentDirectory();
        final DocumentInfo cwd = getCurrentDirectory();
@@ -178,7 +178,7 @@ public class DownloadsActivity extends BaseActivity {
            DirectoryFragment.showSearch(fm, root, mState.currentSearch, anim);
            DirectoryFragment.showSearch(fm, root, mState.currentSearch, anim);
        } else {
        } else {
            // Normal boring directory
            // Normal boring directory
            DirectoryFragment.showNormal(fm, root, cwd, anim);
            DirectoryFragment.showDirectory(fm, root, cwd, anim);
        }
        }
    }
    }


+4 −4
Original line number Original line Diff line number Diff line
@@ -95,7 +95,7 @@ public class FilesActivity extends BaseActivity {


        if (mState.restored) {
        if (mState.restored) {
            if (DEBUG) Log.d(TAG, "Stack already resolved for uri: " + intent.getData());
            if (DEBUG) Log.d(TAG, "Stack already resolved for uri: " + intent.getData());
            onCurrentDirectoryChanged(ANIM_NONE);
            refreshCurrentRootAndDirectory(ANIM_NONE);
        } else if (!mState.stack.isEmpty()) {
        } else if (!mState.stack.isEmpty()) {
            // If a non-empty stack is present in our state it was read (presumably)
            // 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
            // from EXTRA_STACK intent extra. In this case, we'll skip other means of
@@ -106,7 +106,7 @@ public class FilesActivity extends BaseActivity {
            // don't specify a real content target.
            // don't specify a real content target.
            if (DEBUG) Log.d(TAG, "Launching with non-empty stack.");
            if (DEBUG) Log.d(TAG, "Launching with non-empty stack.");
            checkState(uri == null || LauncherActivity.isLaunchUri(uri));
            checkState(uri == null || LauncherActivity.isLaunchUri(uri));
            onCurrentDirectoryChanged(ANIM_NONE);
            refreshCurrentRootAndDirectory(ANIM_NONE);
        } else if (DocumentsContract.isRootUri(this, uri)) {
        } else if (DocumentsContract.isRootUri(this, uri)) {
            if (DEBUG) Log.d(TAG, "Launching with root 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
            // If we've got a specific root to display, restore that root using a dedicated
@@ -288,7 +288,7 @@ public class FilesActivity extends BaseActivity {
    }
    }


    @Override
    @Override
    void onDirectoryChanged(int anim) {
    void refreshDirectory(int anim) {
        final FragmentManager fm = getFragmentManager();
        final FragmentManager fm = getFragmentManager();
        final RootInfo root = getCurrentRoot();
        final RootInfo root = getCurrentRoot();
        final DocumentInfo cwd = getCurrentDirectory();
        final DocumentInfo cwd = getCurrentDirectory();
@@ -307,7 +307,7 @@ public class FilesActivity extends BaseActivity {
                DirectoryFragment.showSearch(fm, root, mState.currentSearch, anim);
                DirectoryFragment.showSearch(fm, root, mState.currentSearch, anim);
            } else {
            } else {
                // Normal boring directory
                // Normal boring directory
                DirectoryFragment.showNormal(fm, root, cwd, anim);
                DirectoryFragment.showDirectory(fm, root, cwd, anim);
            }
            }
        }
        }
    }
    }
+210 −0
Original line number Original line 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