Add multiple gesture preview trails animation

Change-Id: I533e6de9b138317472565be82c8ba5e422472888
main
Tadashi G. Takaoka 2012-08-20 12:57:34 +09:00
parent 64a26b4389
commit 333a300586
8 changed files with 316 additions and 61 deletions

View File

@ -131,6 +131,12 @@
<attr name="gestureFloatingPreviewTextConnectorWidth" format="dimension" />
<!-- Delay after gesture input and gesture floating preview text dismissing in millisecond -->
<attr name="gestureFloatingPreviewTextLingerTimeout" format="integer" />
<!-- Delay after gesture trail starts fading out in millisecond. -->
<attr name="gesturePreviewTrailFadeoutStartDelay" format="integer" />
<!-- Duration while gesture preview trail is fading out in millisecond. -->
<attr name="gesturePreviewTrailFadeoutDuration" format="integer" />
<!-- Interval of updating gesture preview trail in millisecond. -->
<attr name="gesturePreviewTrailUpdateInterval" format="integer" />
<attr name="gesturePreviewTrailColor" format="color" />
<attr name="gesturePreviewTrailWidth" format="dimension" />
</declare-styleable>

View File

@ -50,6 +50,9 @@
-->
<integer name="config_key_preview_linger_timeout">70</integer>
<integer name="config_gesture_floating_preview_text_linger_timeout">200</integer>
<integer name="config_gesture_preview_trail_fadeout_start_delay">100</integer>
<integer name="config_gesture_preview_trail_fadeout_duration">1000</integer>
<integer name="config_gesture_preview_trail_update_interval">20</integer>
<!--
Configuration for MainKeyboardView
-->

View File

@ -78,6 +78,9 @@
<item name="gestureFloatingPreviewTextConnectorColor">@android:color/white</item>
<item name="gestureFloatingPreviewTextConnectorWidth">@dimen/gesture_floating_preview_text_connector_width</item>
<item name="gestureFloatingPreviewTextLingerTimeout">@integer/config_gesture_floating_preview_text_linger_timeout</item>
<item name="gesturePreviewTrailFadeoutStartDelay">@integer/config_gesture_preview_trail_fadeout_start_delay</item>
<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>
<!-- Common attributes of MainKeyboardView -->

View File

@ -17,14 +17,13 @@
package com.android.inputmethod.keyboard;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.SystemClock;
import android.util.Log;
import android.view.MotionEvent;
import com.android.inputmethod.accessibility.AccessibilityUtils;
import com.android.inputmethod.keyboard.internal.GestureStroke;
import com.android.inputmethod.keyboard.internal.GestureStrokeWithPreviewTrail;
import com.android.inputmethod.keyboard.internal.PointerTrackerQueue;
import com.android.inputmethod.latin.CollectionUtils;
import com.android.inputmethod.latin.InputPointers;
@ -211,7 +210,7 @@ public class PointerTracker implements PointerTrackerQueue.Element {
private static final KeyboardActionListener EMPTY_LISTENER =
new KeyboardActionListener.Adapter();
private final GestureStroke mGestureStroke;
private final GestureStrokeWithPreviewTrail mGestureStrokeWithPreviewTrail;
public static void init(boolean hasDistinctMultitouch,
boolean needsPhantomSuddenMoveEventHack) {
@ -297,7 +296,8 @@ public class PointerTracker implements PointerTrackerQueue.Element {
final int trackersSize = sTrackers.size();
for (int i = 0; i < trackersSize; ++i) {
final PointerTracker tracker = sTrackers.get(i);
tracker.mGestureStroke.appendIncrementalBatchPoints(sAggregratedPointers);
tracker.mGestureStrokeWithPreviewTrail.appendIncrementalBatchPoints(
sAggregratedPointers);
}
return sAggregratedPointers;
}
@ -308,7 +308,7 @@ public class PointerTracker implements PointerTrackerQueue.Element {
final int trackersSize = sTrackers.size();
for (int i = 0; i < trackersSize; ++i) {
final PointerTracker tracker = sTrackers.get(i);
tracker.mGestureStroke.appendAllBatchPoints(sAggregratedPointers);
tracker.mGestureStrokeWithPreviewTrail.appendAllBatchPoints(sAggregratedPointers);
}
return sAggregratedPointers;
}
@ -319,7 +319,7 @@ public class PointerTracker implements PointerTrackerQueue.Element {
final int trackersSize = sTrackers.size();
for (int i = 0; i < trackersSize; ++i) {
final PointerTracker tracker = sTrackers.get(i);
tracker.mGestureStroke.reset();
tracker.mGestureStrokeWithPreviewTrail.reset();
}
sAggregratedPointers.reset();
}
@ -329,7 +329,7 @@ public class PointerTracker implements PointerTrackerQueue.Element {
throw new NullPointerException();
}
mPointerId = id;
mGestureStroke = new GestureStroke(id);
mGestureStrokeWithPreviewTrail = new GestureStrokeWithPreviewTrail(id);
setKeyDetectorInner(handler.getKeyDetector());
mListener = handler.getKeyboardActionListener();
mDrawingProxy = handler.getDrawingProxy();
@ -429,7 +429,7 @@ public class PointerTracker implements PointerTrackerQueue.Element {
mKeyDetector = keyDetector;
mKeyboard = keyDetector.getKeyboard();
mIsAlphabetKeyboard = mKeyboard.mId.isAlphabetKeyboard();
mGestureStroke.setGestureSampleLength(mKeyboard.mMostCommonKeyWidth);
mGestureStrokeWithPreviewTrail.setGestureSampleLength(mKeyboard.mMostCommonKeyWidth);
final Key newKey = mKeyDetector.detectHitKey(mKeyX, mKeyY);
if (newKey != mCurrentKey) {
if (mDrawingProxy != null) {
@ -539,10 +539,8 @@ public class PointerTracker implements PointerTrackerQueue.Element {
mDrawingProxy.invalidateKey(key);
}
public void drawGestureTrail(final Canvas canvas, final Paint paint) {
if (mInGesture) {
mGestureStroke.drawGestureTrail(canvas, paint);
}
public GestureStrokeWithPreviewTrail getGestureStrokeWithPreviewTrail() {
return mGestureStrokeWithPreviewTrail;
}
public int getLastX() {
@ -692,7 +690,7 @@ public class PointerTracker implements PointerTrackerQueue.Element {
mIsPossibleGesture = true;
// TODO: pointer times should be relative to first down even in entire batch input
// instead of resetting to 0 for each new down event.
mGestureStroke.addPoint(x, y, 0, false);
mGestureStrokeWithPreviewTrail.addPoint(x, y, 0, false);
}
}
}
@ -733,7 +731,7 @@ public class PointerTracker implements PointerTrackerQueue.Element {
final long eventTime, final boolean isHistorical, final Key key) {
final int gestureTime = (int)(eventTime - tracker.getDownTime());
if (sShouldHandleGesture && mIsPossibleGesture) {
final GestureStroke stroke = mGestureStroke;
final GestureStroke stroke = mGestureStrokeWithPreviewTrail;
stroke.addPoint(x, y, gestureTime, isHistorical);
if (!mInGesture && stroke.isStartOfAGesture()) {
startBatchInput();

View File

@ -0,0 +1,161 @@
/*
* Copyright (C) 2012 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.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.SystemClock;
import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.ResizableIntArray;
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);
private int mCurrentStrokeId;
private long mCurrentDownTime;
// Use this value as imaginary zero because x-coordinates may be zero.
private static final int DOWN_EVENT_MARKER = -128;
static class GesturePreviewTrailParams {
public final int mFadeoutStartDelay;
public final int mFadeoutDuration;
public final int mUpdateInterval;
public GesturePreviewTrailParams(final TypedArray keyboardViewAttr) {
mFadeoutStartDelay = keyboardViewAttr.getInt(
R.styleable.KeyboardView_gesturePreviewTrailFadeoutStartDelay, 0);
mFadeoutDuration = keyboardViewAttr.getInt(
R.styleable.KeyboardView_gesturePreviewTrailFadeoutDuration, 0);
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;
}
private static boolean isDownEventXCoord(final int xCoordOrMark) {
return xCoordOrMark <= DOWN_EVENT_MARKER;
}
private static int getXCoordValue(final int xCoordOrMark) {
return isDownEventXCoord(xCoordOrMark)
? DOWN_EVENT_MARKER - xCoordOrMark : xCoordOrMark;
}
public void addStroke(final GestureStrokeWithPreviewTrail stroke, final long downTime) {
final int strokeId = stroke.getGestureStrokeId();
final boolean isNewStroke = strokeId != mCurrentStrokeId;
final int trailSize = mEventTimes.getLength();
stroke.appendPreviewStroke(mEventTimes, mXCoordinates, mYCoordinates);
final int newTrailSize = mEventTimes.getLength();
if (stroke.getGestureStrokePreviewSize() == 0) {
return;
}
if (isNewStroke) {
final int elapsedTime = (int)(downTime - mCurrentDownTime);
final int[] eventTimes = mEventTimes.getPrimitiveArray();
for (int i = 0; i < trailSize; i++) {
eventTimes[i] -= elapsedTime;
}
if (newTrailSize > trailSize) {
final int[] xCoords = mXCoordinates.getPrimitiveArray();
xCoords[trailSize] = markAsDownEvent(xCoords[trailSize]);
}
mCurrentDownTime = downTime;
mCurrentStrokeId = strokeId;
}
}
private int getAlpha(final int elapsedTime) {
if (elapsedTime < mPreviewParams.mFadeoutStartDelay) {
return Constants.Color.ALPHA_OPAQUE;
}
final int decreasingAlpha = Constants.Color.ALPHA_OPAQUE
* (elapsedTime - mPreviewParams.mFadeoutStartDelay)
/ mPreviewParams.mFadeoutDuration;
return Constants.Color.ALPHA_OPAQUE - decreasingAlpha;
}
/**
* 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
* @return true if some gesture preview trails remain to be drawn
*/
public boolean drawGestureTrail(final Canvas canvas, final Paint paint) {
final int trailSize = mEventTimes.getLength();
if (trailSize == 0) {
return false;
}
final int[] eventTimes = mEventTimes.getPrimitiveArray();
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 = 0; startIndex < trailSize; startIndex++) {
final int elapsedTime = sinceDown - eventTimes[startIndex];
// Skip too old trail points.
if (elapsedTime < lingeringDuration) {
break;
}
}
if (startIndex < trailSize) {
int lastX = getXCoordValue(xCoords[startIndex]);
int lastY = yCoords[startIndex];
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));
canvas.drawLine(lastX, lastY, x, y, paint);
}
lastX = getXCoordValue(x);
lastY = y;
}
}
// TODO: Implement ring buffer to avoid moving points.
// Discard faded out points.
final int newSize = trailSize - startIndex;
System.arraycopy(eventTimes, startIndex, eventTimes, 0, newSize);
System.arraycopy(xCoords, startIndex, xCoords, 0, newSize);
System.arraycopy(yCoords, startIndex, yCoords, 0, newSize);
mEventTimes.setLength(newSize);
mXCoordinates.setLength(newSize);
mYCoordinates.setLength(newSize);
return newSize > 0;
}
}

View File

@ -14,10 +14,6 @@
package com.android.inputmethod.keyboard.internal;
import android.graphics.Canvas;
import android.graphics.Paint;
import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.InputPointers;
import com.android.inputmethod.latin.ResizableIntArray;
@ -48,13 +44,8 @@ public class GestureStroke {
private static final float DOUBLE_PI = (float)(2.0f * Math.PI);
// Fade based on number of gesture samples, see MIN_GESTURE_SAMPLING_RATIO_TO_KEY_HEIGHT
private static final int DRAWING_GESTURE_FADE_START = 10;
private static final int DRAWING_GESTURE_FADE_RATE = 6;
public GestureStroke(int pointerId) {
public GestureStroke(final int pointerId) {
mPointerId = pointerId;
reset();
}
public void setGestureSampleLength(final int keyWidth) {
@ -158,7 +149,7 @@ public class GestureStroke {
if (dx == 0 && dy == 0) return 0;
// Would it be faster to call atan2f() directly via JNI? Not sure about what the JIT
// does with Math.atan2().
return (float)Math.atan2((double)dy, (double)dx);
return (float)Math.atan2(dy, dx);
}
private static float getAngleDiff(final float a1, final float a2) {
@ -168,20 +159,4 @@ public class GestureStroke {
}
return diff;
}
public void drawGestureTrail(final Canvas canvas, final Paint paint) {
// TODO: These paint parameter interpolation should be tunable, possibly introduce an object
// that implements an interface such as Paint getPaint(int step, int strokePoints)
final int size = mXCoordinates.getLength();
final int[] xCoords = mXCoordinates.getPrimitiveArray();
final int[] yCoords = mYCoordinates.getPrimitiveArray();
int alpha = Constants.Color.ALPHA_OPAQUE;
for (int i = size - 1; i > 0 && alpha > 0; i--) {
paint.setAlpha(alpha);
if (size - i > DRAWING_GESTURE_FADE_START) {
alpha -= DRAWING_GESTURE_FADE_RATE;
}
canvas.drawLine(xCoords[i - 1], yCoords[i - 1], xCoords[i], yCoords[i], paint);
}
}
}

View File

@ -0,0 +1,70 @@
/*
* Copyright (C) 2012 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 com.android.inputmethod.latin.ResizableIntArray;
public class GestureStrokeWithPreviewTrail extends GestureStroke {
public static final int PREVIEW_CAPACITY = 256;
private final ResizableIntArray mPreviewEventTimes = new ResizableIntArray(PREVIEW_CAPACITY);
private final ResizableIntArray mPreviewXCoordinates = new ResizableIntArray(PREVIEW_CAPACITY);
private final ResizableIntArray mPreviewYCoordinates = new ResizableIntArray(PREVIEW_CAPACITY);
private int mStrokeId;
private int mLastPreviewSize;
public GestureStrokeWithPreviewTrail(final int pointerId) {
super(pointerId);
}
@Override
public void reset() {
super.reset();
mStrokeId++;
mLastPreviewSize = 0;
mPreviewEventTimes.setLength(0);
mPreviewXCoordinates.setLength(0);
mPreviewYCoordinates.setLength(0);
}
public int getGestureStrokeId() {
return mStrokeId;
}
public int getGestureStrokePreviewSize() {
return mPreviewEventTimes.getLength();
}
@Override
public void addPoint(final int x, final int y, final int time, final boolean isHistorical) {
super.addPoint(x, y, time, isHistorical);
mPreviewEventTimes.add(time);
mPreviewXCoordinates.add(x);
mPreviewYCoordinates.add(y);
}
public void appendPreviewStroke(final ResizableIntArray eventTimes,
final ResizableIntArray xCoords, final ResizableIntArray yCoords) {
final int length = mPreviewEventTimes.getLength() - mLastPreviewSize;
if (length <= 0) {
return;
}
eventTimes.append(mPreviewEventTimes, mLastPreviewSize, length);
xCoords.append(mPreviewXCoordinates, mLastPreviewSize, length);
yCoords.append(mPreviewYCoordinates, mLastPreviewSize, length);
mLastPreviewSize = mPreviewEventTimes.getLength();
}
}

View File

@ -28,6 +28,7 @@ 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.latin.CollectionUtils;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.StaticInnerHandlerWrapper;
@ -48,7 +49,9 @@ public class PreviewPlacerView extends RelativeLayout {
private int mXOrigin;
private int mYOrigin;
private final SparseArray<PointerTracker> mPointers = CollectionUtils.newSparseArray();
private final SparseArray<GesturePreviewTrail> mGesturePreviewTrails =
CollectionUtils.newSparseArray();
private final GesturePreviewTrailParams mGesturePreviewTrailParams;
private String mGestureFloatingPreviewText;
private int mLastPointerX;
@ -57,23 +60,31 @@ public class PreviewPlacerView extends RelativeLayout {
private boolean mDrawsGesturePreviewTrail;
private boolean mDrawsGestureFloatingPreviewText;
private final DrawingHandler mDrawingHandler = new DrawingHandler(this);
private final DrawingHandler mDrawingHandler;
private static class DrawingHandler extends StaticInnerHandlerWrapper<PreviewPlacerView> {
private static final int MSG_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT = 0;
private static final int MSG_UPDATE_GESTURE_PREVIEW_TRAIL = 1;
public DrawingHandler(PreviewPlacerView outerInstance) {
private final GesturePreviewTrailParams mGesturePreviewTrailParams;
public DrawingHandler(final PreviewPlacerView outerInstance,
final GesturePreviewTrailParams gesturePreviewTrailParams) {
super(outerInstance);
mGesturePreviewTrailParams = gesturePreviewTrailParams;
}
@Override
public void handleMessage(Message msg) {
public void handleMessage(final Message msg) {
final PreviewPlacerView placerView = getOuterInstance();
if (placerView == null) return;
switch (msg.what) {
case MSG_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT:
placerView.setGestureFloatingPreviewText(null);
break;
case MSG_UPDATE_GESTURE_PREVIEW_TRAIL:
placerView.invalidate();
break;
}
}
@ -89,16 +100,27 @@ public class PreviewPlacerView extends RelativeLayout {
placerView.mGestureFloatingPreviewTextLingerTimeout);
}
private void cancelUpdateGestureTrailPreview() {
removeMessages(MSG_UPDATE_GESTURE_PREVIEW_TRAIL);
}
public void postUpdateGestureTrailPreview() {
cancelUpdateGestureTrailPreview();
sendMessageDelayed(obtainMessage(MSG_UPDATE_GESTURE_PREVIEW_TRAIL),
mGesturePreviewTrailParams.mUpdateInterval);
}
public void cancelAllMessages() {
cancelDismissGestureFloatingPreviewText();
cancelUpdateGestureTrailPreview();
}
}
public PreviewPlacerView(Context context, AttributeSet attrs) {
public PreviewPlacerView(final Context context, final AttributeSet attrs) {
this(context, attrs, R.attr.keyboardViewStyle);
}
public PreviewPlacerView(Context context, AttributeSet attrs, int defStyle) {
public PreviewPlacerView(final Context context, final AttributeSet attrs, final int defStyle) {
super(context);
setWillNotDraw(false);
@ -128,8 +150,11 @@ public class PreviewPlacerView extends RelativeLayout {
R.styleable.KeyboardView_gesturePreviewTrailColor, 0);
final int gesturePreviewTrailWidth = keyboardViewAttr.getDimensionPixelSize(
R.styleable.KeyboardView_gesturePreviewTrailWidth, 0);
mGesturePreviewTrailParams = new GesturePreviewTrailParams(keyboardViewAttr);
keyboardViewAttr.recycle();
mDrawingHandler = new DrawingHandler(this, mGesturePreviewTrailParams);
mGesturePaint = new Paint();
mGesturePaint.setAntiAlias(true);
mGesturePaint.setStyle(Paint.Style.STROKE);
@ -144,21 +169,28 @@ public class PreviewPlacerView extends RelativeLayout {
mTextPaint.setTextSize(gestureFloatingPreviewTextSize);
}
public void setOrigin(int x, int y) {
public void setOrigin(final int x, final int y) {
mXOrigin = x;
mYOrigin = y;
}
public void setGesturePreviewMode(boolean drawsGesturePreviewTrail,
boolean drawsGestureFloatingPreviewText) {
public void setGesturePreviewMode(final boolean drawsGesturePreviewTrail,
final boolean drawsGestureFloatingPreviewText) {
mDrawsGesturePreviewTrail = drawsGesturePreviewTrail;
mDrawsGestureFloatingPreviewText = drawsGestureFloatingPreviewText;
}
public void invalidatePointer(PointerTracker tracker) {
synchronized (mPointers) {
mPointers.put(tracker.mPointerId, tracker);
public void invalidatePointer(final PointerTracker tracker) {
GesturePreviewTrail trail;
synchronized (mGesturePreviewTrails) {
trail = mGesturePreviewTrails.get(tracker.mPointerId);
if (trail == null) {
trail = new GesturePreviewTrail(mGesturePreviewTrailParams);
mGesturePreviewTrails.put(tracker.mPointerId, trail);
}
}
trail.addStroke(tracker.getGestureStrokeWithPreviewTrail(), tracker.getDownTime());
mLastPointerX = tracker.getLastX();
mLastPointerY = tracker.getLastY();
// TODO: Should narrow the invalidate region.
@ -166,17 +198,23 @@ public class PreviewPlacerView extends RelativeLayout {
}
@Override
public void onDraw(Canvas canvas) {
public void onDraw(final Canvas canvas) {
super.onDraw(canvas);
canvas.translate(mXOrigin, mYOrigin);
if (mDrawsGesturePreviewTrail) {
synchronized (mPointers) {
final int trackerCount = mPointers.size();
for (int index = 0; index < trackerCount; index++) {
final PointerTracker tracker = mPointers.valueAt(index);
tracker.drawGestureTrail(canvas, mGesturePaint);
boolean needsUpdatingGesturePreviewTrail = false;
synchronized (mGesturePreviewTrails) {
// Trails count == fingers count that have ever been active.
final int trailsCount = mGesturePreviewTrails.size();
for (int index = 0; index < trailsCount; index++) {
final GesturePreviewTrail trail = mGesturePreviewTrails.valueAt(index);
needsUpdatingGesturePreviewTrail |=
trail.drawGestureTrail(canvas, mGesturePaint);
}
}
if (needsUpdatingGesturePreviewTrail) {
mDrawingHandler.postUpdateGestureTrailPreview();
}
}
if (mDrawsGestureFloatingPreviewText) {
drawGestureFloatingPreviewText(canvas, mGestureFloatingPreviewText);
@ -184,7 +222,7 @@ public class PreviewPlacerView extends RelativeLayout {
canvas.translate(-mXOrigin, -mYOrigin);
}
public void setGestureFloatingPreviewText(String gestureFloatingPreviewText) {
public void setGestureFloatingPreviewText(final String gestureFloatingPreviewText) {
mGestureFloatingPreviewText = gestureFloatingPreviewText;
invalidate();
}
@ -197,7 +235,8 @@ public class PreviewPlacerView extends RelativeLayout {
mDrawingHandler.cancelAllMessages();
}
private void drawGestureFloatingPreviewText(Canvas canvas, String gestureFloatingPreviewText) {
private void drawGestureFloatingPreviewText(final Canvas canvas,
final String gestureFloatingPreviewText) {
if (TextUtils.isEmpty(gestureFloatingPreviewText)) {
return;
}