Custom view for key preview popup

Bug: 15143928
Change-Id: I12411b9b5b9611ec089e4967def9b5c19a2367c7
Tadashi G. Takaoka 2014-06-17 17:42:36 -07:00
parent 593fe9b0cf
commit 615f431465
9 changed files with 153 additions and 161 deletions

View File

@ -1,27 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
**
** Copyright 2013, 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.
*/
-->
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="32dp"
android:gravity="center"
style="?attr/keyPreviewTextViewStyle"
/>

View File

@ -26,8 +26,6 @@
<attr name="keyboardViewStyle" format="reference" /> <attr name="keyboardViewStyle" format="reference" />
<!-- MainKeyboardView style --> <!-- MainKeyboardView style -->
<attr name="mainKeyboardViewStyle" format="reference" /> <attr name="mainKeyboardViewStyle" format="reference" />
<!-- Key preview text view style -->
<attr name="keyPreviewTextViewStyle" format="reference"/>
<!-- EmojiPalettesView style --> <!-- EmojiPalettesView style -->
<attr name="emojiPalettesViewStyle" format="reference" /> <attr name="emojiPalettesViewStyle" format="reference" />
<!-- MoreKeysKeyboard style --> <!-- MoreKeysKeyboard style -->
@ -106,8 +104,8 @@
<attr name="longPressShiftLockTimeout" format="integer" /> <attr name="longPressShiftLockTimeout" format="integer" />
<!-- Ignore special key timeout while typing in millisecond. --> <!-- Ignore special key timeout while typing in millisecond. -->
<attr name="ignoreAltCodeKeyTimeout" format="integer" /> <attr name="ignoreAltCodeKeyTimeout" format="integer" />
<!-- Layout resource for key press feedback.--> <!-- Background resource for key press feedback.-->
<attr name="keyPreviewLayout" format="reference" /> <attr name="keyPreviewBackground" format="reference" />
<!-- Vertical offset of the key press feedback from the key. --> <!-- Vertical offset of the key press feedback from the key. -->
<attr name="keyPreviewOffset" format="dimension" /> <attr name="keyPreviewOffset" format="dimension" />
<!-- Height of the key press feedback popup. --> <!-- Height of the key press feedback popup. -->

View File

@ -75,7 +75,6 @@
<item name="keyRepeatInterval">@integer/config_key_repeat_interval</item> <item name="keyRepeatInterval">@integer/config_key_repeat_interval</item>
<item name="longPressShiftLockTimeout">@integer/config_longpress_shift_lock_timeout</item> <item name="longPressShiftLockTimeout">@integer/config_longpress_shift_lock_timeout</item>
<item name="ignoreAltCodeKeyTimeout">@integer/config_ignore_alt_code_key_timeout</item> <item name="ignoreAltCodeKeyTimeout">@integer/config_ignore_alt_code_key_timeout</item>
<item name="keyPreviewLayout">@layout/key_preview</item>
<item name="keyPreviewHeight">@dimen/config_key_preview_height</item> <item name="keyPreviewHeight">@dimen/config_key_preview_height</item>
<!-- TODO: consolidate key preview linger timeout with the key preview animation parameters. --> <!-- TODO: consolidate key preview linger timeout with the key preview animation parameters. -->
<item name="keyPreviewLingerTimeout">@integer/config_key_preview_linger_timeout</item> <item name="keyPreviewLingerTimeout">@integer/config_key_preview_linger_timeout</item>
@ -106,7 +105,6 @@
<style <style
name="MainKeyboardView" name="MainKeyboardView"
parent="KeyboardView" /> parent="KeyboardView" />
<style name="KeyPreviewTextView" />
<!-- Though {@link EmojiPalettesView} doesn't extend {@link KeyboardView}, some views inside it, <!-- Though {@link EmojiPalettesView} doesn't extend {@link KeyboardView}, some views inside it,
for instance delete button, need themed {@link KeyboardView} attributes. --> for instance delete button, need themed {@link KeyboardView} attributes. -->
<style name="EmojiPalettesView" /> <style name="EmojiPalettesView" />

View File

@ -23,7 +23,6 @@
<item name="keyboardStyle">@style/Keyboard.ICS</item> <item name="keyboardStyle">@style/Keyboard.ICS</item>
<item name="keyboardViewStyle">@style/KeyboardView.ICS</item> <item name="keyboardViewStyle">@style/KeyboardView.ICS</item>
<item name="mainKeyboardViewStyle">@style/MainKeyboardView.ICS</item> <item name="mainKeyboardViewStyle">@style/MainKeyboardView.ICS</item>
<item name="keyPreviewTextViewStyle">@style/KeyPreviewTextView.ICS</item>
<item name="emojiPalettesViewStyle">@style/EmojiPalettesView.ICS</item> <item name="emojiPalettesViewStyle">@style/EmojiPalettesView.ICS</item>
<item name="moreKeysKeyboardStyle">@style/MoreKeysKeyboard.ICS</item> <item name="moreKeysKeyboardStyle">@style/MoreKeysKeyboard.ICS</item>
<item name="moreKeysKeyboardViewStyle">@style/MoreKeysKeyboardView.ICS</item> <item name="moreKeysKeyboardViewStyle">@style/MoreKeysKeyboardView.ICS</item>
@ -66,6 +65,7 @@
name="MainKeyboardView.ICS" name="MainKeyboardView.ICS"
parent="KeyboardView.ICS" parent="KeyboardView.ICS"
> >
<item name="keyPreviewBackground">@drawable/keyboard_key_feedback_ics</item>
<item name="keyPreviewOffset">@dimen/config_key_preview_offset_holo</item> <item name="keyPreviewOffset">@dimen/config_key_preview_offset_holo</item>
<item name="gestureFloatingPreviewTextColor">@color/highlight_color_ics</item> <item name="gestureFloatingPreviewTextColor">@color/highlight_color_ics</item>
<item name="gestureFloatingPreviewColor">@color/gesture_floating_preview_color_holo</item> <item name="gestureFloatingPreviewColor">@color/gesture_floating_preview_color_holo</item>
@ -75,12 +75,6 @@
<item name="languageOnSpacebarTextShadowRadius">1.0</item> <item name="languageOnSpacebarTextShadowRadius">1.0</item>
<item name="languageOnSpacebarTextShadowColor">@color/spacebar_text_shadow_color_holo</item> <item name="languageOnSpacebarTextShadowColor">@color/spacebar_text_shadow_color_holo</item>
</style> </style>
<style
name="KeyPreviewTextView.ICS"
parent="KeyPreviewTextView"
>
<item name="android:background">@drawable/keyboard_key_feedback_ics</item>
</style>
<!-- Though {@link EmojiPalettesView} doesn't extend {@link KeyboardView}, some views inside it, <!-- Though {@link EmojiPalettesView} doesn't extend {@link KeyboardView}, some views inside it,
for instance delete button, need themed {@link KeyboardView} attributes. --> for instance delete button, need themed {@link KeyboardView} attributes. -->
<style <style

View File

@ -23,7 +23,6 @@
<item name="keyboardStyle">@style/Keyboard.KLP</item> <item name="keyboardStyle">@style/Keyboard.KLP</item>
<item name="keyboardViewStyle">@style/KeyboardView.KLP</item> <item name="keyboardViewStyle">@style/KeyboardView.KLP</item>
<item name="mainKeyboardViewStyle">@style/MainKeyboardView.KLP</item> <item name="mainKeyboardViewStyle">@style/MainKeyboardView.KLP</item>
<item name="keyPreviewTextViewStyle">@style/KeyPreviewTextView.KLP</item>
<item name="emojiPalettesViewStyle">@style/EmojiPalettesView.KLP</item> <item name="emojiPalettesViewStyle">@style/EmojiPalettesView.KLP</item>
<item name="moreKeysKeyboardStyle">@style/MoreKeysKeyboard.KLP</item> <item name="moreKeysKeyboardStyle">@style/MoreKeysKeyboard.KLP</item>
<item name="moreKeysKeyboardViewStyle">@style/MoreKeysKeyboardView.KLP</item> <item name="moreKeysKeyboardViewStyle">@style/MoreKeysKeyboardView.KLP</item>
@ -66,6 +65,7 @@
name="MainKeyboardView.KLP" name="MainKeyboardView.KLP"
parent="KeyboardView.KLP" parent="KeyboardView.KLP"
> >
<item name="keyPreviewBackground">@drawable/keyboard_key_feedback_klp</item>
<item name="keyPreviewOffset">@dimen/config_key_preview_offset_holo</item> <item name="keyPreviewOffset">@dimen/config_key_preview_offset_holo</item>
<item name="gestureFloatingPreviewTextColor">@color/highlight_color_klp</item> <item name="gestureFloatingPreviewTextColor">@color/highlight_color_klp</item>
<item name="gestureFloatingPreviewColor">@color/gesture_floating_preview_color_holo</item> <item name="gestureFloatingPreviewColor">@color/gesture_floating_preview_color_holo</item>
@ -75,12 +75,6 @@
<item name="languageOnSpacebarTextShadowRadius">1.0</item> <item name="languageOnSpacebarTextShadowRadius">1.0</item>
<item name="languageOnSpacebarTextShadowColor">@color/spacebar_text_shadow_color_holo</item> <item name="languageOnSpacebarTextShadowColor">@color/spacebar_text_shadow_color_holo</item>
</style> </style>
<style
name="KeyPreviewTextView.KLP"
parent="KeyPreviewTextView"
>
<item name="android:background">@drawable/keyboard_key_feedback_klp</item>
</style>
<!-- Though {@link EmojiPalettesView} doesn't extend {@link KeyboardView}, some views inside it, <!-- Though {@link EmojiPalettesView} doesn't extend {@link KeyboardView}, some views inside it,
for instance delete button, need themed {@link KeyboardView} attributes. --> for instance delete button, need themed {@link KeyboardView} attributes. -->
<style <style

View File

@ -23,7 +23,6 @@
<item name="keyboardStyle">@style/Keyboard.LXX_Dark</item> <item name="keyboardStyle">@style/Keyboard.LXX_Dark</item>
<item name="keyboardViewStyle">@style/KeyboardView.LXX_Dark</item> <item name="keyboardViewStyle">@style/KeyboardView.LXX_Dark</item>
<item name="mainKeyboardViewStyle">@style/MainKeyboardView.LXX_Dark</item> <item name="mainKeyboardViewStyle">@style/MainKeyboardView.LXX_Dark</item>
<item name="keyPreviewTextViewStyle">@style/KeyPreviewTextView.LXX_Dark</item>
<item name="emojiPalettesViewStyle">@style/EmojiPalettesView.LXX_Dark</item> <item name="emojiPalettesViewStyle">@style/EmojiPalettesView.LXX_Dark</item>
<item name="moreKeysKeyboardStyle">@style/MoreKeysKeyboard.LXX_Dark</item> <item name="moreKeysKeyboardStyle">@style/MoreKeysKeyboard.LXX_Dark</item>
<item name="moreKeysKeyboardViewStyle">@style/MoreKeysKeyboardView.LXX_Dark</item> <item name="moreKeysKeyboardViewStyle">@style/MoreKeysKeyboardView.LXX_Dark</item>
@ -67,6 +66,7 @@
name="MainKeyboardView.LXX_Dark" name="MainKeyboardView.LXX_Dark"
parent="KeyboardView.LXX_Dark" parent="KeyboardView.LXX_Dark"
> >
<item name="keyPreviewBackground">@drawable/keyboard_key_feedback_lxx_dark</item>
<item name="keyPreviewOffset">@dimen/config_key_preview_offset_holo</item> <item name="keyPreviewOffset">@dimen/config_key_preview_offset_holo</item>
<item name="gestureFloatingPreviewTextColor">@color/highlight_color_lxx_dark</item> <item name="gestureFloatingPreviewTextColor">@color/highlight_color_lxx_dark</item>
<item name="gestureFloatingPreviewColor">@color/gesture_floating_preview_color_lxx_dark</item> <item name="gestureFloatingPreviewColor">@color/gesture_floating_preview_color_lxx_dark</item>
@ -76,12 +76,6 @@
<!-- A negative value to disable text shadow layer. --> <!-- A negative value to disable text shadow layer. -->
<item name="languageOnSpacebarTextShadowRadius">-1.0</item> <item name="languageOnSpacebarTextShadowRadius">-1.0</item>
</style> </style>
<style
name="KeyPreviewTextView.LXX_Dark"
parent="KeyPreviewTextView"
>
<item name="android:background">@drawable/keyboard_key_feedback_lxx_dark</item>
</style>
<!-- Though {@link EmojiPalettesView} doesn't extend {@link KeyboardView}, some views inside it, <!-- Though {@link EmojiPalettesView} doesn't extend {@link KeyboardView}, some views inside it,
for instance delete button, need themed {@link KeyboardView} attributes. --> for instance delete button, need themed {@link KeyboardView} attributes. -->
<style <style

View File

@ -21,17 +21,12 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet; import android.animation.AnimatorSet;
import android.animation.ObjectAnimator; import android.animation.ObjectAnimator;
import android.content.Context; import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.animation.AccelerateInterpolator; import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator; import android.view.animation.DecelerateInterpolator;
import android.widget.TextView;
import com.android.inputmethod.keyboard.Key; import com.android.inputmethod.keyboard.Key;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.utils.CoordinateUtils; import com.android.inputmethod.latin.utils.CoordinateUtils;
import com.android.inputmethod.latin.utils.ViewLayoutUtils; import com.android.inputmethod.latin.utils.ViewLayoutUtils;
@ -46,10 +41,11 @@ import java.util.HashSet;
* - how key previews should be shown and dismissed. * - how key previews should be shown and dismissed.
*/ */
public final class KeyPreviewChoreographer { public final class KeyPreviewChoreographer {
// Free {@link TextView} pool that can be used for key preview. // Free {@link KeyPreviewView} pool that can be used for key preview.
private final ArrayDeque<TextView> mFreeKeyPreviewTextViews = new ArrayDeque<>(); private final ArrayDeque<KeyPreviewView> mFreeKeyPreviewViews = new ArrayDeque<>();
// Map from {@link Key} to {@link TextView} that is currently being displayed as key preview. // Map from {@link Key} to {@link KeyPreviewView} that is currently being displayed as key
private final HashMap<Key,TextView> mShowingKeyPreviewTextViews = new HashMap<>(); // preview.
private final HashMap<Key,KeyPreviewView> mShowingKeyPreviewViews = new HashMap<>();
private final KeyPreviewDrawParams mParams; private final KeyPreviewDrawParams mParams;
@ -57,32 +53,28 @@ public final class KeyPreviewChoreographer {
mParams = params; mParams = params;
} }
private TextView getKeyPreviewTextView(final Key key, final ViewGroup placerView) { public KeyPreviewView getKeyPreviewView(final Key key, final ViewGroup placerView) {
TextView previewTextView = mShowingKeyPreviewTextViews.remove(key); KeyPreviewView keyPreviewView = mShowingKeyPreviewViews.remove(key);
if (previewTextView != null) { if (keyPreviewView != null) {
return previewTextView; return keyPreviewView;
} }
previewTextView = mFreeKeyPreviewTextViews.poll(); keyPreviewView = mFreeKeyPreviewViews.poll();
if (previewTextView != null) { if (keyPreviewView != null) {
return previewTextView; return keyPreviewView;
} }
final Context context = placerView.getContext(); final Context context = placerView.getContext();
if (mParams.mLayoutId != 0) { keyPreviewView = new KeyPreviewView(context, null /* attrs */);
previewTextView = (TextView)LayoutInflater.from(context) keyPreviewView.setBackgroundResource(mParams.mPreviewBackgroundResId);
.inflate(mParams.mLayoutId, null); placerView.addView(keyPreviewView, ViewLayoutUtils.newLayoutParam(placerView, 0, 0));
} else { return keyPreviewView;
previewTextView = new TextView(context);
}
placerView.addView(previewTextView, ViewLayoutUtils.newLayoutParam(placerView, 0, 0));
return previewTextView;
} }
public boolean isShowingKeyPreview(final Key key) { public boolean isShowingKeyPreview(final Key key) {
return mShowingKeyPreviewTextViews.containsKey(key); return mShowingKeyPreviewViews.containsKey(key);
} }
public void dismissAllKeyPreviews() { public void dismissAllKeyPreviews() {
for (final Key key : new HashSet<>(mShowingKeyPreviewTextViews.keySet())) { for (final Key key : new HashSet<>(mShowingKeyPreviewViews.keySet())) {
dismissKeyPreview(key, false /* withAnimation */); dismissKeyPreview(key, false /* withAnimation */);
} }
} }
@ -91,11 +83,11 @@ public final class KeyPreviewChoreographer {
if (key == null) { if (key == null) {
return; return;
} }
final TextView previewTextView = mShowingKeyPreviewTextViews.get(key); final KeyPreviewView keyPreviewView = mShowingKeyPreviewViews.get(key);
if (previewTextView == null) { if (keyPreviewView == null) {
return; return;
} }
final Object tag = previewTextView.getTag(); final Object tag = keyPreviewView.getTag();
if (withAnimation) { if (withAnimation) {
if (tag instanceof KeyPreviewAnimations) { if (tag instanceof KeyPreviewAnimations) {
final KeyPreviewAnimations animation = (KeyPreviewAnimations)tag; final KeyPreviewAnimations animation = (KeyPreviewAnimations)tag;
@ -104,114 +96,76 @@ public final class KeyPreviewChoreographer {
} }
} }
// Dismiss preview without animation. // Dismiss preview without animation.
mShowingKeyPreviewTextViews.remove(key); mShowingKeyPreviewViews.remove(key);
if (tag instanceof Animator) { if (tag instanceof Animator) {
((Animator)tag).cancel(); ((Animator)tag).cancel();
} }
previewTextView.setTag(null); keyPreviewView.setTag(null);
previewTextView.setVisibility(View.INVISIBLE); keyPreviewView.setVisibility(View.INVISIBLE);
mFreeKeyPreviewTextViews.add(previewTextView); mFreeKeyPreviewViews.add(keyPreviewView);
} }
// Background state set
private static final int[][][] KEY_PREVIEW_BACKGROUND_STATE_TABLE = {
{ // STATE_MIDDLE
{},
{ R.attr.state_has_morekeys }
},
{ // STATE_LEFT
{ R.attr.state_left_edge },
{ R.attr.state_left_edge, R.attr.state_has_morekeys }
},
{ // STATE_RIGHT
{ R.attr.state_right_edge },
{ R.attr.state_right_edge, R.attr.state_has_morekeys }
}
};
private static final int STATE_MIDDLE = 0;
private static final int STATE_LEFT = 1;
private static final int STATE_RIGHT = 2;
private static final int STATE_NORMAL = 0;
private static final int STATE_HAS_MOREKEYS = 1;
public void placeKeyPreviewAndShow(final Key key, final KeyboardIconsSet iconsSet, public void placeKeyPreviewAndShow(final Key key, final KeyboardIconsSet iconsSet,
final KeyDrawParams drawParams, final int keyboardViewWidth, final int[] keyboardOrigin, final KeyDrawParams drawParams, final int keyboardViewWidth, final int[] keyboardOrigin,
final ViewGroup placerView, final boolean withAnimation) { final ViewGroup placerView, final boolean withAnimation) {
final TextView previewTextView = getKeyPreviewTextView(key, placerView); final KeyPreviewView keyPreviewView = getKeyPreviewView(key, placerView);
placeKeyPreview( placeKeyPreview(
key, previewTextView, iconsSet, drawParams, keyboardViewWidth, keyboardOrigin); key, keyPreviewView, iconsSet, drawParams, keyboardViewWidth, keyboardOrigin);
showKeyPreview(key, previewTextView, withAnimation); showKeyPreview(key, keyPreviewView, withAnimation);
} }
private void placeKeyPreview(final Key key, final TextView previewTextView, private void placeKeyPreview(final Key key, final KeyPreviewView keyPreviewView,
final KeyboardIconsSet iconsSet, final KeyDrawParams drawParams, final KeyboardIconsSet iconsSet, final KeyDrawParams drawParams,
final int keyboardViewWidth, final int[] originCoords) { final int keyboardViewWidth, final int[] originCoords) {
previewTextView.setTextColor(drawParams.mPreviewTextColor); keyPreviewView.setPreviewVisual(key, iconsSet, drawParams);
final Drawable background = previewTextView.getBackground(); keyPreviewView.measure(
final String label = key.getPreviewLabel();
// What we show as preview should match what we show on a key top in onDraw().
if (label != null) {
// TODO Should take care of temporaryShiftLabel here.
previewTextView.setCompoundDrawables(null, null, null, null);
previewTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX,
key.selectPreviewTextSize(drawParams));
previewTextView.setTypeface(key.selectPreviewTypeface(drawParams));
previewTextView.setText(label);
} else {
previewTextView.setCompoundDrawables(null, null, null, key.getPreviewIcon(iconsSet));
previewTextView.setText(null);
}
previewTextView.measure(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
mParams.setGeometry(previewTextView); mParams.setGeometry(keyPreviewView);
final int previewWidth = previewTextView.getMeasuredWidth(); final int previewWidth = keyPreviewView.getMeasuredWidth();
final int previewHeight = mParams.mPreviewHeight; final int previewHeight = mParams.mPreviewHeight;
final int keyDrawWidth = key.getDrawWidth(); final int keyDrawWidth = key.getDrawWidth();
// The key preview is horizontally aligned with the center of the visible part of the // The key preview is horizontally aligned with the center of the visible part of the
// parent key. If it doesn't fit in this {@link KeyboardView}, it is moved inward to fit and // parent key. If it doesn't fit in this {@link KeyboardView}, it is moved inward to fit and
// the left/right background is used if such background is specified. // the left/right background is used if such background is specified.
final int statePosition; final int keyPreviewPosition;
int previewX = key.getDrawX() - (previewWidth - keyDrawWidth) / 2 int previewX = key.getDrawX() - (previewWidth - keyDrawWidth) / 2
+ CoordinateUtils.x(originCoords); + CoordinateUtils.x(originCoords);
if (previewX < 0) { if (previewX < 0) {
previewX = 0; previewX = 0;
statePosition = STATE_LEFT; keyPreviewPosition = KeyPreviewView.POSITION_LEFT;
} else if (previewX > keyboardViewWidth - previewWidth) { } else if (previewX > keyboardViewWidth - previewWidth) {
previewX = keyboardViewWidth - previewWidth; previewX = keyboardViewWidth - previewWidth;
statePosition = STATE_RIGHT; keyPreviewPosition = KeyPreviewView.POSITION_RIGHT;
} else { } else {
statePosition = STATE_MIDDLE; keyPreviewPosition = KeyPreviewView.POSITION_MIDDLE;
} }
final boolean hasMoreKeys = (key.getMoreKeys() != null);
keyPreviewView.setPreviewBackground(hasMoreKeys, keyPreviewPosition);
// The key preview is placed vertically above the top edge of the parent key with an // The key preview is placed vertically above the top edge of the parent key with an
// arbitrary offset. // arbitrary offset.
final int previewY = key.getY() - previewHeight + mParams.mPreviewOffset final int previewY = key.getY() - previewHeight + mParams.mPreviewOffset
+ CoordinateUtils.y(originCoords); + CoordinateUtils.y(originCoords);
if (background != null) {
final int hasMoreKeys = (key.getMoreKeys() != null) ? STATE_HAS_MOREKEYS : STATE_NORMAL;
background.setState(KEY_PREVIEW_BACKGROUND_STATE_TABLE[statePosition][hasMoreKeys]);
}
ViewLayoutUtils.placeViewAt( ViewLayoutUtils.placeViewAt(
previewTextView, previewX, previewY, previewWidth, previewHeight); keyPreviewView, previewX, previewY, previewWidth, previewHeight);
previewTextView.setPivotX(previewWidth / 2.0f); keyPreviewView.setPivotX(previewWidth / 2.0f);
previewTextView.setPivotY(previewHeight); keyPreviewView.setPivotY(previewHeight);
} }
private void showKeyPreview(final Key key, final TextView previewTextView, private void showKeyPreview(final Key key, final KeyPreviewView keyPreviewView,
final boolean withAnimation) { final boolean withAnimation) {
if (!withAnimation) { if (!withAnimation) {
previewTextView.setVisibility(View.VISIBLE); keyPreviewView.setVisibility(View.VISIBLE);
mShowingKeyPreviewTextViews.put(key, previewTextView); mShowingKeyPreviewViews.put(key, keyPreviewView);
return; return;
} }
// Show preview with animation. // Show preview with animation.
final Animator showUpAnimation = createShowUpAniation(key, previewTextView); final Animator showUpAnimation = createShowUpAniation(key, keyPreviewView);
final Animator dismissAnimation = createDismissAnimation(key, previewTextView); final Animator dismissAnimation = createDismissAnimation(key, keyPreviewView);
final KeyPreviewAnimations animation = new KeyPreviewAnimations( final KeyPreviewAnimations animation = new KeyPreviewAnimations(
showUpAnimation, dismissAnimation); showUpAnimation, dismissAnimation);
previewTextView.setTag(animation); keyPreviewView.setTag(animation);
animation.startShowUp(); animation.startShowUp();
} }
@ -221,13 +175,13 @@ public final class KeyPreviewChoreographer {
private static final DecelerateInterpolator DECELERATE_INTERPOLATOR = private static final DecelerateInterpolator DECELERATE_INTERPOLATOR =
new DecelerateInterpolator(); new DecelerateInterpolator();
private Animator createShowUpAniation(final Key key, final TextView previewTextView) { private Animator createShowUpAniation(final Key key, final KeyPreviewView keyPreviewView) {
// TODO: Optimization for no scale animation and no duration. // TODO: Optimization for no scale animation and no duration.
final ObjectAnimator scaleXAnimation = ObjectAnimator.ofFloat( final ObjectAnimator scaleXAnimation = ObjectAnimator.ofFloat(
previewTextView, View.SCALE_X, mParams.getShowUpStartScale(), keyPreviewView, View.SCALE_X, mParams.getShowUpStartScale(),
KEY_PREVIEW_SHOW_UP_END_SCALE); KEY_PREVIEW_SHOW_UP_END_SCALE);
final ObjectAnimator scaleYAnimation = ObjectAnimator.ofFloat( final ObjectAnimator scaleYAnimation = ObjectAnimator.ofFloat(
previewTextView, View.SCALE_Y, mParams.getShowUpStartScale(), keyPreviewView, View.SCALE_Y, mParams.getShowUpStartScale(),
KEY_PREVIEW_SHOW_UP_END_SCALE); KEY_PREVIEW_SHOW_UP_END_SCALE);
final AnimatorSet showUpAnimation = new AnimatorSet(); final AnimatorSet showUpAnimation = new AnimatorSet();
showUpAnimation.play(scaleXAnimation).with(scaleYAnimation); showUpAnimation.play(scaleXAnimation).with(scaleYAnimation);
@ -236,18 +190,18 @@ public final class KeyPreviewChoreographer {
showUpAnimation.addListener(new AnimatorListenerAdapter() { showUpAnimation.addListener(new AnimatorListenerAdapter() {
@Override @Override
public void onAnimationStart(final Animator animation) { public void onAnimationStart(final Animator animation) {
showKeyPreview(key, previewTextView, false /* withAnimation */); showKeyPreview(key, keyPreviewView, false /* withAnimation */);
} }
}); });
return showUpAnimation; return showUpAnimation;
} }
private Animator createDismissAnimation(final Key key, final TextView previewTextView) { private Animator createDismissAnimation(final Key key, final KeyPreviewView keyPreviewView) {
// TODO: Optimization for no scale animation and no duration. // TODO: Optimization for no scale animation and no duration.
final ObjectAnimator scaleXAnimation = ObjectAnimator.ofFloat( final ObjectAnimator scaleXAnimation = ObjectAnimator.ofFloat(
previewTextView, View.SCALE_X, mParams.getDismissEndScale()); keyPreviewView, View.SCALE_X, mParams.getDismissEndScale());
final ObjectAnimator scaleYAnimation = ObjectAnimator.ofFloat( final ObjectAnimator scaleYAnimation = ObjectAnimator.ofFloat(
previewTextView, View.SCALE_Y, mParams.getDismissEndScale()); keyPreviewView, View.SCALE_Y, mParams.getDismissEndScale());
final AnimatorSet dismissAnimation = new AnimatorSet(); final AnimatorSet dismissAnimation = new AnimatorSet();
dismissAnimation.play(scaleXAnimation).with(scaleYAnimation); dismissAnimation.play(scaleXAnimation).with(scaleYAnimation);
final int dismissDuration = Math.min( final int dismissDuration = Math.min(

View File

@ -23,9 +23,9 @@ import com.android.inputmethod.latin.R;
public final class KeyPreviewDrawParams { public final class KeyPreviewDrawParams {
// XML attributes of {@link MainKeyboardView}. // XML attributes of {@link MainKeyboardView}.
public final int mLayoutId;
public final int mPreviewOffset; public final int mPreviewOffset;
public final int mPreviewHeight; public final int mPreviewHeight;
public final int mPreviewBackgroundResId;
private int mShowUpDuration; private int mShowUpDuration;
private int mDismissDuration; private int mDismissDuration;
private float mShowUpStartScale; private float mShowUpStartScale;
@ -63,13 +63,10 @@ public final class KeyPreviewDrawParams {
R.styleable.MainKeyboardView_keyPreviewOffset, 0); R.styleable.MainKeyboardView_keyPreviewOffset, 0);
mPreviewHeight = mainKeyboardViewAttr.getDimensionPixelSize( mPreviewHeight = mainKeyboardViewAttr.getDimensionPixelSize(
R.styleable.MainKeyboardView_keyPreviewHeight, 0); R.styleable.MainKeyboardView_keyPreviewHeight, 0);
mPreviewBackgroundResId = mainKeyboardViewAttr.getResourceId(
R.styleable.MainKeyboardView_keyPreviewBackground, 0);
mLingerTimeout = mainKeyboardViewAttr.getInt( mLingerTimeout = mainKeyboardViewAttr.getInt(
R.styleable.MainKeyboardView_keyPreviewLingerTimeout, 0); R.styleable.MainKeyboardView_keyPreviewLingerTimeout, 0);
mLayoutId = mainKeyboardViewAttr.getResourceId(
R.styleable.MainKeyboardView_keyPreviewLayout, 0);
if (mLayoutId == 0) {
mShowPopup = false;
}
} }
public void setVisibleOffset(final int previewVisibleOffset) { public void setVisibleOffset(final int previewVisibleOffset) {

View File

@ -0,0 +1,90 @@
/*
* Copyright (C) 2014 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.
*/
package com.android.inputmethod.keyboard.internal;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
import android.widget.TextView;
import com.android.inputmethod.keyboard.Key;
import com.android.inputmethod.latin.R;
/**
* The pop up key preview view.
*/
public class KeyPreviewView extends TextView {
public static final int POSITION_MIDDLE = 0;
public static final int POSITION_LEFT = 1;
public static final int POSITION_RIGHT = 2;
public KeyPreviewView(final Context context, final AttributeSet attrs) {
this(context, attrs, 0);
}
public KeyPreviewView(final Context context, final AttributeSet attrs, final int defStyleAttr) {
super(context, attrs, defStyleAttr);
setGravity(Gravity.CENTER);
}
public void setPreviewVisual(final Key key, final KeyboardIconsSet iconsSet,
final KeyDrawParams drawParams) {
// What we show as preview should match what we show on a key top in onDraw().
final int iconId = key.getIconId();
if (iconId != KeyboardIconsSet.ICON_UNDEFINED) {
setCompoundDrawables(null, null, null, key.getPreviewIcon(iconsSet));
setText(null);
return;
}
setCompoundDrawables(null, null, null, null);
setTextColor(drawParams.mPreviewTextColor);
setTextSize(TypedValue.COMPLEX_UNIT_PX, key.selectPreviewTextSize(drawParams));
setTypeface(key.selectPreviewTypeface(drawParams));
// TODO Should take care of temporaryShiftLabel here.
setText(key.getPreviewLabel());
}
// Background state set
private static final int[][][] KEY_PREVIEW_BACKGROUND_STATE_TABLE = {
{ // POSITION_MIDDLE
{},
{ R.attr.state_has_morekeys }
},
{ // POSITION_LEFT
{ R.attr.state_left_edge },
{ R.attr.state_left_edge, R.attr.state_has_morekeys }
},
{ // POSITION_RIGHT
{ R.attr.state_right_edge },
{ R.attr.state_right_edge, R.attr.state_has_morekeys }
}
};
private static final int STATE_NORMAL = 0;
private static final int STATE_HAS_MOREKEYS = 1;
public void setPreviewBackground(final boolean hasMoreKeys, final int position) {
final Drawable background = getBackground();
if (background == null) {
return;
}
final int hasMoreKeysState = hasMoreKeys ? STATE_HAS_MOREKEYS : STATE_NORMAL;
background.setState(KEY_PREVIEW_BACKGROUND_STATE_TABLE[position][hasMoreKeysState]);
}
}