summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/widget/SearchView.java101
1 files changed, 63 insertions, 38 deletions
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index 38221383df3f..519a7dd8be43 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -58,6 +58,7 @@ import android.view.TouchDelegate;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemSelectedListener;
@@ -159,20 +160,6 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
private SearchableInfo mSearchable;
private Bundle mAppSearchData;
- /*
- * SearchView can be set expanded before the IME is ready to be shown during
- * initial UI setup. The show operation is asynchronous to account for this.
- */
- private Runnable mShowImeRunnable = new Runnable() {
- public void run() {
- InputMethodManager imm = getContext().getSystemService(InputMethodManager.class);
-
- if (imm != null) {
- imm.showSoftInputUnchecked(0, null);
- }
- }
- };
-
private Runnable mUpdateDrawableStateRunnable = new Runnable() {
public void run() {
updateFocusedState();
@@ -497,9 +484,9 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
@Override
public void clearFocus() {
mClearingFocus = true;
- setImeVisibility(false);
super.clearFocus();
mSearchSrcTextView.clearFocus();
+ mSearchSrcTextView.setImeVisibility(false);
mClearingFocus = false;
}
@@ -967,19 +954,6 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
super.onDetachedFromWindow();
}
- private void setImeVisibility(final boolean visible) {
- if (visible) {
- post(mShowImeRunnable);
- } else {
- removeCallbacks(mShowImeRunnable);
- InputMethodManager imm = getContext().getSystemService(InputMethodManager.class);
-
- if (imm != null) {
- imm.hideSoftInputFromWindow(getWindowToken(), 0);
- }
- }
- }
-
/**
* Called by the SuggestionsAdapter
* @hide
@@ -1286,7 +1260,7 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
if (mSearchable != null) {
launchQuerySearch(KeyEvent.KEYCODE_UNKNOWN, null, query.toString());
}
- setImeVisibility(false);
+ mSearchSrcTextView.setImeVisibility(false);
dismissSuggestions();
}
}
@@ -1311,7 +1285,7 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
} else {
mSearchSrcTextView.setText("");
mSearchSrcTextView.requestFocus();
- setImeVisibility(true);
+ mSearchSrcTextView.setImeVisibility(true);
}
}
@@ -1319,7 +1293,7 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
private void onSearchClicked() {
updateViewsVisibility(false);
mSearchSrcTextView.requestFocus();
- setImeVisibility(true);
+ mSearchSrcTextView.setImeVisibility(true);
if (mOnSearchClickListener != null) {
mOnSearchClickListener.onClick(this);
}
@@ -1477,7 +1451,7 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
if (mOnSuggestionListener == null
|| !mOnSuggestionListener.onSuggestionClick(position)) {
launchSuggestion(position, KeyEvent.KEYCODE_UNKNOWN, null);
- setImeVisibility(false);
+ mSearchSrcTextView.setImeVisibility(false);
dismissSuggestions();
return true;
}
@@ -1910,6 +1884,9 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
private int mThreshold;
private SearchView mSearchView;
+ private boolean mHasPendingShowSoftInputRequest;
+ final Runnable mRunShowSoftInputIfNecessary = () -> showSoftInputIfNecessary();
+
public SearchAutoComplete(Context context) {
super(context);
mThreshold = getThreshold();
@@ -1983,11 +1960,13 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
super.onWindowFocusChanged(hasWindowFocus);
if (hasWindowFocus && mSearchView.hasFocus() && getVisibility() == VISIBLE) {
- InputMethodManager inputManager =
- getContext().getSystemService(InputMethodManager.class);
- inputManager.showSoftInput(this, 0);
- // If in landscape mode, then make sure that
- // the ime is in front of the dropdown.
+ // Since InputMethodManager#onPostWindowFocus() will be called after this callback,
+ // it is a bit too early to call InputMethodManager#showSoftInput() here. We still
+ // need to wait until the system calls back onCreateInputConnection() to call
+ // InputMethodManager#showSoftInput().
+ mHasPendingShowSoftInputRequest = true;
+
+ // If in landscape mode, then make sure that the ime is in front of the dropdown.
if (isLandscapeMode(getContext())) {
ensureImeVisible(true);
}
@@ -2027,7 +2006,7 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
}
if (event.isTracking() && !event.isCanceled()) {
mSearchView.clearFocus();
- mSearchView.setImeVisibility(false);
+ setImeVisibility(false);
return true;
}
}
@@ -2051,5 +2030,51 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
};
return 160;
}
+
+ /**
+ * We override {@link View#onCreateInputConnection(EditorInfo)} as a signal to schedule a
+ * pending {@link InputMethodManager#showSoftInput(View, int)} request (if any).
+ */
+ @Override
+ public InputConnection onCreateInputConnection(EditorInfo editorInfo) {
+ final InputConnection ic = super.onCreateInputConnection(editorInfo);
+ if (mHasPendingShowSoftInputRequest) {
+ removeCallbacks(mRunShowSoftInputIfNecessary);
+ post(mRunShowSoftInputIfNecessary);
+ }
+ return ic;
+ }
+
+ private void showSoftInputIfNecessary() {
+ if (mHasPendingShowSoftInputRequest) {
+ final InputMethodManager imm =
+ getContext().getSystemService(InputMethodManager.class);
+ imm.showSoftInput(this, 0);
+ mHasPendingShowSoftInputRequest = false;
+ }
+ }
+
+ private void setImeVisibility(final boolean visible) {
+ final InputMethodManager imm = getContext().getSystemService(InputMethodManager.class);
+ if (!visible) {
+ mHasPendingShowSoftInputRequest = false;
+ removeCallbacks(mRunShowSoftInputIfNecessary);
+ imm.hideSoftInputFromWindow(getWindowToken(), 0);
+ return;
+ }
+
+ if (imm.isActive(this)) {
+ // This means that SearchAutoComplete is already connected to the IME.
+ // InputMethodManager#showSoftInput() is guaranteed to pass client-side focus check.
+ mHasPendingShowSoftInputRequest = false;
+ removeCallbacks(mRunShowSoftInputIfNecessary);
+ imm.showSoftInput(this, 0);
+ return;
+ }
+
+ // Otherwise, InputMethodManager#showSoftInput() should be deferred after
+ // onCreateInputConnection().
+ mHasPendingShowSoftInputRequest = true;
+ }
}
}