Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f2749e41 authored by Tadashi G. Takaoka's avatar Tadashi G. Takaoka Committed by Android (Google) Code Review
Browse files

Merge "Revert "Move key preview related methods to KeyPreviewChoreographer""

parents ade1aa55 32d6c6a4
Loading
Loading
Loading
Loading
+231 −16
Original line number Diff line number Diff line
@@ -16,7 +16,10 @@

package com.android.inputmethod.keyboard;

import android.animation.Animator;
import android.animation.AnimatorInflater;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.SharedPreferences;
@@ -32,10 +35,13 @@ import android.preference.PreferenceManager;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.inputmethod.InputMethodSubtype;
import android.widget.TextView;

@@ -47,7 +53,6 @@ import com.android.inputmethod.keyboard.internal.DrawingPreviewPlacerView;
import com.android.inputmethod.keyboard.internal.GestureFloatingTextDrawingPreview;
import com.android.inputmethod.keyboard.internal.GestureTrailsDrawingPreview;
import com.android.inputmethod.keyboard.internal.KeyDrawParams;
import com.android.inputmethod.keyboard.internal.KeyPreviewChoreographer;
import com.android.inputmethod.keyboard.internal.KeyPreviewDrawParams;
import com.android.inputmethod.keyboard.internal.NonDistinctMultitouchHelper;
import com.android.inputmethod.keyboard.internal.SlidingKeyInputDrawingPreview;
@@ -66,6 +71,9 @@ import com.android.inputmethod.latin.utils.UsabilityStudyLogUtils;
import com.android.inputmethod.latin.utils.ViewLayoutUtils;
import com.android.inputmethod.research.ResearchLogger;

import java.util.ArrayDeque;
import java.util.HashMap;
import java.util.HashSet;
import java.util.WeakHashMap;

/**
@@ -153,8 +161,18 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack

    // Key preview
    private static final boolean FADE_OUT_KEY_TOP_LETTER_WHEN_KEY_IS_PRESSED = false;
    // Free {@link TextView} pool that can be used for key preview.
    private final ArrayDeque<TextView> mFreeKeyPreviewTextViews = CollectionUtils.newArrayDeque();
    // Map from {@link Key} to {@link TextView} that is currently being displayed as key preview.
    private final HashMap<Key,TextView> mShowingKeyPreviewTextViews = CollectionUtils.newHashMap();
    private final KeyPreviewDrawParams mKeyPreviewDrawParams;
    private final KeyPreviewChoreographer mKeyPreviewChoreographer;
    private static final float KEY_PREVIEW_START_ZOOM_IN_SCALE = 0.7f;
    private static final float KEY_PREVIEW_END_ZOOM_IN_SCALE = 1.0f;
    private static final float KEY_PREVIEW_END_ZOOM_OUT_SCALE = 0.7f;
    private static final AccelerateInterpolator ACCELERATE_INTERPOLATOR =
            new AccelerateInterpolator();
    private static final DecelerateInterpolator DECELERATE_INTERPOLATOR =
            new DecelerateInterpolator();

    // More keys keyboard
    private final Paint mBackgroundDimAlphaPaint = new Paint();
@@ -243,8 +261,6 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
                R.styleable.MainKeyboardView_altCodeKeyWhileTypingFadeinAnimator, 0);

        mKeyPreviewDrawParams = new KeyPreviewDrawParams(mainKeyboardViewAttr);
        mKeyPreviewChoreographer = new KeyPreviewChoreographer(mKeyPreviewDrawParams);

        final int moreKeysKeyboardLayoutId = mainKeyboardViewAttr.getResourceId(
                R.styleable.MainKeyboardView_moreKeysKeyboardLayout, 0);
        mConfigShowMoreKeysKeyboardAtTouchedPoint = mainKeyboardViewAttr.getBoolean(
@@ -461,13 +477,60 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
        return mKeyPreviewDrawParams.isPopupEnabled();
    }

    private TextView getKeyPreviewTextView(final Key key) {
        TextView previewTextView = mShowingKeyPreviewTextViews.remove(key);
        if (previewTextView != null) {
            return previewTextView;
        }
        previewTextView = mFreeKeyPreviewTextViews.poll();
        if (previewTextView != null) {
            return previewTextView;
        }
        final Context context = getContext();
        final int previewLayoutId = mKeyPreviewDrawParams.mLayoutId;
        if (previewLayoutId != 0) {
            previewTextView = (TextView)LayoutInflater.from(context)
                    .inflate(previewLayoutId, null);
        } else {
            previewTextView = new TextView(context);
        }
        locatePreviewPlacerView();
        mDrawingPreviewPlacerView.addView(
                previewTextView, ViewLayoutUtils.newLayoutParam(mDrawingPreviewPlacerView, 0, 0));
        return previewTextView;
    }

    // Implements {@link DrawingHandler.Callbacks} method.
    @Override
    public void dismissAllKeyPreviews() {
        mKeyPreviewChoreographer.dismissAllKeyPreviews();
        for (final Key key : new HashSet<Key>(mShowingKeyPreviewTextViews.keySet())) {
            dismissKeyPreviewWithoutDelay(key);
        }
        PointerTracker.setReleasedKeyGraphicsToAllKeys();
    }

    // Background state set
    private static final int[][][] KEY_PREVIEW_BACKGROUND_STATE_TABLE = {
        { // STATE_MIDDLE
            EMPTY_STATE_SET,
            { 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;

    // TODO: Take this method out of this class.
    @Override
    public void showKeyPreview(final Key key) {
        // If key is invalid or IME is already closed, we must not show key preview.
@@ -484,33 +547,185 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
            return;
        }

        final TextView previewTextView = mKeyPreviewChoreographer.getKeyPreviewTextView(
                key, getContext());
        locatePreviewPlacerView();
        mDrawingPreviewPlacerView.addView(
                previewTextView, ViewLayoutUtils.newLayoutParam(mDrawingPreviewPlacerView, 0, 0));
        final TextView previewTextView = getKeyPreviewTextView(key);
        final KeyDrawParams drawParams = mKeyDrawParams;
        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(keyboard.mIconsSet));
            previewTextView.setText(null);
        }

        previewTextView.measure(
                ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        final int keyDrawWidth = key.getDrawWidth();
        final int previewWidth = previewTextView.getMeasuredWidth();
        final int previewHeight = previewParams.mPreviewHeight;
        previewParams.setGeometry(previewTextView);
        getLocationInWindow(mOriginCoords);
        mKeyPreviewChoreographer.placeKeyPreview(key, previewTextView, keyboard.mIconsSet,
                mKeyDrawParams, getWidth(), mOriginCoords);
        mKeyPreviewChoreographer.showKeyPreview(key, previewTextView, isHardwareAccelerated());
        // 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;
        int previewX = key.getDrawX() - (previewWidth - keyDrawWidth) / 2
                + CoordinateUtils.x(mOriginCoords);
        if (previewX < 0) {
            previewX = 0;
            statePosition = STATE_LEFT;
        } else if (previewX > getWidth() - previewWidth) {
            previewX = getWidth() - previewWidth;
            statePosition = STATE_RIGHT;
        } else {
            statePosition = STATE_MIDDLE;
        }
        // The key preview is placed vertically above the top edge of the parent key with an
        // arbitrary offset.
        final int previewY = key.getY() - previewHeight + previewParams.mPreviewOffset
                + CoordinateUtils.y(mOriginCoords);

        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);

        if (!isHardwareAccelerated()) {
            previewTextView.setVisibility(VISIBLE);
            mShowingKeyPreviewTextViews.put(key, previewTextView);
            return;
        }
        previewTextView.setPivotX(previewWidth / 2.0f);
        previewTextView.setPivotY(previewHeight);

        final Animator zoomIn = createZoomInAniation(key, previewTextView);
        final Animator zoomOut = createZoomOutAnimation(key, previewTextView);
        final KeyPreviewAnimations animation = new KeyPreviewAnimations(zoomIn, zoomOut);
        previewTextView.setTag(animation);
        animation.startZoomIn();
    }

    // TODO: Move this internal class out to a separate external class.
    private static class KeyPreviewAnimations extends AnimatorListenerAdapter {
        private final Animator mZoomIn;
        private final Animator mZoomOut;

        public KeyPreviewAnimations(final Animator zoomIn, final Animator zoomOut) {
            mZoomIn = zoomIn;
            mZoomOut = zoomOut;
        }

        public void startZoomIn() {
            mZoomIn.start();
        }

        public void startZoomOut() {
            if (mZoomIn.isRunning()) {
                mZoomIn.addListener(this);
                return;
            }
            mZoomOut.start();
        }

        @Override
        public void onAnimationEnd(final Animator animation) {
            mZoomOut.start();
        }
    }

    // TODO: Take this method out of this class.
    private Animator createZoomInAniation(final Key key, final TextView previewTextView) {
        final ObjectAnimator scaleXAnimation = ObjectAnimator.ofFloat(
                previewTextView, SCALE_X, KEY_PREVIEW_START_ZOOM_IN_SCALE,
                KEY_PREVIEW_END_ZOOM_IN_SCALE);
        final ObjectAnimator scaleYAnimation = ObjectAnimator.ofFloat(
                previewTextView, SCALE_Y, KEY_PREVIEW_START_ZOOM_IN_SCALE,
                KEY_PREVIEW_END_ZOOM_IN_SCALE);
        final AnimatorSet zoomInAnimation = new AnimatorSet();
        zoomInAnimation.play(scaleXAnimation).with(scaleYAnimation);
        // TODO: Implement preference option to control key preview animation duration.
        zoomInAnimation.setDuration(mKeyPreviewDrawParams.mZoomInDuration);
        zoomInAnimation.setInterpolator(DECELERATE_INTERPOLATOR);
        zoomInAnimation.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(final Animator animation) {
                previewTextView.setVisibility(VISIBLE);
                mShowingKeyPreviewTextViews.put(key, previewTextView);
            }
        });
        return zoomInAnimation;
    }

    // TODO: Take this method out of this class.
    private Animator createZoomOutAnimation(final Key key, final TextView previewTextView) {
        final ObjectAnimator scaleXAnimation = ObjectAnimator.ofFloat(
                previewTextView, SCALE_X, KEY_PREVIEW_END_ZOOM_OUT_SCALE);
        final ObjectAnimator scaleYAnimation = ObjectAnimator.ofFloat(
                previewTextView, SCALE_Y, KEY_PREVIEW_END_ZOOM_OUT_SCALE);
        final AnimatorSet zoomOutAnimation = new AnimatorSet();
        zoomOutAnimation.play(scaleXAnimation).with(scaleYAnimation);
        // TODO: Implement preference option to control key preview animation duration.
        final int zoomOutDuration = Math.min(mKeyPreviewDrawParams.mZoomOutDuration,
                mKeyPreviewDrawParams.getLingerTimeout());
        zoomOutAnimation.setDuration(zoomOutDuration);
        zoomOutAnimation.setInterpolator(ACCELERATE_INTERPOLATOR);
        zoomOutAnimation.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(final Animator animation) {
                dismissKeyPreviewWithoutDelay(key);
            }
        });
        return zoomOutAnimation;
    }

    // Implements {@link TimerHandler.Callbacks} method.
    // TODO: Take this method out of this class.
    @Override
    public void dismissKeyPreviewWithoutDelay(final Key key) {
        mKeyPreviewChoreographer.dismissKeyPreview(key, false /* withAnimation */);
        if (key == null) {
            return;
        }
        final TextView previewTextView = mShowingKeyPreviewTextViews.remove(key);
        if (previewTextView != null) {
            final Object tag = previewTextView.getTag();
            if (tag instanceof Animator) {
                ((Animator)tag).cancel();
            }
            previewTextView.setTag(null);
            previewTextView.setVisibility(INVISIBLE);
            mFreeKeyPreviewTextViews.add(previewTextView);
        }
        // To redraw key top letter.
        invalidateKey(key);
    }

    // TODO: Take this method out of this class.
    @Override
    public void dismissKeyPreview(final Key key) {
        final TextView previewTextView = mShowingKeyPreviewTextViews.get(key);
        if (previewTextView == null) {
            return;
        }
        if (!isHardwareAccelerated()) {
            // TODO: Implement preference option to control key preview method and duration.
            mDrawingHandler.dismissKeyPreview(mKeyPreviewDrawParams.getLingerTimeout(), key);
            return;
        }
        mKeyPreviewChoreographer.dismissKeyPreview(key, true /* withAnimation */);
        final Object tag = previewTextView.getTag();
        if (tag instanceof KeyPreviewAnimations) {
            final KeyPreviewAnimations animation = (KeyPreviewAnimations)tag;
            animation.startZoomOut();
        }
    }

    public void setSlidingKeyInputPreviewEnabled(final boolean enabled) {
@@ -883,7 +1098,7 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
        }
        // Don't draw key top letter when key preview is showing.
        if (FADE_OUT_KEY_TOP_LETTER_WHEN_KEY_IS_PRESSED
                && mKeyPreviewChoreographer.isShowingKeyPreview(key)) {
                && mShowingKeyPreviewTextViews.containsKey(key)) {
            // TODO: Fade out animation for the key top letter, and fade in animation for the key
            // background color when the user presses the key.
            return;
+0 −279

File deleted.

Preview size limit exceeded, changes collapsed.

+0 −1
Original line number Diff line number Diff line
@@ -26,7 +26,6 @@ public final class KeyPreviewDrawParams {
    public final int mLayoutId;
    public final int mPreviewOffset;
    public final int mPreviewHeight;
    // TODO: Move those parameters to preferences.
    public final int mZoomInDuration;
    public final int mZoomOutDuration;
    private int mLingerTimeout;