Fast key preview

Previously the key preview was implemented by PopupWindow.  The key
preview popup window would be dismissed and shown each time the key
was released and pressed.  It turned out that it was taking several
milliseconds.

This change implements the key preview by a simple TextView which will
be layout-ed at absolute coordinates within the screen FrameLayout.
And dismissing and showing the key preview is implemented by the
TextView's visibility.

This implementation needs careful coordination of candidates.xml
layout and LatinIME.onComputeInsets to control suggestion strip
visibility.

Bug: 4179964
Change-Id: Id6347cb35b91eb14ab20dd2f312e58b54b6625a7
main
Tadashi G. Takaoka 2011-04-13 14:12:24 +09:00
parent 47d2ef69d3
commit 7a3d3ae17f
15 changed files with 98 additions and 206 deletions

View File

@ -1,29 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
**
** Copyright 2010, 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.
*/
-->
<set
xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/decelerate_interpolator"
>
<alpha
android:fromAlpha="0.5"
android:toAlpha="1.0"
android:duration="@integer/config_preview_fadein_anim_time" />
</set>

View File

@ -1,29 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
**
** Copyright 2010, 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.
*/
-->
<set
xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_interpolator"
>
<alpha
android:fromAlpha="1.0"
android:toAlpha="0.0"
android:duration="@integer/config_preview_fadeout_anim_time" />
</set>

View File

@ -25,5 +25,5 @@
<alpha
android:fromAlpha="0.5"
android:toAlpha="1.0"
android:duration="@integer/config_preview_fadein_anim_time" />
android:duration="@integer/config_mini_keyboard_fadein_anim_time" />
</set>

View File

@ -25,5 +25,5 @@
<alpha
android:fromAlpha="1.0"
android:toAlpha="0.0"
android:duration="@integer/config_preview_fadeout_anim_time" />
android:duration="@integer/config_mini_keyboard_fadeout_anim_time" />
</set>

View File

@ -21,25 +21,33 @@
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:gravity="bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/keyboard_suggest_strip_holo"
android:paddingRight="@dimen/candidate_strip_padding"
android:paddingLeft="@dimen/candidate_strip_padding"
android:minHeight="@dimen/candidate_strip_minimum_height"
>
<HorizontalScrollView
android:id="@+id/candidates_scroll_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fadingEdge="horizontal"
android:fadingEdgeLength="@dimen/candidate_strip_fading_edge_length"
android:scrollbars="none"
<!-- On tablets, the candidate strip is centered with horizontal paddings on both sides because
width of the landscape mode is too long for the candidate strip. This LinearLayout is
required to hold the paddings. -->
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="@dimen/candidate_strip_height"
android:background="@drawable/keyboard_suggest_strip_holo"
android:paddingRight="@dimen/candidate_strip_padding"
android:paddingLeft="@dimen/candidate_strip_padding"
>
<com.android.inputmethod.latin.CandidateView
android:id="@+id/candidates"
android:orientation="horizontal"
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="@dimen/candidate_strip_height"
android:background="@drawable/keyboard_suggest_strip_holo" />
</HorizontalScrollView>
android:layout_height="match_parent"
android:fadingEdge="horizontal"
android:fadingEdgeLength="@dimen/candidate_strip_fading_edge_length"
android:scrollbars="none"
>
<com.android.inputmethod.latin.CandidateView
android:id="@+id/candidates"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</HorizontalScrollView>
</LinearLayout>
</LinearLayout>

View File

@ -21,25 +21,24 @@
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:gravity="bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/keyboard_suggest_strip"
android:minHeight="@dimen/candidate_strip_minimum_height"
android:paddingRight="@dimen/candidate_strip_padding"
android:paddingLeft="@dimen/candidate_strip_padding"
>
<HorizontalScrollView
android:id="@+id/candidates_scroll_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_height="@dimen/candidate_strip_height"
android:background="@drawable/keyboard_suggest_strip"
android:fadingEdge="horizontal"
android:fadingEdgeLength="@dimen/candidate_strip_fading_edge_length"
android:scrollbars="none"
>
<com.android.inputmethod.latin.CandidateView
android:id="@+id/candidates"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="@dimen/candidate_strip_height"
android:background="@drawable/keyboard_suggest_strip" />
android:layout_height="match_parent" />
</HorizontalScrollView>
</LinearLayout>

View File

@ -46,6 +46,9 @@
<dimen name="key_preview_offset_holo">8.0mm</dimen>
<dimen name="candidate_strip_height">46dip</dimen>
<!-- candidate_strip_minimum_height =
key_preview_height_holo - key_preview_offset_holo + alpha -->
<dimen name="candidate_strip_minimum_height">18mm</dimen>
<dimen name="candidate_strip_padding">15.0mm</dimen>
<dimen name="candidate_min_width">0.3in</dimen>
<dimen name="candidate_padding">12dip</dimen>

View File

@ -49,8 +49,6 @@
<integer name="config_final_fadeout_percentage_of_language_on_spacebar">15</integer>
<integer name="config_delay_before_preview">0</integer>
<integer name="config_delay_after_preview">10</integer>
<integer name="config_preview_fadein_anim_time">0</integer>
<integer name="config_preview_fadeout_anim_time">70</integer>
<integer name="config_mini_keyboard_fadein_anim_time">0</integer>
<integer name="config_mini_keyboard_fadeout_anim_time">100</integer>
<integer name="config_delay_before_key_repeat_start">400</integer>

View File

@ -52,6 +52,9 @@
<dimen name="key_preview_offset_holo">0.193in</dimen>
<dimen name="candidate_strip_height">42dip</dimen>
<!-- candidate_strip_minimum_height =
key_preview_height_holo - key_preview_offset_holo + alpha -->
<dimen name="candidate_strip_minimum_height">100sp</dimen>
<dimen name="candidate_strip_fading_edge_length">63dip</dimen>
<dimen name="candidate_strip_padding">0dip</dimen>
<dimen name="candidate_min_width">0.3in</dimen>

View File

@ -35,10 +35,6 @@
<item name="backgroundDimAmount">0.5</item>
<item name="colorScheme">white</item>
</style>
<style name="KeyPreviewAnimation">
<item name="android:windowEnterAnimation">@anim/key_preview_fadein</item>
<item name="android:windowExitAnimation">@anim/key_preview_fadeout</item>
</style>
<style name="MiniKeyboardAnimation">
<item name="android:windowEnterAnimation">@anim/mini_keyboard_fadein</item>
<item name="android:windowExitAnimation">@anim/mini_keyboard_fadeout</item>

View File

@ -19,20 +19,9 @@ package com.android.inputmethod.compat;
import com.android.inputmethod.latin.SubtypeSwitcher;
import android.inputmethodservice.InputMethodService;
import android.view.View;
import android.view.inputmethod.InputMethodSubtype;
import android.widget.HorizontalScrollView;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class InputMethodServiceCompatWrapper extends InputMethodService {
private static final Method METHOD_HorizontalScrollView_setOverScrollMode =
CompatUtils.getMethod(HorizontalScrollView.class, "setOverScrollMode", int.class);
private static final Field FIELD_View_OVER_SCROLL_NEVER =
CompatUtils.getField(View.class, "OVER_SCROLL_NEVER");
private static final Integer View_OVER_SCROLL_NEVER =
(Integer)CompatUtils.getFieldValue(null, null, FIELD_View_OVER_SCROLL_NEVER);
// CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED needs to be false if the API level is 10
// or previous. Note that InputMethodSubtype was added in the API level 11.
// For the API level 11 or later, LatinIME should override onCurrentInputMethodSubtypeChanged().
@ -66,13 +55,6 @@ public class InputMethodServiceCompatWrapper extends InputMethodService {
}
}
protected static void setOverScrollModeNever(HorizontalScrollView scrollView) {
if (View_OVER_SCROLL_NEVER != null) {
CompatUtils.invoke(scrollView, null, METHOD_HorizontalScrollView_setOverScrollMode,
View_OVER_SCROLL_NEVER);
}
}
//////////////////////////////////////
// Functions using API v11 or later //
//////////////////////////////////////

View File

@ -45,8 +45,8 @@ import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.PopupWindow;
import android.widget.TextView;
@ -110,14 +110,12 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
// Key preview popup
private boolean mInForeground;
private TextView mPreviewText;
private PopupWindow mPreviewPopup;
private int mPreviewTextSizeLarge;
private int[] mOffsetInWindow;
private final int[] mOffsetInWindow = new int[2];
private int mOldPreviewKeyIndex = KeyDetector.NOT_A_KEY;
private boolean mShowPreview = true;
private int mPopupPreviewOffsetX;
private int mPopupPreviewOffsetY;
private int mWindowY;
private int mPopupPreviewDisplayedY;
private final int mDelayBeforePreview;
private final int mDelayAfterPreview;
@ -125,7 +123,6 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
// Popup mini keyboard
private PopupWindow mMiniKeyboardPopup;
private KeyboardView mMiniKeyboardView;
private View mMiniKeyboardParent;
private final WeakHashMap<Key, View> mMiniKeyboardCache = new WeakHashMap<Key, View>();
private int mMiniKeyboardOriginX;
private int mMiniKeyboardOriginY;
@ -204,7 +201,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
showKey(msg.arg1, (PointerTracker)msg.obj);
break;
case MSG_DISMISS_PREVIEW:
mPreviewPopup.dismiss();
mPreviewText.setVisibility(View.INVISIBLE);
break;
case MSG_REPEAT_KEY: {
final PointerTracker tracker = (PointerTracker)msg.obj;
@ -227,12 +224,11 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
public void popupPreview(long delay, int keyIndex, PointerTracker tracker) {
removeMessages(MSG_POPUP_PREVIEW);
if (mPreviewPopup.isShowing() && mPreviewText.getVisibility() == VISIBLE) {
if (mPreviewText.getVisibility() == VISIBLE) {
// Show right away, if it's already visible and finger is moving around
showKey(keyIndex, tracker);
} else {
sendMessageDelayed(obtainMessage(MSG_POPUP_PREVIEW, keyIndex, 0, tracker),
delay);
sendMessageDelayed(obtainMessage(MSG_POPUP_PREVIEW, keyIndex, 0, tracker), delay);
}
}
@ -241,9 +237,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
}
public void dismissPreview(long delay) {
if (mPreviewPopup.isShowing()) {
sendMessageDelayed(obtainMessage(MSG_DISMISS_PREVIEW), delay);
}
sendMessageDelayed(obtainMessage(MSG_DISMISS_PREVIEW), delay);
}
public void cancelDismissPreview() {
@ -366,24 +360,17 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
final Resources res = getResources();
mPreviewPopup = new PopupWindow(context);
if (previewLayout != 0) {
mPreviewText = (TextView) LayoutInflater.from(context).inflate(previewLayout, null);
mPreviewTextSizeLarge = (int) res.getDimension(R.dimen.key_preview_text_size_large);
mPreviewPopup.setContentView(mPreviewText);
mPreviewPopup.setBackgroundDrawable(null);
} else {
mShowPreview = false;
}
mPreviewPopup.setTouchable(false);
mPreviewPopup.setAnimationStyle(R.style.KeyPreviewAnimation);
mPreviewPopup.setClippingEnabled(false);
mDelayBeforePreview = res.getInteger(R.integer.config_delay_before_preview);
mDelayAfterPreview = res.getInteger(R.integer.config_delay_after_preview);
mKeyLabelHorizontalPadding = (int)res.getDimension(
R.dimen.key_label_horizontal_alignment_padding);
mMiniKeyboardParent = this;
mMiniKeyboardPopup = new PopupWindow(context);
mMiniKeyboardPopup.setBackgroundDrawable(null);
mMiniKeyboardPopup.setAnimationStyle(R.style.MiniKeyboardAnimation);
@ -583,7 +570,6 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
public void setPopupOffset(int x, int y) {
mPopupPreviewOffsetX = x;
mPopupPreviewOffsetY = y;
mPreviewPopup.dismiss();
}
/**
@ -915,8 +901,16 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
}
}
// TODO Must fix popup preview on xlarge layout
// TODO: Introduce minimum duration for displaying key previews
// TODO: Display up to two key previews when the user presses two keys at the same time
private void showKey(final int keyIndex, PointerTracker tracker) {
// If the preview popup has no parent view yet, add it to the screen FrameLayout.
if (mPreviewText.getParent() == null) {
final FrameLayout screenContent = (FrameLayout) getRootView()
.findViewById(android.R.id.content);
screenContent.addView(mPreviewText, new FrameLayout.LayoutParams(0, 0));
}
Key key = tracker.getKey(keyIndex);
// If keyIndex is invalid or IME is already closed, we must not show key preview.
// Trying to show preview PopupWindow while root window is closed causes
@ -948,7 +942,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
int popupWidth = Math.max(mPreviewText.getMeasuredWidth(), keyDrawWidth
+ mPreviewText.getPaddingLeft() + mPreviewText.getPaddingRight());
final int popupHeight = mPreviewHeight;
LayoutParams lp = mPreviewText.getLayoutParams();
final ViewGroup.LayoutParams lp = mPreviewText.getLayoutParams();
if (lp != null) {
lp.width = popupWidth;
lp.height = popupHeight;
@ -958,47 +952,23 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
int popupPreviewY = key.mY - popupHeight + mPreviewOffset;
mHandler.cancelDismissPreview();
if (mOffsetInWindow == null) {
mOffsetInWindow = new int[2];
getLocationInWindow(mOffsetInWindow);
mOffsetInWindow[0] += mPopupPreviewOffsetX; // Offset may be zero
mOffsetInWindow[1] += mPopupPreviewOffsetY; // Offset may be zero
int[] windowLocation = new int[2];
getLocationOnScreen(windowLocation);
mWindowY = windowLocation[1];
}
getLocationInWindow(mOffsetInWindow);
mOffsetInWindow[0] += mPopupPreviewOffsetX; // Offset may be zero
mOffsetInWindow[1] += mPopupPreviewOffsetY; // Offset may be zero
// Set the preview background state
mPreviewText.getBackground().setState(
key.mPopupCharacters != null ? LONG_PRESSABLE_STATE_SET : EMPTY_STATE_SET);
popupPreviewX += mOffsetInWindow[0];
popupPreviewY += mOffsetInWindow[1];
// If the popup cannot be shown above the key, put it on the side
if (popupPreviewY + mWindowY < 0) {
// If the key you're pressing is on the left side of the keyboard, show the popup on
// the right, offset by enough to see at least one key to the left/right.
if (keyDrawX + keyDrawWidth <= getWidth() / 2) {
popupPreviewX += (int) (keyDrawWidth * 2.5);
} else {
popupPreviewX -= (int) (keyDrawWidth * 2.5);
}
popupPreviewY += popupHeight;
// Place the key preview.
// TODO: Adjust position of key previews which touch screen edges
if (lp instanceof ViewGroup.MarginLayoutParams) {
ViewGroup.MarginLayoutParams mlp = (ViewGroup.MarginLayoutParams)lp;
mlp.setMargins(popupPreviewX, popupPreviewY, 0, 0);
}
try {
if (mPreviewPopup.isShowing()) {
mPreviewPopup.update(popupPreviewX, popupPreviewY, popupWidth, popupHeight);
} else {
mPreviewPopup.setWidth(popupWidth);
mPreviewPopup.setHeight(popupHeight);
mPreviewPopup.showAtLocation(mMiniKeyboardParent, Gravity.NO_GRAVITY,
popupPreviewX, popupPreviewY);
}
} catch (WindowManager.BadTokenException e) {
// Swallow the exception which will be happened when IME is already closed.
Log.w(TAG, "LatinIME is already closed when tried showing key preview.");
}
// Record popup preview position to display mini-keyboard later at the same positon
// Record popup preview position to display mini-keyboard later at the same position
mPopupPreviewDisplayedY = popupPreviewY;
mPreviewText.setVisibility(VISIBLE);
}
@ -1114,7 +1084,6 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
final Keyboard keyboard = new MiniKeyboardBuilder(this, mKeyboard.getPopupKeyboardResId(),
popupKey).build();
miniKeyboardView.setKeyboard(keyboard);
miniKeyboardView.mMiniKeyboardParent = this;
container.measure(MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.AT_MOST),
MeasureSpec.makeMeasureSpec(getHeight(), MeasureSpec.AT_MOST));
@ -1349,7 +1318,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
}
public void closing() {
mPreviewPopup.dismiss();
mPreviewText.setVisibility(View.GONE);
mHandler.cancelAllMessages();
dismissPopupKeyboard();

View File

@ -549,7 +549,6 @@ public class PointerTracker {
final Key key = getKey(keyIndex);
if (key != null && !key.mEnabled)
return;
updateKeyGraphics(keyIndex);
// The modifier key, such as shift key, should not be shown as preview when multi-touch is
// supported. On the other hand, if multi-touch is not supported, the modifier key should
// be shown as preview. If accessibility is turned on, the modifier key should be shown as
@ -559,6 +558,7 @@ public class PointerTracker {
} else {
mProxy.showPreview(keyIndex, this);
}
updateKeyGraphics(keyIndex);
}
private void startLongPressTimer(int keyIndex) {

View File

@ -133,7 +133,6 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
ViewGroup.LayoutParams.WRAP_CONTENT);
mPreviewPopup.setContentView(mPreviewText);
mPreviewPopup.setBackgroundDrawable(null);
mPreviewPopup.setAnimationStyle(R.style.KeyPreviewAnimation);
mConfigCandidateHighlightFontColorEnabled =
res.getBoolean(R.bool.config_candidate_highlight_font_color_enabled);
mColorNormal = res.getColor(R.color.candidate_normal);

View File

@ -56,7 +56,6 @@ import android.util.DisplayMetrics;
import android.util.Log;
import android.util.PrintWriterPrinter;
import android.util.Printer;
import android.view.Gravity;
import android.view.HapticFeedbackConstants;
import android.view.KeyEvent;
import android.view.LayoutInflater;
@ -70,8 +69,6 @@ import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.ExtractedText;
import android.view.inputmethod.ExtractedTextRequest;
import android.view.inputmethod.InputConnection;
import android.widget.FrameLayout;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
import java.io.FileDescriptor;
@ -143,6 +140,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
};
private View mCandidateViewContainer;
private int mCandidateStripHeight;
private CandidateView mCandidateView;
private Suggest mSuggest;
private CompletionInfo[] mApplicationSpecifiedCompletions;
@ -528,12 +526,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
LayoutInflater inflater = getLayoutInflater();
LinearLayout container = (LinearLayout)inflater.inflate(R.layout.candidates, null);
mCandidateViewContainer = container;
if (container.getPaddingRight() != 0) {
HorizontalScrollView scrollView =
(HorizontalScrollView) container.findViewById(R.id.candidates_scroll_view);
setOverScrollModeNever(scrollView);
container.setGravity(Gravity.CENTER_HORIZONTAL);
}
mCandidateStripHeight = (int)mResources.getDimension(R.dimen.candidate_strip_height);
mCandidateView = (CandidateView) container.findViewById(R.id.candidates);
mCandidateView.setService(this);
setCandidatesViewShown(true);
@ -581,8 +574,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
switcher.updateShiftState();
}
setCandidatesViewShownInternal(isCandidateStripVisible(),
false /* needsInputViewShown */ );
setCandidatesViewShownInternal(isCandidateStripVisible(), false /* needsInputViewShown */ );
// Delay updating suggestions because keyboard input view may not be shown at this point.
mHandler.postUpdateSuggestions();
@ -872,10 +864,21 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
}
private void setCandidatesViewShownInternal(boolean shown, boolean needsInputViewShown) {
// TODO: Remove this if we support candidates with hard keyboard
// TODO: Modify this if we support candidates with hard keyboard
if (onEvaluateInputViewShown()) {
super.setCandidatesViewShown(shown
&& (needsInputViewShown ? mKeyboardSwitcher.isInputViewShown() : true));
final boolean shouldShowCandidates = shown
&& (needsInputViewShown ? mKeyboardSwitcher.isInputViewShown() : true);
if (isExtractViewShown()) {
// No need to have extra space to show the key preview.
mCandidateViewContainer.setMinimumHeight(0);
super.setCandidatesViewShown(shown);
} else {
// We must control the visibility of the suggestion strip in order to avoid clipped
// key previews, even when we don't show the suggestion strip.
mCandidateViewContainer.setVisibility(
shouldShowCandidates ? View.VISIBLE : View.INVISIBLE);
super.setCandidatesViewShown(true);
}
}
}
@ -887,35 +890,25 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
@Override
public void onComputeInsets(InputMethodService.Insets outInsets) {
super.onComputeInsets(outInsets);
if (!isFullscreenMode()) {
outInsets.contentTopInsets = outInsets.visibleTopInsets;
}
KeyboardView inputView = mKeyboardSwitcher.getInputView();
final KeyboardView inputView = mKeyboardSwitcher.getInputView();
// Need to set touchable region only if input view is being shown
if (inputView != null && mKeyboardSwitcher.isInputViewShown()) {
final int x = 0;
int y = 0;
final int width = inputView.getWidth();
int height = inputView.getHeight() + EXTENDED_TOUCHABLE_REGION_HEIGHT;
if (mCandidateViewContainer != null) {
ViewParent candidateParent = mCandidateViewContainer.getParent();
if (candidateParent instanceof FrameLayout) {
FrameLayout fl = (FrameLayout) candidateParent;
if (fl != null) {
// Check frame layout's visibility
if (fl.getVisibility() == View.INVISIBLE) {
y = fl.getHeight();
height += y;
} else if (fl.getVisibility() == View.VISIBLE) {
height += fl.getHeight();
}
}
}
final int containerHeight = mCandidateViewContainer.getHeight();
int touchY = containerHeight;
if (mCandidateViewContainer.getVisibility() == View.VISIBLE) {
touchY -= mCandidateStripHeight;
}
outInsets.contentTopInsets = touchY;
outInsets.visibleTopInsets = touchY;
final int touchWidth = inputView.getWidth();
final int touchHeight = inputView.getHeight() + containerHeight
// Extend touchable region below the keyboard.
+ EXTENDED_TOUCHABLE_REGION_HEIGHT;
if (DEBUG) {
Log.d(TAG, "Touchable region " + x + ", " + y + ", " + width + ", " + height);
Log.d(TAG, "Touchable region: y=" + touchY + " width=" + touchWidth
+ " height=" + touchHeight);
}
setTouchableRegionCompat(outInsets, x, y, width, height);
setTouchableRegionCompat(outInsets, 0, touchY, touchWidth, touchHeight);
}
}