FileDocCategorySizeDatePackage
SearchView.javaAPI DocAndroid 5.1 API71250Thu Mar 12 22:22:10 GMT 2015android.widget

SearchView

public class SearchView extends LinearLayout implements android.view.CollapsibleActionView
A widget that provides a user interface for the user to enter a search query and submit a request to a search provider. Shows a list of query suggestions or results, if available, and allows the user to pick a suggestion or result to launch into.

When the SearchView is used in an ActionBar as an action view for a collapsible menu item, it needs to be set to iconified by default using {@link #setIconifiedByDefault(boolean) setIconifiedByDefault(true)}. This is the default, so nothing needs to be done.

If you want the search field to always be visible, then call setIconifiedByDefault(false).

Developer Guides

For information about using {@code SearchView}, read the Search developer guide.

see
android.view.MenuItem#SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW
attr
ref android.R.styleable#SearchView_iconifiedByDefault
attr
ref android.R.styleable#SearchView_imeOptions
attr
ref android.R.styleable#SearchView_inputType
attr
ref android.R.styleable#SearchView_maxWidth
attr
ref android.R.styleable#SearchView_queryHint

Fields Summary
private static final boolean
DBG
private static final String
LOG_TAG
private static final String
IME_OPTION_NO_MICROPHONE
Private constant for removing the microphone in the keyboard.
private final SearchAutoComplete
mSearchSrcTextView
private final android.view.View
mSearchEditFrame
private final android.view.View
mSearchPlate
private final android.view.View
mSubmitArea
private final ImageView
mSearchButton
private final ImageView
mGoButton
private final ImageView
mCloseButton
private final ImageView
mVoiceButton
private final android.view.View
mDropDownAnchor
private final ImageView
mCollapsedIcon
Icon optionally displayed when the SearchView is collapsed.
private final android.graphics.drawable.Drawable
mSearchHintIcon
Drawable used as an EditText hint.
private final int
mSuggestionRowLayout
private final int
mSuggestionCommitIconResId
private final android.content.Intent
mVoiceWebSearchIntent
private final android.content.Intent
mVoiceAppSearchIntent
private OnQueryTextListener
mOnQueryChangeListener
private OnCloseListener
mOnCloseListener
private OnFocusChangeListener
mOnQueryTextFocusChangeListener
private OnSuggestionListener
mOnSuggestionListener
private OnClickListener
mOnSearchClickListener
private boolean
mIconifiedByDefault
private boolean
mIconified
private CursorAdapter
mSuggestionsAdapter
private boolean
mSubmitButtonEnabled
private CharSequence
mQueryHint
private boolean
mQueryRefinement
private boolean
mClearingFocus
private int
mMaxWidth
private boolean
mVoiceButtonEnabled
private CharSequence
mOldQueryText
private CharSequence
mUserQuery
private boolean
mExpandedInActionView
private int
mCollapsedImeOptions
private android.app.SearchableInfo
mSearchable
private android.os.Bundle
mAppSearchData
private Runnable
mShowImeRunnable
private Runnable
mUpdateDrawableStateRunnable
private Runnable
mReleaseCursorRunnable
private final WeakHashMap
mOutsideDrawablesCache
private final OnClickListener
mOnClickListener
View.OnKeyListener
mTextKeyListener
React to the user typing "enter" or other hardwired keys while typing in the search box. This handles these special keys while the edit box has focus.
private final android.widget.TextView.OnEditorActionListener
mOnEditorActionListener
private final android.widget.AdapterView.OnItemClickListener
mOnItemClickListener
private final android.widget.AdapterView.OnItemSelectedListener
mOnItemSelectedListener
private android.text.TextWatcher
mTextWatcher
Callback to watch the text field for empty/non-empty
Constructors Summary
public SearchView(android.content.Context context)


                
       

                                                                                                          
          

                                                              
          
    

       

                                              
         
    

                              
       

                                                                
          

                                                                    
          
    

       
        this(context, null);
    
public SearchView(android.content.Context context, android.util.AttributeSet attrs)

        this(context, attrs, R.attr.searchViewStyle);
    
public SearchView(android.content.Context context, android.util.AttributeSet attrs, int defStyleAttr)

        this(context, attrs, defStyleAttr, 0);
    
public SearchView(android.content.Context context, android.util.AttributeSet attrs, int defStyleAttr, int defStyleRes)

        super(context, attrs, defStyleAttr, defStyleRes);

        final TypedArray a = context.obtainStyledAttributes(
                attrs, R.styleable.SearchView, defStyleAttr, defStyleRes);
        final LayoutInflater inflater = (LayoutInflater) context.getSystemService(
                Context.LAYOUT_INFLATER_SERVICE);
        final int layoutResId = a.getResourceId(
                R.styleable.SearchView_layout, R.layout.search_view);
        inflater.inflate(layoutResId, this, true);

        mSearchSrcTextView = (SearchAutoComplete) findViewById(R.id.search_src_text);
        mSearchSrcTextView.setSearchView(this);

        mSearchEditFrame = findViewById(R.id.search_edit_frame);
        mSearchPlate = findViewById(R.id.search_plate);
        mSubmitArea = findViewById(R.id.submit_area);
        mSearchButton = (ImageView) findViewById(R.id.search_button);
        mGoButton = (ImageView) findViewById(R.id.search_go_btn);
        mCloseButton = (ImageView) findViewById(R.id.search_close_btn);
        mVoiceButton = (ImageView) findViewById(R.id.search_voice_btn);
        mCollapsedIcon = (ImageView) findViewById(R.id.search_mag_icon);

        // Set up icons and backgrounds.
        mSearchPlate.setBackground(a.getDrawable(R.styleable.SearchView_queryBackground));
        mSubmitArea.setBackground(a.getDrawable(R.styleable.SearchView_submitBackground));
        mSearchButton.setImageDrawable(a.getDrawable(R.styleable.SearchView_searchIcon));
        mGoButton.setImageDrawable(a.getDrawable(R.styleable.SearchView_goIcon));
        mCloseButton.setImageDrawable(a.getDrawable(R.styleable.SearchView_closeIcon));
        mVoiceButton.setImageDrawable(a.getDrawable(R.styleable.SearchView_voiceIcon));
        mCollapsedIcon.setImageDrawable(a.getDrawable(R.styleable.SearchView_searchIcon));

        // Prior to L MR1, the search hint icon defaulted to searchIcon. If the
        // style does not have an explicit value set, fall back to that.
        if (a.hasValueOrEmpty(R.styleable.SearchView_searchHintIcon)) {
            mSearchHintIcon = a.getDrawable(R.styleable.SearchView_searchHintIcon);
        } else {
            mSearchHintIcon = a.getDrawable(R.styleable.SearchView_searchIcon);
        }

        // Extract dropdown layout resource IDs for later use.
        mSuggestionRowLayout = a.getResourceId(R.styleable.SearchView_suggestionRowLayout,
                R.layout.search_dropdown_item_icons_2line);
        mSuggestionCommitIconResId = a.getResourceId(R.styleable.SearchView_commitIcon, 0);

        mSearchButton.setOnClickListener(mOnClickListener);
        mCloseButton.setOnClickListener(mOnClickListener);
        mGoButton.setOnClickListener(mOnClickListener);
        mVoiceButton.setOnClickListener(mOnClickListener);
        mSearchSrcTextView.setOnClickListener(mOnClickListener);

        mSearchSrcTextView.addTextChangedListener(mTextWatcher);
        mSearchSrcTextView.setOnEditorActionListener(mOnEditorActionListener);
        mSearchSrcTextView.setOnItemClickListener(mOnItemClickListener);
        mSearchSrcTextView.setOnItemSelectedListener(mOnItemSelectedListener);
        mSearchSrcTextView.setOnKeyListener(mTextKeyListener);

        // Inform any listener of focus changes
        mSearchSrcTextView.setOnFocusChangeListener(new OnFocusChangeListener() {

            public void onFocusChange(View v, boolean hasFocus) {
                if (mOnQueryTextFocusChangeListener != null) {
                    mOnQueryTextFocusChangeListener.onFocusChange(SearchView.this, hasFocus);
                }
            }
        });
        setIconifiedByDefault(a.getBoolean(R.styleable.SearchView_iconifiedByDefault, true));

        final int maxWidth = a.getDimensionPixelSize(R.styleable.SearchView_maxWidth, -1);
        if (maxWidth != -1) {
            setMaxWidth(maxWidth);
        }

        final CharSequence queryHint = a.getText(R.styleable.SearchView_queryHint);
        if (!TextUtils.isEmpty(queryHint)) {
            setQueryHint(queryHint);
        }

        final int imeOptions = a.getInt(R.styleable.SearchView_imeOptions, -1);
        if (imeOptions != -1) {
            setImeOptions(imeOptions);
        }

        final int inputType = a.getInt(R.styleable.SearchView_inputType, -1);
        if (inputType != -1) {
            setInputType(inputType);
        }

        boolean focusable = true;
        focusable = a.getBoolean(R.styleable.SearchView_focusable, focusable);
        setFocusable(focusable);

        a.recycle();

        // Save voice intent for later queries/launching
        mVoiceWebSearchIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
        mVoiceWebSearchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        mVoiceWebSearchIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
                RecognizerIntent.LANGUAGE_MODEL_WEB_SEARCH);

        mVoiceAppSearchIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
        mVoiceAppSearchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        mDropDownAnchor = findViewById(mSearchSrcTextView.getDropDownAnchor());
        if (mDropDownAnchor != null) {
            mDropDownAnchor.addOnLayoutChangeListener(new OnLayoutChangeListener() {
                @Override
                public void onLayoutChange(View v, int left, int top, int right, int bottom,
                        int oldLeft, int oldTop, int oldRight, int oldBottom) {
                    adjustDropDownSizeAndPosition();
                }
            });
        }

        updateViewsVisibility(mIconifiedByDefault);
        updateQueryHint();
    
Methods Summary
private voidadjustDropDownSizeAndPosition()

        if (mDropDownAnchor.getWidth() > 1) {
            Resources res = getContext().getResources();
            int anchorPadding = mSearchPlate.getPaddingLeft();
            Rect dropDownPadding = new Rect();
            final boolean isLayoutRtl = isLayoutRtl();
            int iconOffset = mIconifiedByDefault
                    ? res.getDimensionPixelSize(R.dimen.dropdownitem_icon_width)
                    + res.getDimensionPixelSize(R.dimen.dropdownitem_text_padding_left)
                    : 0;
            mSearchSrcTextView.getDropDownBackground().getPadding(dropDownPadding);
            int offset;
            if (isLayoutRtl) {
                offset = - dropDownPadding.left;
            } else {
                offset = anchorPadding - (dropDownPadding.left + iconOffset);
            }
            mSearchSrcTextView.setDropDownHorizontalOffset(offset);
            final int width = mDropDownAnchor.getWidth() + dropDownPadding.left
                    + dropDownPadding.right + iconOffset - anchorPadding;
            mSearchSrcTextView.setDropDownWidth(width);
        }
    
public voidclearFocus()

hide

        mClearingFocus = true;
        setImeVisibility(false);
        super.clearFocus();
        mSearchSrcTextView.clearFocus();
        mClearingFocus = false;
    
private android.content.IntentcreateIntent(java.lang.String action, android.net.Uri data, java.lang.String extraData, java.lang.String query, int actionKey, java.lang.String actionMsg)
Constructs an intent from the given information and the search dialog state.

param
action Intent action.
param
data Intent data, or null.
param
extraData Data for {@link SearchManager#EXTRA_DATA_KEY} or null.
param
query Intent query, or null.
param
actionKey The key code of the action key that was pressed, or {@link KeyEvent#KEYCODE_UNKNOWN} if none.
param
actionMsg The message for the action key that was pressed, or null if none.
param
mode The search mode, one of the acceptable values for {@link SearchManager#SEARCH_MODE}, or {@code null}.
return
The intent.

        // Now build the Intent
        Intent intent = new Intent(action);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        // We need CLEAR_TOP to avoid reusing an old task that has other activities
        // on top of the one we want. We don't want to do this in in-app search though,
        // as it can be destructive to the activity stack.
        if (data != null) {
            intent.setData(data);
        }
        intent.putExtra(SearchManager.USER_QUERY, mUserQuery);
        if (query != null) {
            intent.putExtra(SearchManager.QUERY, query);
        }
        if (extraData != null) {
            intent.putExtra(SearchManager.EXTRA_DATA_KEY, extraData);
        }
        if (mAppSearchData != null) {
            intent.putExtra(SearchManager.APP_DATA, mAppSearchData);
        }
        if (actionKey != KeyEvent.KEYCODE_UNKNOWN) {
            intent.putExtra(SearchManager.ACTION_KEY, actionKey);
            intent.putExtra(SearchManager.ACTION_MSG, actionMsg);
        }
        intent.setComponent(mSearchable.getSearchActivity());
        return intent;
    
private android.content.IntentcreateIntentFromSuggestion(android.database.Cursor c, int actionKey, java.lang.String actionMsg)
When a particular suggestion has been selected, perform the various lookups required to use the suggestion. This includes checking the cursor for suggestion-specific data, and/or falling back to the XML for defaults; It also creates REST style Uri data when the suggestion includes a data id.

param
c The suggestions cursor, moved to the row of the user's selection
param
actionKey The key code of the action key that was pressed, or {@link KeyEvent#KEYCODE_UNKNOWN} if none.
param
actionMsg The message for the action key that was pressed, or null if none.
return
An intent for the suggestion at the cursor's position.

        try {
            // use specific action if supplied, or default action if supplied, or fixed default
            String action = getColumnString(c, SearchManager.SUGGEST_COLUMN_INTENT_ACTION);

            if (action == null) {
                action = mSearchable.getSuggestIntentAction();
            }
            if (action == null) {
                action = Intent.ACTION_SEARCH;
            }

            // use specific data if supplied, or default data if supplied
            String data = getColumnString(c, SearchManager.SUGGEST_COLUMN_INTENT_DATA);
            if (data == null) {
                data = mSearchable.getSuggestIntentData();
            }
            // then, if an ID was provided, append it.
            if (data != null) {
                String id = getColumnString(c, SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID);
                if (id != null) {
                    data = data + "/" + Uri.encode(id);
                }
            }
            Uri dataUri = (data == null) ? null : Uri.parse(data);

            String query = getColumnString(c, SearchManager.SUGGEST_COLUMN_QUERY);
            String extraData = getColumnString(c, SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA);

            return createIntent(action, dataUri, extraData, query, actionKey, actionMsg);
        } catch (RuntimeException e ) {
            int rowNum;
            try {                       // be really paranoid now
                rowNum = c.getPosition();
            } catch (RuntimeException e2 ) {
                rowNum = -1;
            }
            Log.w(LOG_TAG, "Search suggestions cursor at row " + rowNum +
                            " returned exception.", e);
            return null;
        }
    
private android.content.IntentcreateVoiceAppSearchIntent(android.content.Intent baseIntent, android.app.SearchableInfo searchable)
Create and return an Intent that can launch the voice search activity, perform a specific voice transcription, and forward the results to the searchable activity.

param
baseIntent The voice app search intent to start from
return
A completely-configured intent ready to send to the voice search activity

        ComponentName searchActivity = searchable.getSearchActivity();

        // create the necessary intent to set up a search-and-forward operation
        // in the voice search system.   We have to keep the bundle separate,
        // because it becomes immutable once it enters the PendingIntent
        Intent queryIntent = new Intent(Intent.ACTION_SEARCH);
        queryIntent.setComponent(searchActivity);
        PendingIntent pending = PendingIntent.getActivity(getContext(), 0, queryIntent,
                PendingIntent.FLAG_ONE_SHOT);

        // Now set up the bundle that will be inserted into the pending intent
        // when it's time to do the search.  We always build it here (even if empty)
        // because the voice search activity will always need to insert "QUERY" into
        // it anyway.
        Bundle queryExtras = new Bundle();
        if (mAppSearchData != null) {
            queryExtras.putParcelable(SearchManager.APP_DATA, mAppSearchData);
        }

        // Now build the intent to launch the voice search.  Add all necessary
        // extras to launch the voice recognizer, and then all the necessary extras
        // to forward the results to the searchable activity
        Intent voiceIntent = new Intent(baseIntent);

        // Add all of the configuration options supplied by the searchable's metadata
        String languageModel = RecognizerIntent.LANGUAGE_MODEL_FREE_FORM;
        String prompt = null;
        String language = null;
        int maxResults = 1;

        Resources resources = getResources();
        if (searchable.getVoiceLanguageModeId() != 0) {
            languageModel = resources.getString(searchable.getVoiceLanguageModeId());
        }
        if (searchable.getVoicePromptTextId() != 0) {
            prompt = resources.getString(searchable.getVoicePromptTextId());
        }
        if (searchable.getVoiceLanguageId() != 0) {
            language = resources.getString(searchable.getVoiceLanguageId());
        }
        if (searchable.getVoiceMaxResults() != 0) {
            maxResults = searchable.getVoiceMaxResults();
        }
        voiceIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, languageModel);
        voiceIntent.putExtra(RecognizerIntent.EXTRA_PROMPT, prompt);
        voiceIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, language);
        voiceIntent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, maxResults);
        voiceIntent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, searchActivity == null ? null
                : searchActivity.flattenToShortString());

        // Add the values that configure forwarding the results
        voiceIntent.putExtra(RecognizerIntent.EXTRA_RESULTS_PENDINGINTENT, pending);
        voiceIntent.putExtra(RecognizerIntent.EXTRA_RESULTS_PENDINGINTENT_BUNDLE, queryExtras);

        return voiceIntent;
    
private android.content.IntentcreateVoiceWebSearchIntent(android.content.Intent baseIntent, android.app.SearchableInfo searchable)
Create and return an Intent that can launch the voice search activity for web search.

        Intent voiceIntent = new Intent(baseIntent);
        ComponentName searchActivity = searchable.getSearchActivity();
        voiceIntent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, searchActivity == null ? null
                : searchActivity.flattenToShortString());
        return voiceIntent;
    
private voiddismissSuggestions()

        mSearchSrcTextView.dismissDropDown();
    
private voidforceSuggestionQuery()

        mSearchSrcTextView.doBeforeTextChanged();
        mSearchSrcTextView.doAfterTextChanged();
    
private static java.lang.StringgetActionKeyMessage(android.database.Cursor c, SearchableInfo.ActionKeyInfo actionKey)
For a given suggestion and a given cursor row, get the action message. If not provided by the specific row/column, also check for a single definition (for the action key).

param
c The cursor providing suggestions
param
actionKey The actionkey record being examined
return
Returns a string, or null if no action key message for this suggestion

        String result = null;
        // check first in the cursor data, for a suggestion-specific message
        final String column = actionKey.getSuggestActionMsgColumn();
        if (column != null) {
            result = SuggestionsAdapter.getColumnString(c, column);
        }
        // If the cursor didn't give us a message, see if there's a single
        // message defined
        // for the actionkey (for all suggestions)
        if (result == null) {
            result = actionKey.getSuggestActionMsg();
        }
        return result;
    
private java.lang.CharSequencegetDecoratedHint(java.lang.CharSequence hintText)

        // If the field is always expanded or we don't have a search hint icon,
        // then don't add the search icon to the hint.
        if (!mIconifiedByDefault || mSearchHintIcon == null) {
            return hintText;
        }

        final int textSize = (int) (mSearchSrcTextView.getTextSize() * 1.25);
        mSearchHintIcon.setBounds(0, 0, textSize, textSize);

        final SpannableStringBuilder ssb = new SpannableStringBuilder("   ");
        ssb.setSpan(new ImageSpan(mSearchHintIcon), 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        ssb.append(hintText);
        return ssb;
    
public intgetImeOptions()
Returns the IME options set on the query text field.

return
the ime options
see
TextView#setImeOptions(int)
attr
ref android.R.styleable#SearchView_imeOptions

        return mSearchSrcTextView.getImeOptions();
    
public intgetInputType()
Returns the input type set on the query text field.

return
the input type
attr
ref android.R.styleable#SearchView_inputType

        return mSearchSrcTextView.getInputType();
    
public intgetMaxWidth()
Gets the specified maximum width in pixels, if set. Returns zero if no maximum width was specified.

return
the maximum width of the view
attr
ref android.R.styleable#SearchView_maxWidth

        return mMaxWidth;
    
private intgetPreferredWidth()

        return getContext().getResources()
                .getDimensionPixelSize(R.dimen.search_view_preferred_width);
    
public java.lang.CharSequencegetQuery()
Returns the query string currently in the text field.

return
the query string

        return mSearchSrcTextView.getText();
    
public java.lang.CharSequencegetQueryHint()
Gets the hint text to display in the query text field.

return
the query hint text, if specified, null otherwise.
attr
ref android.R.styleable#SearchView_queryHint

        if (mQueryHint != null) {
            return mQueryHint;
        } else if (mSearchable != null) {
            CharSequence hint = null;
            int hintId = mSearchable.getHintId();
            if (hintId != 0) {
                hint = getContext().getString(hintId);
            }
            return hint;
        }
        return null;
    
intgetSuggestionCommitIconResId()

        return mSuggestionCommitIconResId;
    
intgetSuggestionRowLayout()

        return mSuggestionRowLayout;
    
public CursorAdaptergetSuggestionsAdapter()
Returns the adapter used for suggestions, if any.

return
the suggestions adapter

        return mSuggestionsAdapter;
    
private booleanhasVoiceSearch()

        if (mSearchable != null && mSearchable.getVoiceSearchEnabled()) {
            Intent testIntent = null;
            if (mSearchable.getVoiceSearchLaunchWebSearch()) {
                testIntent = mVoiceWebSearchIntent;
            } else if (mSearchable.getVoiceSearchLaunchRecognizer()) {
                testIntent = mVoiceAppSearchIntent;
            }
            if (testIntent != null) {
                ResolveInfo ri = getContext().getPackageManager().resolveActivity(testIntent,
                        PackageManager.MATCH_DEFAULT_ONLY);
                return ri != null;
            }
        }
        return false;
    
public booleanisIconfiedByDefault()
Returns the default iconified state of the search field.

return
attr
ref android.R.styleable#SearchView_iconifiedByDefault

        return mIconifiedByDefault;
    
public booleanisIconified()
Returns the current iconified state of the SearchView.

return
true if the SearchView is currently iconified, false if the search field is fully visible.

        return mIconified;
    
static booleanisLandscapeMode(android.content.Context context)

        return context.getResources().getConfiguration().orientation
                == Configuration.ORIENTATION_LANDSCAPE;
    
public booleanisQueryRefinementEnabled()
Returns whether query refinement is enabled for all items or only specific ones.

return
true if enabled for all items, false otherwise.

        return mQueryRefinement;
    
private booleanisSubmitAreaEnabled()

        return (mSubmitButtonEnabled || mVoiceButtonEnabled) && !isIconified();
    
public booleanisSubmitButtonEnabled()
Returns whether the submit button is enabled when necessary or never displayed.

return
whether the submit button is enabled automatically when necessary

        return mSubmitButtonEnabled;
    
private voidlaunchIntent(android.content.Intent intent)
Launches an intent, including any special intent handling.

        if (intent == null) {
            return;
        }
        try {
            // If the intent was created from a suggestion, it will always have an explicit
            // component here.
            getContext().startActivity(intent);
        } catch (RuntimeException ex) {
            Log.e(LOG_TAG, "Failed launch activity: " + intent, ex);
        }
    
private voidlaunchQuerySearch(int actionKey, java.lang.String actionMsg, java.lang.String query)

        String action = Intent.ACTION_SEARCH;
        Intent intent = createIntent(action, null, null, query, actionKey, actionMsg);
        getContext().startActivity(intent);
    
private booleanlaunchSuggestion(int position, int actionKey, java.lang.String actionMsg)
Launches an intent based on a suggestion.

param
position The index of the suggestion to create the intent from.
param
actionKey The key code of the action key that was pressed, or {@link KeyEvent#KEYCODE_UNKNOWN} if none.
param
actionMsg The message for the action key that was pressed, or null if none.
return
true if a successful launch, false if could not (e.g. bad position).

        Cursor c = mSuggestionsAdapter.getCursor();
        if ((c != null) && c.moveToPosition(position)) {

            Intent intent = createIntentFromSuggestion(c, actionKey, actionMsg);

            // launch the intent
            launchIntent(intent);

            return true;
        }
        return false;
    
public voidonActionViewCollapsed()
{@inheritDoc}

        setQuery("", false);
        clearFocus();
        updateViewsVisibility(true);
        mSearchSrcTextView.setImeOptions(mCollapsedImeOptions);
        mExpandedInActionView = false;
    
public voidonActionViewExpanded()
{@inheritDoc}

        if (mExpandedInActionView) return;

        mExpandedInActionView = true;
        mCollapsedImeOptions = mSearchSrcTextView.getImeOptions();
        mSearchSrcTextView.setImeOptions(mCollapsedImeOptions | EditorInfo.IME_FLAG_NO_FULLSCREEN);
        mSearchSrcTextView.setText("");
        setIconified(false);
    
private voidonCloseClicked()

        CharSequence text = mSearchSrcTextView.getText();
        if (TextUtils.isEmpty(text)) {
            if (mIconifiedByDefault) {
                // If the app doesn't override the close behavior
                if (mOnCloseListener == null || !mOnCloseListener.onClose()) {
                    // hide the keyboard and remove focus
                    clearFocus();
                    // collapse the search field
                    updateViewsVisibility(true);
                }
            }
        } else {
            mSearchSrcTextView.setText("");
            mSearchSrcTextView.requestFocus();
            setImeVisibility(true);
        }

    
protected voidonDetachedFromWindow()

        removeCallbacks(mUpdateDrawableStateRunnable);
        post(mReleaseCursorRunnable);
        super.onDetachedFromWindow();
    
public voidonInitializeAccessibilityEvent(android.view.accessibility.AccessibilityEvent event)

        super.onInitializeAccessibilityEvent(event);
        event.setClassName(SearchView.class.getName());
    
public voidonInitializeAccessibilityNodeInfo(android.view.accessibility.AccessibilityNodeInfo info)

        super.onInitializeAccessibilityNodeInfo(info);
        info.setClassName(SearchView.class.getName());
    
private booleanonItemClicked(int position, int actionKey, java.lang.String actionMsg)

        if (mOnSuggestionListener == null
                || !mOnSuggestionListener.onSuggestionClick(position)) {
            launchSuggestion(position, KeyEvent.KEYCODE_UNKNOWN, null);
            setImeVisibility(false);
            dismissSuggestions();
            return true;
        }
        return false;
    
private booleanonItemSelected(int position)

        if (mOnSuggestionListener == null
                || !mOnSuggestionListener.onSuggestionSelect(position)) {
            rewriteQueryFromSuggestion(position);
            return true;
        }
        return false;
    
public booleanonKeyDown(int keyCode, android.view.KeyEvent event)
Handles the key down event for dealing with action keys.

param
keyCode This is the keycode of the typed key, and is the same value as found in the KeyEvent parameter.
param
event The complete event record for the typed key
return
true if the event was handled here, or false if not.


                                                                     
    
          
        if (mSearchable == null) {
            return false;
        }

        // if it's an action specified by the searchable activity, launch the
        // entered query with the action key
        SearchableInfo.ActionKeyInfo actionKey = mSearchable.findActionKey(keyCode);
        if ((actionKey != null) && (actionKey.getQueryActionMsg() != null)) {
            launchQuerySearch(keyCode, actionKey.getQueryActionMsg(), mSearchSrcTextView.getText()
                    .toString());
            return true;
        }

        return super.onKeyDown(keyCode, event);
    
protected voidonMeasure(int widthMeasureSpec, int heightMeasureSpec)

        // Let the standard measurements take effect in iconified state.
        if (isIconified()) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            return;
        }

        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);

        switch (widthMode) {
        case MeasureSpec.AT_MOST:
            // If there is an upper limit, don't exceed maximum width (explicit or implicit)
            if (mMaxWidth > 0) {
                width = Math.min(mMaxWidth, width);
            } else {
                width = Math.min(getPreferredWidth(), width);
            }
            break;
        case MeasureSpec.EXACTLY:
            // If an exact width is specified, still don't exceed any specified maximum width
            if (mMaxWidth > 0) {
                width = Math.min(mMaxWidth, width);
            }
            break;
        case MeasureSpec.UNSPECIFIED:
            // Use maximum width, if specified, else preferred width
            width = mMaxWidth > 0 ? mMaxWidth : getPreferredWidth();
            break;
        }
        widthMode = MeasureSpec.EXACTLY;
        super.onMeasure(MeasureSpec.makeMeasureSpec(width, widthMode), heightMeasureSpec);
    
voidonQueryRefine(java.lang.CharSequence queryText)
Called by the SuggestionsAdapter

hide

        setQuery(queryText);
    
private voidonSearchClicked()

        updateViewsVisibility(false);
        mSearchSrcTextView.requestFocus();
        setImeVisibility(true);
        if (mOnSearchClickListener != null) {
            mOnSearchClickListener.onClick(this);
        }
    
private voidonSubmitQuery()

        CharSequence query = mSearchSrcTextView.getText();
        if (query != null && TextUtils.getTrimmedLength(query) > 0) {
            if (mOnQueryChangeListener == null
                    || !mOnQueryChangeListener.onQueryTextSubmit(query.toString())) {
                if (mSearchable != null) {
                    launchQuerySearch(KeyEvent.KEYCODE_UNKNOWN, null, query.toString());
                }
                setImeVisibility(false);
                dismissSuggestions();
            }
        }
    
private booleanonSuggestionsKey(android.view.View v, int keyCode, android.view.KeyEvent event)
React to the user typing while in the suggestions list. First, check for action keys. If not handled, try refocusing regular characters into the EditText.


                                  
            
        // guard against possible race conditions (late arrival after dismiss)
        if (mSearchable == null) {
            return false;
        }
        if (mSuggestionsAdapter == null) {
            return false;
        }
        if (event.getAction() == KeyEvent.ACTION_DOWN && event.hasNoModifiers()) {
            // First, check for enter or search (both of which we'll treat as a
            // "click")
            if (keyCode == KeyEvent.KEYCODE_ENTER || keyCode == KeyEvent.KEYCODE_SEARCH
                    || keyCode == KeyEvent.KEYCODE_TAB) {
                int position = mSearchSrcTextView.getListSelection();
                return onItemClicked(position, KeyEvent.KEYCODE_UNKNOWN, null);
            }

            // Next, check for left/right moves, which we use to "return" the
            // user to the edit view
            if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT || keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
                // give "focus" to text editor, with cursor at the beginning if
                // left key, at end if right key
                // TODO: Reverse left/right for right-to-left languages, e.g.
                // Arabic
                int selPoint = (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) ? 0 : mSearchSrcTextView
                        .length();
                mSearchSrcTextView.setSelection(selPoint);
                mSearchSrcTextView.setListSelection(0);
                mSearchSrcTextView.clearListSelection();
                mSearchSrcTextView.ensureImeVisible(true);

                return true;
            }

            // Next, check for an "up and out" move
            if (keyCode == KeyEvent.KEYCODE_DPAD_UP && 0 == mSearchSrcTextView.getListSelection()) {
                // TODO: restoreUserQuery();
                // let ACTV complete the move
                return false;
            }

            // Next, check for an "action key"
            SearchableInfo.ActionKeyInfo actionKey = mSearchable.findActionKey(keyCode);
            if ((actionKey != null)
                    && ((actionKey.getSuggestActionMsg() != null) || (actionKey
                            .getSuggestActionMsgColumn() != null))) {
                // launch suggestion using action key column
                int position = mSearchSrcTextView.getListSelection();
                if (position != ListView.INVALID_POSITION) {
                    Cursor c = mSuggestionsAdapter.getCursor();
                    if (c.moveToPosition(position)) {
                        final String actionMsg = getActionKeyMessage(c, actionKey);
                        if (actionMsg != null && (actionMsg.length() > 0)) {
                            return onItemClicked(position, keyCode, actionMsg);
                        }
                    }
                }
            }
        }
        return false;
    
private voidonTextChanged(java.lang.CharSequence newText)


        
        CharSequence text = mSearchSrcTextView.getText();
        mUserQuery = text;
        boolean hasText = !TextUtils.isEmpty(text);
        updateSubmitButton(hasText);
        updateVoiceButton(!hasText);
        updateCloseButton();
        updateSubmitArea();
        if (mOnQueryChangeListener != null && !TextUtils.equals(newText, mOldQueryText)) {
            mOnQueryChangeListener.onQueryTextChange(newText.toString());
        }
        mOldQueryText = newText.toString();
    
voidonTextFocusChanged()

        updateViewsVisibility(isIconified());
        // Delayed update to make sure that the focus has settled down and window focus changes
        // don't affect it. A synchronous update was not working.
        postUpdateFocusedState();
        if (mSearchSrcTextView.hasFocus()) {
            forceSuggestionQuery();
        }
    
private voidonVoiceClicked()

        // guard against possible race conditions
        if (mSearchable == null) {
            return;
        }
        SearchableInfo searchable = mSearchable;
        try {
            if (searchable.getVoiceSearchLaunchWebSearch()) {
                Intent webSearchIntent = createVoiceWebSearchIntent(mVoiceWebSearchIntent,
                        searchable);
                getContext().startActivity(webSearchIntent);
            } else if (searchable.getVoiceSearchLaunchRecognizer()) {
                Intent appSearchIntent = createVoiceAppSearchIntent(mVoiceAppSearchIntent,
                        searchable);
                getContext().startActivity(appSearchIntent);
            }
        } catch (ActivityNotFoundException e) {
            // Should not happen, since we check the availability of
            // voice search before showing the button. But just in case...
            Log.w(LOG_TAG, "Could not find voice search activity");
        }
    
public voidonWindowFocusChanged(boolean hasWindowFocus)

        super.onWindowFocusChanged(hasWindowFocus);

        postUpdateFocusedState();
    
private voidpostUpdateFocusedState()

        post(mUpdateDrawableStateRunnable);
    
public booleanrequestFocus(int direction, android.graphics.Rect previouslyFocusedRect)

hide

        // Don't accept focus if in the middle of clearing focus
        if (mClearingFocus) return false;
        // Check if SearchView is focusable.
        if (!isFocusable()) return false;
        // If it is not iconified, then give the focus to the text field
        if (!isIconified()) {
            boolean result = mSearchSrcTextView.requestFocus(direction, previouslyFocusedRect);
            if (result) {
                updateViewsVisibility(false);
            }
            return result;
        } else {
            return super.requestFocus(direction, previouslyFocusedRect);
        }
    
private voidrewriteQueryFromSuggestion(int position)
Query rewriting.


           
        
        CharSequence oldQuery = mSearchSrcTextView.getText();
        Cursor c = mSuggestionsAdapter.getCursor();
        if (c == null) {
            return;
        }
        if (c.moveToPosition(position)) {
            // Get the new query from the suggestion.
            CharSequence newQuery = mSuggestionsAdapter.convertToString(c);
            if (newQuery != null) {
                // The suggestion rewrites the query.
                // Update the text field, without getting new suggestions.
                setQuery(newQuery);
            } else {
                // The suggestion does not rewrite the query, restore the user's query.
                setQuery(oldQuery);
            }
        } else {
            // We got a bad position, restore the user's query.
            setQuery(oldQuery);
        }
    
public voidsetAppSearchData(android.os.Bundle appSearchData)
Sets the APP_DATA for legacy SearchDialog use.

param
appSearchData bundle provided by the app when launching the search dialog
hide

        mAppSearchData = appSearchData;
    
public voidsetIconified(boolean iconify)
Iconifies or expands the SearchView. Any query text is cleared when iconified. This is a temporary state and does not override the default iconified state set by {@link #setIconifiedByDefault(boolean)}. If the default state is iconified, then a false here will only be valid until the user closes the field. And if the default state is expanded, then a true here will only clear the text field and not close it.

param
iconify a true value will collapse the SearchView to an icon, while a false will expand it.

        if (iconify) {
            onCloseClicked();
        } else {
            onSearchClicked();
        }
    
public voidsetIconifiedByDefault(boolean iconified)
Sets the default or resting state of the search field. If true, a single search icon is shown by default and expands to show the text field and other buttons when pressed. Also, if the default state is iconified, then it collapses to that state when the close button is pressed. Changes to this property will take effect immediately.

The default value is true.

param
iconified whether the search field should be iconified by default
attr
ref android.R.styleable#SearchView_iconifiedByDefault

        if (mIconifiedByDefault == iconified) return;
        mIconifiedByDefault = iconified;
        updateViewsVisibility(iconified);
        updateQueryHint();
    
public voidsetImeOptions(int imeOptions)
Sets the IME options on the query text field.

see
TextView#setImeOptions(int)
param
imeOptions the options to set on the query text field
attr
ref android.R.styleable#SearchView_imeOptions

        mSearchSrcTextView.setImeOptions(imeOptions);
    
private voidsetImeVisibility(boolean visible)

        if (visible) {
            post(mShowImeRunnable);
        } else {
            removeCallbacks(mShowImeRunnable);
            InputMethodManager imm = (InputMethodManager)
                    getContext().getSystemService(Context.INPUT_METHOD_SERVICE);

            if (imm != null) {
                imm.hideSoftInputFromWindow(getWindowToken(), 0);
            }
        }
    
public voidsetInputType(int inputType)
Sets the input type on the query text field.

see
TextView#setInputType(int)
param
inputType the input type to set on the query text field
attr
ref android.R.styleable#SearchView_inputType

        mSearchSrcTextView.setInputType(inputType);
    
public voidsetMaxWidth(int maxpixels)
Makes the view at most this many pixels wide

attr
ref android.R.styleable#SearchView_maxWidth

        mMaxWidth = maxpixels;

        requestLayout();
    
public voidsetOnCloseListener(android.widget.SearchView$OnCloseListener listener)
Sets a listener to inform when the user closes the SearchView.

param
listener the listener to call when the user closes the SearchView.

        mOnCloseListener = listener;
    
public voidsetOnQueryTextFocusChangeListener(OnFocusChangeListener listener)
Sets a listener to inform when the focus of the query text field changes.

param
listener the listener to inform of focus changes.

        mOnQueryTextFocusChangeListener = listener;
    
public voidsetOnQueryTextListener(android.widget.SearchView$OnQueryTextListener listener)
Sets a listener for user actions within the SearchView.

param
listener the listener object that receives callbacks when the user performs actions in the SearchView such as clicking on buttons or typing a query.

        mOnQueryChangeListener = listener;
    
public voidsetOnSearchClickListener(OnClickListener listener)
Sets a listener to inform when the search button is pressed. This is only relevant when the text field is not visible by default. Calling {@link #setIconified setIconified(false)} can also cause this listener to be informed.

param
listener the listener to inform when the search button is clicked or the text field is programmatically de-iconified.

        mOnSearchClickListener = listener;
    
public voidsetOnSuggestionListener(android.widget.SearchView$OnSuggestionListener listener)
Sets a listener to inform when a suggestion is focused or clicked.

param
listener the listener to inform of suggestion selection events.

        mOnSuggestionListener = listener;
    
public voidsetQuery(java.lang.CharSequence query, boolean submit)
Sets a query string in the text field and optionally submits the query as well.

param
query the query string. This replaces any query text already present in the text field.
param
submit whether to submit the query right now or only update the contents of text field.

        mSearchSrcTextView.setText(query);
        if (query != null) {
            mSearchSrcTextView.setSelection(mSearchSrcTextView.length());
            mUserQuery = query;
        }

        // If the query is not empty and submit is requested, submit the query
        if (submit && !TextUtils.isEmpty(query)) {
            onSubmitQuery();
        }
    
private voidsetQuery(java.lang.CharSequence query)
Sets the text in the query box, without updating the suggestions.

        mSearchSrcTextView.setText(query, true);
        // Move the cursor to the end
        mSearchSrcTextView.setSelection(TextUtils.isEmpty(query) ? 0 : query.length());
    
public voidsetQueryHint(java.lang.CharSequence hint)
Sets the hint text to display in the query text field. This overrides any hint specified in the SearchableInfo.

param
hint the hint text to display
attr
ref android.R.styleable#SearchView_queryHint

        mQueryHint = hint;
        updateQueryHint();
    
public voidsetQueryRefinementEnabled(boolean enable)
Specifies if a query refinement button should be displayed alongside each suggestion or if it should depend on the flags set in the individual items retrieved from the suggestions provider. Clicking on the query refinement button will replace the text in the query text field with the text from the suggestion. This flag only takes effect if a SearchableInfo has been specified with {@link #setSearchableInfo(SearchableInfo)} and not when using a custom adapter.

param
enable true if all items should have a query refinement button, false if only those items that have a query refinement flag set should have the button.
see
SearchManager#SUGGEST_COLUMN_FLAGS
see
SearchManager#FLAG_QUERY_REFINEMENT

        mQueryRefinement = enable;
        if (mSuggestionsAdapter instanceof SuggestionsAdapter) {
            ((SuggestionsAdapter) mSuggestionsAdapter).setQueryRefinement(
                    enable ? SuggestionsAdapter.REFINE_ALL : SuggestionsAdapter.REFINE_BY_ENTRY);
        }
    
public voidsetSearchableInfo(android.app.SearchableInfo searchable)
Sets the SearchableInfo for this SearchView. Properties in the SearchableInfo are used to display labels, hints, suggestions, create intents for launching search results screens and controlling other affordances such as a voice button.

param
searchable a SearchableInfo can be retrieved from the SearchManager, for a specific activity or a global search provider.

        mSearchable = searchable;
        if (mSearchable != null) {
            updateSearchAutoComplete();
            updateQueryHint();
        }
        // Cache the voice search capability
        mVoiceButtonEnabled = hasVoiceSearch();

        if (mVoiceButtonEnabled) {
            // Disable the microphone on the keyboard, as a mic is displayed near the text box
            // TODO: use imeOptions to disable voice input when the new API will be available
            mSearchSrcTextView.setPrivateImeOptions(IME_OPTION_NO_MICROPHONE);
        }
        updateViewsVisibility(isIconified());
    
public voidsetSubmitButtonEnabled(boolean enabled)
Enables showing a submit button when the query is non-empty. In cases where the SearchView is being used to filter the contents of the current activity and doesn't launch a separate results activity, then the submit button should be disabled.

param
enabled true to show a submit button for submitting queries, false if a submit button is not required.

        mSubmitButtonEnabled = enabled;
        updateViewsVisibility(isIconified());
    
public voidsetSuggestionsAdapter(CursorAdapter adapter)
You can set a custom adapter if you wish. Otherwise the default adapter is used to display the suggestions from the suggestions provider associated with the SearchableInfo.

see
#setSearchableInfo(SearchableInfo)

        mSuggestionsAdapter = adapter;

        mSearchSrcTextView.setAdapter(mSuggestionsAdapter);
    
private voidupdateCloseButton()

        final boolean hasText = !TextUtils.isEmpty(mSearchSrcTextView.getText());
        // Should we show the close button? It is not shown if there's no focus,
        // field is not iconified by default and there is no text in it.
        final boolean showClose = hasText || (mIconifiedByDefault && !mExpandedInActionView);
        mCloseButton.setVisibility(showClose ? VISIBLE : GONE);
        final Drawable closeButtonImg = mCloseButton.getDrawable();
        if (closeButtonImg != null){
            closeButtonImg.setState(hasText ? ENABLED_STATE_SET : EMPTY_STATE_SET);
        }
    
private voidupdateFocusedState()

        final boolean focused = mSearchSrcTextView.hasFocus();
        final int[] stateSet = focused ? FOCUSED_STATE_SET : EMPTY_STATE_SET;
        final Drawable searchPlateBg = mSearchPlate.getBackground();
        if (searchPlateBg != null) {
            searchPlateBg.setState(stateSet);
        }
        final Drawable submitAreaBg = mSubmitArea.getBackground();
        if (submitAreaBg != null) {
            submitAreaBg.setState(stateSet);
        }
        invalidate();
    
private voidupdateQueryHint()

        if (mQueryHint != null) {
            mSearchSrcTextView.setHint(getDecoratedHint(mQueryHint));
        } else if (mSearchable != null) {
            CharSequence hint = null;
            int hintId = mSearchable.getHintId();
            if (hintId != 0) {
                hint = getContext().getString(hintId);
            }
            if (hint != null) {
                mSearchSrcTextView.setHint(getDecoratedHint(hint));
            }
        } else {
            mSearchSrcTextView.setHint(getDecoratedHint(""));
        }
    
private voidupdateSearchAutoComplete()
Updates the auto-complete text view.

        mSearchSrcTextView.setDropDownAnimationStyle(0); // no animation
        mSearchSrcTextView.setThreshold(mSearchable.getSuggestThreshold());
        mSearchSrcTextView.setImeOptions(mSearchable.getImeOptions());
        int inputType = mSearchable.getInputType();
        // We only touch this if the input type is set up for text (which it almost certainly
        // should be, in the case of search!)
        if ((inputType & InputType.TYPE_MASK_CLASS) == InputType.TYPE_CLASS_TEXT) {
            // The existence of a suggestions authority is the proxy for "suggestions
            // are available here"
            inputType &= ~InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE;
            if (mSearchable.getSuggestAuthority() != null) {
                inputType |= InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE;
                // TYPE_TEXT_FLAG_AUTO_COMPLETE means that the text editor is performing
                // auto-completion based on its own semantics, which it will present to the user
                // as they type. This generally means that the input method should not show its
                // own candidates, and the spell checker should not be in action. The text editor
                // supplies its candidates by calling InputMethodManager.displayCompletions(),
                // which in turn will call InputMethodSession.displayCompletions().
                inputType |= InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS;
            }
        }
        mSearchSrcTextView.setInputType(inputType);
        if (mSuggestionsAdapter != null) {
            mSuggestionsAdapter.changeCursor(null);
        }
        // attach the suggestions adapter, if suggestions are available
        // The existence of a suggestions authority is the proxy for "suggestions available here"
        if (mSearchable.getSuggestAuthority() != null) {
            mSuggestionsAdapter = new SuggestionsAdapter(getContext(),
                    this, mSearchable, mOutsideDrawablesCache);
            mSearchSrcTextView.setAdapter(mSuggestionsAdapter);
            ((SuggestionsAdapter) mSuggestionsAdapter).setQueryRefinement(
                    mQueryRefinement ? SuggestionsAdapter.REFINE_ALL
                    : SuggestionsAdapter.REFINE_BY_ENTRY);
        }
    
private voidupdateSubmitArea()

        int visibility = GONE;
        if (isSubmitAreaEnabled()
                && (mGoButton.getVisibility() == VISIBLE
                        || mVoiceButton.getVisibility() == VISIBLE)) {
            visibility = VISIBLE;
        }
        mSubmitArea.setVisibility(visibility);
    
private voidupdateSubmitButton(boolean hasText)

        int visibility = GONE;
        if (mSubmitButtonEnabled && isSubmitAreaEnabled() && hasFocus()
                && (hasText || !mVoiceButtonEnabled)) {
            visibility = VISIBLE;
        }
        mGoButton.setVisibility(visibility);
    
private voidupdateViewsVisibility(boolean collapsed)

        mIconified = collapsed;
        // Visibility of views that are visible when collapsed
        final int visCollapsed = collapsed ? VISIBLE : GONE;
        // Is there text in the query
        final boolean hasText = !TextUtils.isEmpty(mSearchSrcTextView.getText());

        mSearchButton.setVisibility(visCollapsed);
        updateSubmitButton(hasText);
        mSearchEditFrame.setVisibility(collapsed ? GONE : VISIBLE);
        mCollapsedIcon.setVisibility(mIconifiedByDefault ? GONE : VISIBLE);
        updateCloseButton();
        updateVoiceButton(!hasText);
        updateSubmitArea();
    
private voidupdateVoiceButton(boolean empty)
Update the visibility of the voice button. There are actually two voice search modes, either of which will activate the button.

param
empty whether the search query text field is empty. If it is, then the other criteria apply to make the voice button visible.

        int visibility = GONE;
        if (mVoiceButtonEnabled && !isIconified() && empty) {
            visibility = VISIBLE;
            mGoButton.setVisibility(GONE);
        }
        mVoiceButton.setVisibility(visibility);