diff options
author | 2014-06-17 17:42:36 -0700 | |
---|---|---|
committer | 2014-06-23 01:07:59 -0700 | |
commit | 615f431465ed2b5f3511ddfcc4c6de7bbfc28151 (patch) | |
tree | a04a6472dcca705b07fe56cadceeaeb008524949 /java/src | |
parent | 593fe9b0cfcd5ffd0a33e3260358b192997d8347 (diff) | |
download | latinime-615f431465ed2b5f3511ddfcc4c6de7bbfc28151.tar.gz latinime-615f431465ed2b5f3511ddfcc4c6de7bbfc28151.tar.xz latinime-615f431465ed2b5f3511ddfcc4c6de7bbfc28151.zip |
Custom view for key preview popup
Bug: 15143928
Change-Id: I12411b9b5b9611ec089e4967def9b5c19a2367c7
Diffstat (limited to 'java/src')
3 files changed, 148 insertions, 107 deletions
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewChoreographer.java b/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewChoreographer.java index d4c671028..6fc300beb 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewChoreographer.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewChoreographer.java @@ -21,17 +21,12 @@ import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.content.Context; -import android.graphics.drawable.Drawable; -import android.util.TypedValue; -import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.animation.AccelerateInterpolator; import android.view.animation.DecelerateInterpolator; -import android.widget.TextView; 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.ViewLayoutUtils; @@ -46,10 +41,11 @@ import java.util.HashSet; * - how key previews should be shown and dismissed. */ public final class KeyPreviewChoreographer { - // Free {@link TextView} pool that can be used for key preview. - private final ArrayDeque<TextView> mFreeKeyPreviewTextViews = new ArrayDeque<>(); - // Map from {@link Key} to {@link TextView} that is currently being displayed as key preview. - private final HashMap<Key,TextView> mShowingKeyPreviewTextViews = new HashMap<>(); + // Free {@link KeyPreviewView} pool that can be used for key preview. + private final ArrayDeque<KeyPreviewView> mFreeKeyPreviewViews = new ArrayDeque<>(); + // Map from {@link Key} to {@link KeyPreviewView} that is currently being displayed as key + // preview. + private final HashMap<Key,KeyPreviewView> mShowingKeyPreviewViews = new HashMap<>(); private final KeyPreviewDrawParams mParams; @@ -57,32 +53,28 @@ public final class KeyPreviewChoreographer { mParams = params; } - private TextView getKeyPreviewTextView(final Key key, final ViewGroup placerView) { - TextView previewTextView = mShowingKeyPreviewTextViews.remove(key); - if (previewTextView != null) { - return previewTextView; + public KeyPreviewView getKeyPreviewView(final Key key, final ViewGroup placerView) { + KeyPreviewView keyPreviewView = mShowingKeyPreviewViews.remove(key); + if (keyPreviewView != null) { + return keyPreviewView; } - previewTextView = mFreeKeyPreviewTextViews.poll(); - if (previewTextView != null) { - return previewTextView; + keyPreviewView = mFreeKeyPreviewViews.poll(); + if (keyPreviewView != null) { + return keyPreviewView; } final Context context = placerView.getContext(); - if (mParams.mLayoutId != 0) { - previewTextView = (TextView)LayoutInflater.from(context) - .inflate(mParams.mLayoutId, null); - } else { - previewTextView = new TextView(context); - } - placerView.addView(previewTextView, ViewLayoutUtils.newLayoutParam(placerView, 0, 0)); - return previewTextView; + keyPreviewView = new KeyPreviewView(context, null /* attrs */); + keyPreviewView.setBackgroundResource(mParams.mPreviewBackgroundResId); + placerView.addView(keyPreviewView, ViewLayoutUtils.newLayoutParam(placerView, 0, 0)); + return keyPreviewView; } public boolean isShowingKeyPreview(final Key key) { - return mShowingKeyPreviewTextViews.containsKey(key); + return mShowingKeyPreviewViews.containsKey(key); } public void dismissAllKeyPreviews() { - for (final Key key : new HashSet<>(mShowingKeyPreviewTextViews.keySet())) { + for (final Key key : new HashSet<>(mShowingKeyPreviewViews.keySet())) { dismissKeyPreview(key, false /* withAnimation */); } } @@ -91,11 +83,11 @@ public final class KeyPreviewChoreographer { if (key == null) { return; } - final TextView previewTextView = mShowingKeyPreviewTextViews.get(key); - if (previewTextView == null) { + final KeyPreviewView keyPreviewView = mShowingKeyPreviewViews.get(key); + if (keyPreviewView == null) { return; } - final Object tag = previewTextView.getTag(); + final Object tag = keyPreviewView.getTag(); if (withAnimation) { if (tag instanceof KeyPreviewAnimations) { final KeyPreviewAnimations animation = (KeyPreviewAnimations)tag; @@ -104,114 +96,76 @@ public final class KeyPreviewChoreographer { } } // Dismiss preview without animation. - mShowingKeyPreviewTextViews.remove(key); + mShowingKeyPreviewViews.remove(key); if (tag instanceof Animator) { ((Animator)tag).cancel(); } - previewTextView.setTag(null); - previewTextView.setVisibility(View.INVISIBLE); - mFreeKeyPreviewTextViews.add(previewTextView); + keyPreviewView.setTag(null); + keyPreviewView.setVisibility(View.INVISIBLE); + 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, final KeyDrawParams drawParams, final int keyboardViewWidth, final int[] keyboardOrigin, final ViewGroup placerView, final boolean withAnimation) { - final TextView previewTextView = getKeyPreviewTextView(key, placerView); + final KeyPreviewView keyPreviewView = getKeyPreviewView(key, placerView); placeKeyPreview( - key, previewTextView, iconsSet, drawParams, keyboardViewWidth, keyboardOrigin); - showKeyPreview(key, previewTextView, withAnimation); + key, keyPreviewView, iconsSet, drawParams, keyboardViewWidth, keyboardOrigin); + 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 int keyboardViewWidth, final int[] originCoords) { - previewTextView.setTextColor(drawParams.mPreviewTextColor); - final Drawable background = previewTextView.getBackground(); - 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( + keyPreviewView.setPreviewVisual(key, iconsSet, drawParams); + keyPreviewView.measure( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); - mParams.setGeometry(previewTextView); - final int previewWidth = previewTextView.getMeasuredWidth(); + mParams.setGeometry(keyPreviewView); + final int previewWidth = keyPreviewView.getMeasuredWidth(); final int previewHeight = mParams.mPreviewHeight; final int keyDrawWidth = key.getDrawWidth(); // 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 // the left/right background is used if such background is specified. - final int statePosition; + final int keyPreviewPosition; int previewX = key.getDrawX() - (previewWidth - keyDrawWidth) / 2 + CoordinateUtils.x(originCoords); if (previewX < 0) { previewX = 0; - statePosition = STATE_LEFT; + keyPreviewPosition = KeyPreviewView.POSITION_LEFT; } else if (previewX > keyboardViewWidth - previewWidth) { previewX = keyboardViewWidth - previewWidth; - statePosition = STATE_RIGHT; + keyPreviewPosition = KeyPreviewView.POSITION_RIGHT; } 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 // arbitrary offset. final int previewY = key.getY() - previewHeight + mParams.mPreviewOffset + 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( - previewTextView, previewX, previewY, previewWidth, previewHeight); - previewTextView.setPivotX(previewWidth / 2.0f); - previewTextView.setPivotY(previewHeight); + keyPreviewView, previewX, previewY, previewWidth, previewHeight); + keyPreviewView.setPivotX(previewWidth / 2.0f); + keyPreviewView.setPivotY(previewHeight); } - private void showKeyPreview(final Key key, final TextView previewTextView, + private void showKeyPreview(final Key key, final KeyPreviewView keyPreviewView, final boolean withAnimation) { if (!withAnimation) { - previewTextView.setVisibility(View.VISIBLE); - mShowingKeyPreviewTextViews.put(key, previewTextView); + keyPreviewView.setVisibility(View.VISIBLE); + mShowingKeyPreviewViews.put(key, keyPreviewView); return; } // Show preview with animation. - final Animator showUpAnimation = createShowUpAniation(key, previewTextView); - final Animator dismissAnimation = createDismissAnimation(key, previewTextView); + final Animator showUpAnimation = createShowUpAniation(key, keyPreviewView); + final Animator dismissAnimation = createDismissAnimation(key, keyPreviewView); final KeyPreviewAnimations animation = new KeyPreviewAnimations( showUpAnimation, dismissAnimation); - previewTextView.setTag(animation); + keyPreviewView.setTag(animation); animation.startShowUp(); } @@ -221,13 +175,13 @@ public final class KeyPreviewChoreographer { private static final DecelerateInterpolator DECELERATE_INTERPOLATOR = 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. final ObjectAnimator scaleXAnimation = ObjectAnimator.ofFloat( - previewTextView, View.SCALE_X, mParams.getShowUpStartScale(), + keyPreviewView, View.SCALE_X, mParams.getShowUpStartScale(), KEY_PREVIEW_SHOW_UP_END_SCALE); final ObjectAnimator scaleYAnimation = ObjectAnimator.ofFloat( - previewTextView, View.SCALE_Y, mParams.getShowUpStartScale(), + keyPreviewView, View.SCALE_Y, mParams.getShowUpStartScale(), KEY_PREVIEW_SHOW_UP_END_SCALE); final AnimatorSet showUpAnimation = new AnimatorSet(); showUpAnimation.play(scaleXAnimation).with(scaleYAnimation); @@ -236,18 +190,18 @@ public final class KeyPreviewChoreographer { showUpAnimation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(final Animator animation) { - showKeyPreview(key, previewTextView, false /* withAnimation */); + showKeyPreview(key, keyPreviewView, false /* withAnimation */); } }); 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. final ObjectAnimator scaleXAnimation = ObjectAnimator.ofFloat( - previewTextView, View.SCALE_X, mParams.getDismissEndScale()); + keyPreviewView, View.SCALE_X, mParams.getDismissEndScale()); final ObjectAnimator scaleYAnimation = ObjectAnimator.ofFloat( - previewTextView, View.SCALE_Y, mParams.getDismissEndScale()); + keyPreviewView, View.SCALE_Y, mParams.getDismissEndScale()); final AnimatorSet dismissAnimation = new AnimatorSet(); dismissAnimation.play(scaleXAnimation).with(scaleYAnimation); final int dismissDuration = Math.min( diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewDrawParams.java b/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewDrawParams.java index 37e5c889d..68c9831fa 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewDrawParams.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewDrawParams.java @@ -23,9 +23,9 @@ import com.android.inputmethod.latin.R; public final class KeyPreviewDrawParams { // XML attributes of {@link MainKeyboardView}. - public final int mLayoutId; public final int mPreviewOffset; public final int mPreviewHeight; + public final int mPreviewBackgroundResId; private int mShowUpDuration; private int mDismissDuration; private float mShowUpStartScale; @@ -63,13 +63,10 @@ public final class KeyPreviewDrawParams { R.styleable.MainKeyboardView_keyPreviewOffset, 0); mPreviewHeight = mainKeyboardViewAttr.getDimensionPixelSize( R.styleable.MainKeyboardView_keyPreviewHeight, 0); + mPreviewBackgroundResId = mainKeyboardViewAttr.getResourceId( + R.styleable.MainKeyboardView_keyPreviewBackground, 0); mLingerTimeout = mainKeyboardViewAttr.getInt( R.styleable.MainKeyboardView_keyPreviewLingerTimeout, 0); - mLayoutId = mainKeyboardViewAttr.getResourceId( - R.styleable.MainKeyboardView_keyPreviewLayout, 0); - if (mLayoutId == 0) { - mShowPopup = false; - } } public void setVisibleOffset(final int previewVisibleOffset) { diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewView.java b/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewView.java new file mode 100644 index 000000000..360faf829 --- /dev/null +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyPreviewView.java @@ -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]); + } +} |