Merge "Fast key preview"

This commit is contained in:
Tadashi G. Takaoka 2011-04-13 03:12:06 -07:00 committed by Android (Google) Code Review
commit dc3d4e8c06
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 <alpha
android:fromAlpha="0.5" android:fromAlpha="0.5"
android:toAlpha="1.0" android:toAlpha="1.0"
android:duration="@integer/config_preview_fadein_anim_time" /> android:duration="@integer/config_mini_keyboard_fadein_anim_time" />
</set> </set>

View File

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

View File

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

View File

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

View File

@ -46,6 +46,9 @@
<dimen name="key_preview_offset_holo">8.0mm</dimen> <dimen name="key_preview_offset_holo">8.0mm</dimen>
<dimen name="candidate_strip_height">46dip</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_strip_padding">15.0mm</dimen>
<dimen name="candidate_min_width">0.3in</dimen> <dimen name="candidate_min_width">0.3in</dimen>
<dimen name="candidate_padding">12dip</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_final_fadeout_percentage_of_language_on_spacebar">15</integer>
<integer name="config_delay_before_preview">0</integer> <integer name="config_delay_before_preview">0</integer>
<integer name="config_delay_after_preview">10</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_fadein_anim_time">0</integer>
<integer name="config_mini_keyboard_fadeout_anim_time">100</integer> <integer name="config_mini_keyboard_fadeout_anim_time">100</integer>
<integer name="config_delay_before_key_repeat_start">400</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="key_preview_offset_holo">0.193in</dimen>
<dimen name="candidate_strip_height">42dip</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_fading_edge_length">63dip</dimen>
<dimen name="candidate_strip_padding">0dip</dimen> <dimen name="candidate_strip_padding">0dip</dimen>
<dimen name="candidate_min_width">0.3in</dimen> <dimen name="candidate_min_width">0.3in</dimen>

View File

@ -35,10 +35,6 @@
<item name="backgroundDimAmount">0.5</item> <item name="backgroundDimAmount">0.5</item>
<item name="colorScheme">white</item> <item name="colorScheme">white</item>
</style> </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"> <style name="MiniKeyboardAnimation">
<item name="android:windowEnterAnimation">@anim/mini_keyboard_fadein</item> <item name="android:windowEnterAnimation">@anim/mini_keyboard_fadein</item>
<item name="android:windowExitAnimation">@anim/mini_keyboard_fadeout</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 com.android.inputmethod.latin.SubtypeSwitcher;
import android.inputmethodservice.InputMethodService; import android.inputmethodservice.InputMethodService;
import android.view.View;
import android.view.inputmethod.InputMethodSubtype; import android.view.inputmethod.InputMethodSubtype;
import android.widget.HorizontalScrollView;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class InputMethodServiceCompatWrapper extends InputMethodService { 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 // 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. // or previous. Note that InputMethodSubtype was added in the API level 11.
// For the API level 11 or later, LatinIME should override onCurrentInputMethodSubtypeChanged(). // 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 // // Functions using API v11 or later //
////////////////////////////////////// //////////////////////////////////////

View File

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

View File

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

View File

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

View File

@ -57,7 +57,6 @@ import android.util.DisplayMetrics;
import android.util.Log; import android.util.Log;
import android.util.PrintWriterPrinter; import android.util.PrintWriterPrinter;
import android.util.Printer; import android.util.Printer;
import android.view.Gravity;
import android.view.HapticFeedbackConstants; import android.view.HapticFeedbackConstants;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -71,8 +70,6 @@ import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.ExtractedText; import android.view.inputmethod.ExtractedText;
import android.view.inputmethod.ExtractedTextRequest; import android.view.inputmethod.ExtractedTextRequest;
import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputConnection;
import android.widget.FrameLayout;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import java.io.FileDescriptor; import java.io.FileDescriptor;
@ -144,6 +141,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
}; };
private View mCandidateViewContainer; private View mCandidateViewContainer;
private int mCandidateStripHeight;
private CandidateView mCandidateView; private CandidateView mCandidateView;
private Suggest mSuggest; private Suggest mSuggest;
private CompletionInfo[] mApplicationSpecifiedCompletions; private CompletionInfo[] mApplicationSpecifiedCompletions;
@ -533,12 +531,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
LayoutInflater inflater = getLayoutInflater(); LayoutInflater inflater = getLayoutInflater();
LinearLayout container = (LinearLayout)inflater.inflate(R.layout.candidates, null); LinearLayout container = (LinearLayout)inflater.inflate(R.layout.candidates, null);
mCandidateViewContainer = container; mCandidateViewContainer = container;
if (container.getPaddingRight() != 0) { mCandidateStripHeight = (int)mResources.getDimension(R.dimen.candidate_strip_height);
HorizontalScrollView scrollView =
(HorizontalScrollView) container.findViewById(R.id.candidates_scroll_view);
setOverScrollModeNever(scrollView);
container.setGravity(Gravity.CENTER_HORIZONTAL);
}
mCandidateView = (CandidateView) container.findViewById(R.id.candidates); mCandidateView = (CandidateView) container.findViewById(R.id.candidates);
mCandidateView.setService(this); mCandidateView.setService(this);
setCandidatesViewShown(true); setCandidatesViewShown(true);
@ -586,8 +579,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
switcher.updateShiftState(); switcher.updateShiftState();
} }
setCandidatesViewShownInternal(isCandidateStripVisible(), setCandidatesViewShownInternal(isCandidateStripVisible(), false /* needsInputViewShown */ );
false /* needsInputViewShown */ );
// Delay updating suggestions because keyboard input view may not be shown at this point. // Delay updating suggestions because keyboard input view may not be shown at this point.
mHandler.postUpdateSuggestions(); mHandler.postUpdateSuggestions();
@ -877,10 +869,21 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
} }
private void setCandidatesViewShownInternal(boolean shown, boolean needsInputViewShown) { 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()) { if (onEvaluateInputViewShown()) {
super.setCandidatesViewShown(shown final boolean shouldShowCandidates = shown
&& (needsInputViewShown ? mKeyboardSwitcher.isInputViewShown() : true)); && (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);
}
} }
} }
@ -892,35 +895,25 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
@Override @Override
public void onComputeInsets(InputMethodService.Insets outInsets) { public void onComputeInsets(InputMethodService.Insets outInsets) {
super.onComputeInsets(outInsets); super.onComputeInsets(outInsets);
if (!isFullscreenMode()) { final KeyboardView inputView = mKeyboardSwitcher.getInputView();
outInsets.contentTopInsets = outInsets.visibleTopInsets;
}
KeyboardView inputView = mKeyboardSwitcher.getInputView();
// Need to set touchable region only if input view is being shown // Need to set touchable region only if input view is being shown
if (inputView != null && mKeyboardSwitcher.isInputViewShown()) { if (inputView != null && mKeyboardSwitcher.isInputViewShown()) {
final int x = 0; final int containerHeight = mCandidateViewContainer.getHeight();
int y = 0; int touchY = containerHeight;
final int width = inputView.getWidth(); if (mCandidateViewContainer.getVisibility() == View.VISIBLE) {
int height = inputView.getHeight() + EXTENDED_TOUCHABLE_REGION_HEIGHT; touchY -= mCandidateStripHeight;
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();
}
}
}
} }
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) { 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);
} }
} }