diff --git a/samples/AutofillKeyboard/src/com/example/android/autofillkeyboard/AutofillImeService.java b/samples/AutofillKeyboard/src/com/example/android/autofillkeyboard/AutofillImeService.java index 73e5a92ea..7b7971f82 100644 --- a/samples/AutofillKeyboard/src/com/example/android/autofillkeyboard/AutofillImeService.java +++ b/samples/AutofillKeyboard/src/com/example/android/autofillkeyboard/AutofillImeService.java @@ -23,6 +23,7 @@ import android.graphics.drawable.Icon; import android.inputmethodservice.InputMethodService; import android.os.Bundle; import android.os.Handler; +import android.os.Looper; import android.util.Log; import android.util.Size; import android.util.TypedValue; @@ -66,6 +67,7 @@ public class AutofillImeService extends InputMethodService { private static final long MOVE_SUGGESTIONS_DOWN_TIMEOUT = 10000; private InputView mInputView; + private Keyboard mKeyboard; private Decoder mDecoder; private ViewGroup mSuggestionStrip; @@ -74,6 +76,8 @@ public class AutofillImeService extends InputMethodService { private InlineContentClipView mScrollableSuggestionsClip; private ViewGroup mScrollableSuggestions; + private final Handler mHandler = new Handler(Looper.getMainLooper()); + private final Runnable mMoveScrollableSuggestionsToBg = () -> { mScrollableSuggestionsClip.setZOrderedOnTop(false); Toast.makeText(AutofillImeService.this, "Chips moved to bg - not clickable", @@ -101,6 +105,13 @@ public class AutofillImeService extends InputMethodService { @Override public View onCreateInputView() { mInputView = (InputView) LayoutInflater.from(this).inflate(R.layout.input_view, null); + mKeyboard = Keyboard.qwerty(this); + mInputView.addView(mKeyboard.inflateKeyboardView(LayoutInflater.from(this), mInputView)); + mSuggestionStrip = mInputView.findViewById(R.id.suggestion_strip); + mPinnedSuggestionsStart = mInputView.findViewById(R.id.pinned_suggestions_start); + mPinnedSuggestionsEnd = mInputView.findViewById(R.id.pinned_suggestions_end); + mScrollableSuggestionsClip = mInputView.findViewById(R.id.scrollable_suggestions_clip); + mScrollableSuggestions = mInputView.findViewById(R.id.scrollable_suggestions); return mInputView; } @@ -108,23 +119,42 @@ public class AutofillImeService extends InputMethodService { public void onStartInput(EditorInfo attribute, boolean restarting) { super.onStartInput(attribute, restarting); mDecoder = new Decoder(getCurrentInputConnection()); + if(mKeyboard != null) { + mKeyboard.reset(); + } + if (mInputView != null) { + // We delay the deletion of the suggestions from previous input connection, to avoid + // the flicker caused by deleting them and immediately showing new suggestions for + // the current input connection. + Log.d(TAG, "onStartInput scheduling a delayed deletion of inline suggestions"); + mDelayedDeletion = () -> { + Log.d(TAG, "onStartInput deleting inline suggestions"); + mDelayedDeletion = null; + updateInlineSuggestionStrip(Collections.emptyList()); + }; + mHandler.postDelayed(mDelayedDeletion, 200); + } } + private Runnable mDelayedDeletion; + @Override public void onStartInputView(EditorInfo info, boolean restarting) { super.onStartInputView(info, restarting); + } - mInputView.removeAllViews(); - Keyboard keyboard = Keyboard.qwerty(this); - mInputView.addView(keyboard.inflateKeyboardView(LayoutInflater.from(this), mInputView)); - - mSuggestionStrip = mInputView.findViewById(R.id.suggestion_strip); - mPinnedSuggestionsStart = mInputView.findViewById(R.id.pinned_suggestions_start); - mPinnedSuggestionsEnd = mInputView.findViewById(R.id.pinned_suggestions_end); - mScrollableSuggestionsClip = mInputView.findViewById(R.id.scrollable_suggestions_clip); - mScrollableSuggestions = mInputView.findViewById(R.id.scrollable_suggestions); - - updateInlineSuggestionStrip(Collections.emptyList()); + @Override + public void onFinishInputView(boolean finishingInput) { + super.onFinishInputView(finishingInput); + if (!finishingInput) { + // This runs when the IME is hide (but not finished). We need to clear the suggestions. + // Otherwise, they will stay on the screen for a bit after the IME window disappears. + // TODO: right now the framework resends the suggestions when onStartInputView is + // called. If the framework is changed to not resend, then we need to cache the + // inline suggestion views locally and re-attach them when the IME is shown again by + // onStartInputView. + updateInlineSuggestionStrip(Collections.emptyList()); + } } @Override @@ -198,6 +228,10 @@ public class AutofillImeService extends InputMethodService { @Override public boolean onInlineSuggestionsResponse(InlineSuggestionsResponse response) { Log.d(TAG, "onInlineSuggestionsResponse() called"); + if(mDelayedDeletion != null) { + Log.d(TAG, "onInlineSuggestionsResponse unscheduling delayed deletion"); + mHandler.removeCallbacks(mDelayedDeletion); + } onInlineSuggestionsResponseInternal(response); return true; } @@ -209,7 +243,6 @@ public class AutofillImeService extends InputMethodService { final int size = suggestionItems.size(); if (size <= 0) { - mSuggestionStrip.setVisibility(View.GONE); return; } diff --git a/samples/AutofillKeyboard/src/com/example/android/autofillkeyboard/Keyboard.java b/samples/AutofillKeyboard/src/com/example/android/autofillkeyboard/Keyboard.java index e7b279e1f..334cdf5dd 100644 --- a/samples/AutofillKeyboard/src/com/example/android/autofillkeyboard/Keyboard.java +++ b/samples/AutofillKeyboard/src/com/example/android/autofillkeyboard/Keyboard.java @@ -102,6 +102,11 @@ final class Keyboard { return mKeyboardView; } + void reset() { + mState = 0; + mapKeys(); + } + private void mapKeys() { for (int i = 0; i < mKeyMapping.size(); i++) { TextView softkey = mKeyboardView.findViewById(mKeyMapping.keyAt(i));