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

Commit c1780c16 authored by Tadashi G. Takaoka's avatar Tadashi G. Takaoka
Browse files

Revise gesture preview trail design

Bug: 7042741
Change-Id: I99e3b3a6fc52afaee3cc5daf371131c3afebb3ae
parent 15496ec4
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -90,7 +90,8 @@
        <!-- Interval of updating gesture preview trail in millisecond. -->
        <attr name="gesturePreviewTrailUpdateInterval" format="integer" />
        <attr name="gesturePreviewTrailColor" format="color" />
        <attr name="gesturePreviewTrailWidth" format="dimension" />
        <attr name="gesturePreviewTrailStartWidth" format="dimension" />
        <attr name="gesturePreviewTrailEndWidth" format="dimension" />
    </declare-styleable>

    <declare-styleable name="MainKeyboardView">
+2 −1
Original line number Diff line number Diff line
@@ -100,7 +100,8 @@
    <fraction name="center_suggestion_percentile">36%</fraction>

    <!-- Gesture preview trail parameters -->
    <dimen name="gesture_preview_trail_width">2.5dp</dimen>
    <dimen name="gesture_preview_trail_start_width">18.0dp</dimen>
    <dimen name="gesture_preview_trail_end_width">2.5dp</dimen>
    <!-- Gesture floating preview text parameters -->
    <dimen name="gesture_floating_preview_text_size">24dp</dimen>
    <dimen name="gesture_floating_preview_text_offset">73dp</dimen>
+2 −1
Original line number Diff line number Diff line
@@ -77,7 +77,8 @@
        <item name="gesturePreviewTrailFadeoutDuration">@integer/config_gesture_preview_trail_fadeout_duration</item>
        <item name="gesturePreviewTrailUpdateInterval">@integer/config_gesture_preview_trail_update_interval</item>
        <item name="gesturePreviewTrailColor">@android:color/holo_blue_light</item>
        <item name="gesturePreviewTrailWidth">@dimen/gesture_preview_trail_width</item>
        <item name="gesturePreviewTrailStartWidth">@dimen/gesture_preview_trail_start_width</item>
        <item name="gesturePreviewTrailEndWidth">@dimen/gesture_preview_trail_end_width</item>
        <!-- Common attributes of MainKeyboardView -->
        <item name="keyHysteresisDistance">@dimen/config_key_hysteresis_distance</item>
        <item name="touchNoiseThresholdTime">@integer/config_touch_noise_threshold_time</item>
+42 −17
Original line number Diff line number Diff line
@@ -17,16 +17,18 @@ package com.android.inputmethod.keyboard.internal;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Xfermode;
import android.os.SystemClock;

import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.ResizableIntArray;

class GesturePreviewTrail {
final class GesturePreviewTrail {
    private static final int DEFAULT_CAPACITY = GestureStrokeWithPreviewTrail.PREVIEW_CAPACITY;

    private final GesturePreviewTrailParams mPreviewParams;
    private final ResizableIntArray mXCoordinates = new ResizableIntArray(DEFAULT_CAPACITY);
    private final ResizableIntArray mYCoordinates = new ResizableIntArray(DEFAULT_CAPACITY);
    private final ResizableIntArray mEventTimes = new ResizableIntArray(DEFAULT_CAPACITY);
@@ -34,28 +36,39 @@ class GesturePreviewTrail {
    private long mCurrentDownTime;
    private int mTrailStartIndex;

    private final static Xfermode PORTER_DUFF_MODE_SRC =
            new PorterDuffXfermode(PorterDuff.Mode.SRC);

    // Use this value as imaginary zero because x-coordinates may be zero.
    private static final int DOWN_EVENT_MARKER = -128;

    static class GesturePreviewTrailParams {
    static final class Params {
        public final int mTrailColor;
        public final float mTrailStartWidth;
        public final float mTrailEndWidth;
        public final int mFadeoutStartDelay;
        public final int mFadeoutDuration;
        public final int mUpdateInterval;

        public GesturePreviewTrailParams(final TypedArray keyboardViewAttr) {
        public final int mTrailLingerDuration;

        public Params(final TypedArray keyboardViewAttr) {
            mTrailColor = keyboardViewAttr.getColor(
                    R.styleable.KeyboardView_gesturePreviewTrailColor, 0);
            mTrailStartWidth = keyboardViewAttr.getDimension(
                    R.styleable.KeyboardView_gesturePreviewTrailStartWidth, 0.0f);
            mTrailEndWidth = keyboardViewAttr.getDimension(
                    R.styleable.KeyboardView_gesturePreviewTrailEndWidth, 0.0f);
            mFadeoutStartDelay = keyboardViewAttr.getInt(
                    R.styleable.KeyboardView_gesturePreviewTrailFadeoutStartDelay, 0);
            mFadeoutDuration = keyboardViewAttr.getInt(
                    R.styleable.KeyboardView_gesturePreviewTrailFadeoutDuration, 0);
            mTrailLingerDuration = mFadeoutStartDelay + mFadeoutDuration;
            mUpdateInterval = keyboardViewAttr.getInt(
                    R.styleable.KeyboardView_gesturePreviewTrailUpdateInterval, 0);
        }
    }

    public GesturePreviewTrail(final GesturePreviewTrailParams params) {
        mPreviewParams = params;
    }

    private static int markAsDownEvent(final int xCoord) {
        return DOWN_EVENT_MARKER - xCoord;
    }
@@ -94,23 +107,30 @@ class GesturePreviewTrail {
        }
    }

    private int getAlpha(final int elapsedTime) {
        if (elapsedTime < mPreviewParams.mFadeoutStartDelay) {
    private static int getAlpha(final int elapsedTime, final Params params) {
        if (elapsedTime < params.mFadeoutStartDelay) {
            return Constants.Color.ALPHA_OPAQUE;
        }
        final int decreasingAlpha = Constants.Color.ALPHA_OPAQUE
                * (elapsedTime - mPreviewParams.mFadeoutStartDelay)
                / mPreviewParams.mFadeoutDuration;
                * (elapsedTime - params.mFadeoutStartDelay)
                / params.mFadeoutDuration;
        return Constants.Color.ALPHA_OPAQUE - decreasingAlpha;
    }

    private static float getWidth(final int elapsedTime, final Params params) {
        return Math.max((params.mTrailLingerDuration - elapsedTime)
                * (params.mTrailStartWidth - params.mTrailEndWidth)
                / params.mTrailLingerDuration, 0.0f);
    }

    /**
     * Draw gesture preview trail
     * @param canvas The canvas to draw the gesture preview trail
     * @param paint The paint object to be used to draw the gesture preview trail
     * @param params The drawing parameters of gesture preview trail
     * @return true if some gesture preview trails remain to be drawn
     */
    public boolean drawGestureTrail(final Canvas canvas, final Paint paint) {
    public boolean drawGestureTrail(final Canvas canvas, final Paint paint, final Params params) {
        final int trailSize = mEventTimes.getLength();
        if (trailSize == 0) {
            return false;
@@ -120,13 +140,11 @@ class GesturePreviewTrail {
        final int[] xCoords = mXCoordinates.getPrimitiveArray();
        final int[] yCoords = mYCoordinates.getPrimitiveArray();
        final int sinceDown = (int)(SystemClock.uptimeMillis() - mCurrentDownTime);
        final int lingeringDuration = mPreviewParams.mFadeoutStartDelay
                + mPreviewParams.mFadeoutDuration;
        int startIndex;
        for (startIndex = mTrailStartIndex; startIndex < trailSize; startIndex++) {
            final int elapsedTime = sinceDown - eventTimes[startIndex];
            // Skip too old trail points.
            if (elapsedTime < lingeringDuration) {
            if (elapsedTime < params.mTrailLingerDuration) {
                break;
            }
        }
@@ -135,13 +153,20 @@ class GesturePreviewTrail {
        if (startIndex < trailSize) {
            int lastX = getXCoordValue(xCoords[startIndex]);
            int lastY = yCoords[startIndex];
            paint.setColor(params.mTrailColor);
            paint.setStyle(Paint.Style.STROKE);
            paint.setStrokeCap(Paint.Cap.ROUND);
            paint.setXfermode(PORTER_DUFF_MODE_SRC);
            for (int i = startIndex + 1; i < trailSize - 1; i++) {
                final int x = xCoords[i];
                final int y = yCoords[i];
                final int elapsedTime = sinceDown - eventTimes[i];
                // Draw trail line only when the current point isn't a down point.
                if (!isDownEventXCoord(x)) {
                    paint.setAlpha(getAlpha(elapsedTime));
                    final int alpha = getAlpha(elapsedTime, params);
                    paint.setAlpha(alpha);
                    final float width = getWidth(elapsedTime, params);
                    paint.setStrokeWidth(width);
                    canvas.drawLine(lastX, lastY, x, y, paint);
                }
                lastX = getXCoordValue(x);
+17 −19
Original line number Diff line number Diff line
@@ -21,6 +21,8 @@ import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Message;
@@ -30,14 +32,12 @@ import android.util.SparseArray;
import android.widget.RelativeLayout;

import com.android.inputmethod.keyboard.PointerTracker;
import com.android.inputmethod.keyboard.internal.GesturePreviewTrail.GesturePreviewTrailParams;
import com.android.inputmethod.keyboard.internal.GesturePreviewTrail.Params;
import com.android.inputmethod.latin.CollectionUtils;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.StaticInnerHandlerWrapper;

public class PreviewPlacerView extends RelativeLayout {
    private final Paint mGesturePaint;
    private final Paint mTextPaint;
    private final int mGestureFloatingPreviewTextColor;
    private final int mGestureFloatingPreviewTextOffset;
    private final int mGestureFloatingPreviewColor;
@@ -51,8 +51,11 @@ public class PreviewPlacerView extends RelativeLayout {

    private final SparseArray<GesturePreviewTrail> mGesturePreviewTrails =
            CollectionUtils.newSparseArray();
    private final GesturePreviewTrailParams mGesturePreviewTrailParams;
    private final Params mGesturePreviewTrailParams;
    private final Paint mGesturePaint;
    private boolean mDrawsGesturePreviewTrail;

    private final Paint mTextPaint;
    private String mGestureFloatingPreviewText;
    private final int mGestureFloatingPreviewTextHeight;
    // {@link RectF} is needed for {@link Canvas#drawRoundRect(RectF, float, float, Paint)}.
@@ -60,8 +63,6 @@ public class PreviewPlacerView extends RelativeLayout {
    private int mLastPointerX;
    private int mLastPointerY;
    private static final char[] TEXT_HEIGHT_REFERENCE_CHAR = { 'M' };

    private boolean mDrawsGesturePreviewTrail;
    private boolean mDrawsGestureFloatingPreviewText;

    private final DrawingHandler mDrawingHandler;
@@ -70,10 +71,10 @@ public class PreviewPlacerView extends RelativeLayout {
        private static final int MSG_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT = 0;
        private static final int MSG_UPDATE_GESTURE_PREVIEW_TRAIL = 1;

        private final GesturePreviewTrailParams mGesturePreviewTrailParams;
        private final Params mGesturePreviewTrailParams;

        public DrawingHandler(final PreviewPlacerView outerInstance,
                final GesturePreviewTrailParams gesturePreviewTrailParams) {
                final Params gesturePreviewTrailParams) {
            super(outerInstance);
            mGesturePreviewTrailParams = gesturePreviewTrailParams;
        }
@@ -146,21 +147,13 @@ public class PreviewPlacerView extends RelativeLayout {
                R.styleable.KeyboardView_gestureFloatingPreviewRoundRadius, 0.0f);
        mGestureFloatingPreviewTextLingerTimeout = keyboardViewAttr.getInt(
                R.styleable.KeyboardView_gestureFloatingPreviewTextLingerTimeout, 0);
        final int gesturePreviewTrailColor = keyboardViewAttr.getColor(
                R.styleable.KeyboardView_gesturePreviewTrailColor, 0);
        final int gesturePreviewTrailWidth = keyboardViewAttr.getDimensionPixelSize(
                R.styleable.KeyboardView_gesturePreviewTrailWidth, 0);
        mGesturePreviewTrailParams = new GesturePreviewTrailParams(keyboardViewAttr);
        mGesturePreviewTrailParams = new Params(keyboardViewAttr);
        keyboardViewAttr.recycle();

        mDrawingHandler = new DrawingHandler(this, mGesturePreviewTrailParams);

        final Paint gesturePaint = new Paint();
        gesturePaint.setAntiAlias(true);
        gesturePaint.setStyle(Paint.Style.STROKE);
        gesturePaint.setStrokeJoin(Paint.Join.ROUND);
        gesturePaint.setColor(gesturePreviewTrailColor);
        gesturePaint.setStrokeWidth(gesturePreviewTrailWidth);
        mGesturePaint = gesturePaint;

        final Paint textPaint = new Paint();
@@ -172,6 +165,10 @@ public class PreviewPlacerView extends RelativeLayout {
        final Rect textRect = new Rect();
        textPaint.getTextBounds(TEXT_HEIGHT_REFERENCE_CHAR, 0, 1, textRect);
        mGestureFloatingPreviewTextHeight = textRect.height();

        final Paint layerPaint = new Paint();
        layerPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER));
        setLayerType(LAYER_TYPE_HARDWARE, layerPaint);
    }

    public void setOrigin(final int x, final int y) {
@@ -190,7 +187,7 @@ public class PreviewPlacerView extends RelativeLayout {
        synchronized (mGesturePreviewTrails) {
            trail = mGesturePreviewTrails.get(tracker.mPointerId);
            if (trail == null) {
                trail = new GesturePreviewTrail(mGesturePreviewTrailParams);
                trail = new GesturePreviewTrail();
                mGesturePreviewTrails.put(tracker.mPointerId, trail);
            }
        }
@@ -214,7 +211,8 @@ public class PreviewPlacerView extends RelativeLayout {
                for (int index = 0; index < trailsCount; index++) {
                    final GesturePreviewTrail trail = mGesturePreviewTrails.valueAt(index);
                    needsUpdatingGesturePreviewTrail |=
                            trail.drawGestureTrail(canvas, mGesturePaint);
                            trail.drawGestureTrail(canvas, mGesturePaint,
                                    mGesturePreviewTrailParams);
                }
            }
            if (needsUpdatingGesturePreviewTrail) {