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

Commit 0594476f authored by Amith Yamasani's avatar Amith Yamasani
Browse files

SearchView: Add some more listeners, IME dismiss improvements and focus control.

Addresses following bugs:
3067611 : Submit button incorrectly displayed
3064371 : Callback to report suggestion click
3008580 : Setting initial focus

The SearchView will take initial focus now, reverting an earlier change. If
you don't want it to take initial focus, then you must requestFocus on a
different view on launching the activity, since the initial focus is desirable
in other cases. This is normal behavior for all EditText widgets and SearchView
shouldn't have a different behavior.
parent 9568a5ab
Loading
Loading
Loading
Loading
+61 −1
Original line number Diff line number Diff line
@@ -236406,6 +236406,32 @@
<parameter name="listener" type="android.widget.SearchView.OnQueryChangeListener">
</parameter>
</method>
<method name="setOnQueryTextFocusChangeListener"
 return="void"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="listener" type="android.view.View.OnFocusChangeListener">
</parameter>
</method>
<method name="setOnSuggestionSelectionListener"
 return="void"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="listener" type="android.widget.SearchView.OnSuggestionSelectionListener">
</parameter>
</method>
<method name="setQuery"
 return="void"
 abstract="false"
@@ -236540,6 +236566,40 @@
</parameter>
</method>
</interface>
<interface name="SearchView.OnSuggestionSelectionListener"
 abstract="true"
 static="true"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<method name="onSuggestionClicked"
 return="boolean"
 abstract="true"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="position" type="int">
</parameter>
</method>
<method name="onSuggestionSelected"
 return="boolean"
 abstract="true"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="position" type="int">
</parameter>
</method>
</interface>
<interface name="SectionIndexer"
 abstract="true"
 static="false"
@@ -242818,7 +242878,7 @@
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="arg0" type="T">
<parameter name="t" type="T">
</parameter>
</method>
</interface>
+110 −29
Original line number Diff line number Diff line
@@ -56,6 +56,8 @@ public class SearchView extends LinearLayout {

    private OnQueryChangeListener mOnQueryChangeListener;
    private OnCloseListener mOnCloseListener;
    private OnFocusChangeListener mOnQueryTextFocusChangeListener;
    private OnSuggestionSelectionListener mOnSuggestionListener;

    private boolean mIconifiedByDefault;
    private boolean mIconified;
@@ -68,6 +70,7 @@ public class SearchView extends LinearLayout {
    private boolean mSubmitButtonEnabled;
    private CharSequence mQueryHint;
    private boolean mQueryRefinement;
    private boolean mClearingFocus;

    private SearchableInfo mSearchable;

@@ -117,6 +120,32 @@ public class SearchView extends LinearLayout {
        boolean onClose();
    }

    /**
     * Callback interface for selection events on suggestions. These callbacks
     * are only relevant when a SearchableInfo has been specified by {@link #setSearchableInfo}.
     */
    public interface OnSuggestionSelectionListener {

        /**
         * Called when a suggestion was selected by navigating to it.
         * @param position the absolute position in the list of suggestions.
         *
         * @return true if the listener handles the event and wants to override the default
         * behavior of possibly rewriting the query based on the selected item, false otherwise.
         */
        boolean onSuggestionSelected(int position);

        /**
         * Called when a suggestion was clicked.
         * @param position the absolute position of the clicked item in the list of suggestions.
         *
         * @return true if the listener handles the event and wants to override the default
         * behavior of launching any intent or submitting a search query specified on that item.
         * Return false otherwise.
         */
        boolean onSuggestionClicked(int position);
    }

    public SearchView(Context context) {
        this(context, null);
    }
@@ -141,6 +170,15 @@ public class SearchView extends LinearLayout {
        mQueryTextView.setOnEditorActionListener(mOnEditorActionListener);
        mQueryTextView.setOnItemClickListener(mOnItemClickListener);
        mQueryTextView.setOnItemSelectedListener(mOnItemSelectedListener);
        // Inform any listener of focus changes 
        mQueryTextView.setOnFocusChangeListener(new OnFocusChangeListener() {

            public void onFocusChange(View v, boolean hasFocus) {
                if (mOnQueryTextFocusChangeListener != null) {
                    mOnQueryTextFocusChangeListener.onFocusChange(SearchView.this, hasFocus);
                }
            }
        });

        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SearchView, 0, 0);
        setIconifiedByDefault(a.getBoolean(R.styleable.SearchView_iconifiedByDefault, true));
@@ -165,6 +203,27 @@ public class SearchView extends LinearLayout {
        updateViewsVisibility(mIconifiedByDefault);
    }

    /** @hide */
    @Override
    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
        if (mClearingFocus) return false;
        boolean result = mQueryTextView.requestFocus(direction, previouslyFocusedRect);
        if (result && !isIconified()) {
            setImeVisibility(true);
        }
        return result;
    }

    /** @hide */
    @Override
    public void clearFocus() {
        mClearingFocus = true;
        super.clearFocus();
        mQueryTextView.clearFocus();
        setImeVisibility(false);
        mClearingFocus = false;
    }

    /**
     * Sets a listener for user actions within the SearchView.
     *
@@ -184,6 +243,24 @@ public class SearchView extends LinearLayout {
        mOnCloseListener = listener;
    }

    /**
     * Sets a listener to inform when the focus of the query text field changes.
     *
     * @param listener the listener to inform of focus changes.
     */
    public void setOnQueryTextFocusChangeListener(OnFocusChangeListener listener) {
        mOnQueryTextFocusChangeListener = listener;
    }

    /**
     * Sets a listener to inform when a suggestion is focused or clicked.
     *
     * @param listener the listener to inform of suggestion selection events.
     */
    public void setOnSuggestionSelectionListener(OnSuggestionSelectionListener listener) {
        mOnSuggestionListener = listener;
    }

    /**
     * Sets a query string in the text field and optionally submits the query as well.
     *
@@ -224,6 +301,7 @@ public class SearchView extends LinearLayout {
    public void setIconifiedByDefault(boolean iconified) {
        mIconifiedByDefault = iconified;
        updateViewsVisibility(iconified);
        setImeVisibility(!iconified);
    }

    /**
@@ -340,17 +418,15 @@ public class SearchView extends LinearLayout {
        final int visCollapsed = collapsed ? VISIBLE : GONE;
        // Visibility of views that are visible when expanded
        final int visExpanded = collapsed ? GONE : VISIBLE;
        // Is there text in the query
        final boolean hasText = !TextUtils.isEmpty(mQueryTextView.getText());

        mSearchButton.setVisibility(visCollapsed);
        mSubmitButton.setVisibility(mSubmitButtonEnabled ? visExpanded : GONE);
        mSubmitButton.setVisibility(mSubmitButtonEnabled && hasText ? visExpanded : GONE);
        mSearchEditFrame.setVisibility(visExpanded);

        setImeVisibility(!collapsed);
    }

    private void setImeVisibility(boolean visible) {
        // don't mess with the soft input if we're not iconified by default
        if (mIconifiedByDefault) {
        InputMethodManager imm = (InputMethodManager)
        getContext().getSystemService(Context.INPUT_METHOD_SERVICE);

@@ -364,7 +440,6 @@ public class SearchView extends LinearLayout {
            }
        }
    }
    }

    /**
     * Called by the SuggestionsAdapter
@@ -478,6 +553,7 @@ public class SearchView extends LinearLayout {
                    || !mOnQueryChangeListener.onSubmitQuery(query.toString())) {
                if (mSearchable != null) {
                    launchQuerySearch(KeyEvent.KEYCODE_UNKNOWN, null, query.toString());
                    setImeVisibility(false);
                }
            }
        }
@@ -485,7 +561,14 @@ public class SearchView extends LinearLayout {

    private void onCloseClicked() {
        if (mOnCloseListener == null || !mOnCloseListener.onClose()) {
            CharSequence text = mQueryTextView.getText();
            if (TextUtils.isEmpty(text)) {
                // query field already empty, hide the keyboard and remove focus
                mQueryTextView.clearFocus();
                setImeVisibility(false);
            } else {
                mQueryTextView.setText("");
            }
            updateViewsVisibility(mIconifiedByDefault);
        }
    }
@@ -493,6 +576,7 @@ public class SearchView extends LinearLayout {
    private void onSearchClicked() {
        mQueryTextView.requestFocus();
        updateViewsVisibility(false);
        setImeVisibility(true);
    }

    private final OnItemClickListener mOnItemClickListener = new OnItemClickListener() {
@@ -503,8 +587,11 @@ public class SearchView extends LinearLayout {
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            if (DBG)
                Log.d(LOG_TAG, "onItemClick() position " + position);
            if (mOnSuggestionListener == null
                    || !mOnSuggestionListener.onSuggestionClicked(position)) {
                launchSuggestion(position, KeyEvent.KEYCODE_UNKNOWN, null);
            }
        }
    };

    private final OnItemSelectedListener mOnItemSelectedListener = new OnItemSelectedListener() {
@@ -517,8 +604,11 @@ public class SearchView extends LinearLayout {
                Log.d(LOG_TAG, "onItemSelected() position " + position);
            // A suggestion has been selected, rewrite the query if possible,
            // otherwise the restore the original query.
            if (mOnSuggestionListener == null
                    || !mOnSuggestionListener.onSuggestionSelected(position)) {
                rewriteQueryFromSuggestion(position);
            }
        }

        /**
         * Implements OnItemSelectedListener
@@ -722,13 +812,4 @@ public class SearchView extends LinearLayout {
        public void afterTextChanged(Editable s) {
        }
    };

    /*
     * Avoid getting focus when searching for something to focus on.
     * The user will have to touch the text view to get focus.
     */
    protected boolean onRequestFocusInDescendants(int direction,
            Rect previouslyFocusedRect) {
        return false;
    }
}