am a1a669a1
: Merge "Add multiple gesture preview trails animation" into jb-mr1-dev
* commit 'a1a669a1212d630e9c04d9ddfc1588169359c790': Add multiple gesture preview trails animation
This commit is contained in:
commit
d6e390c765
8 changed files with 316 additions and 61 deletions
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
-->
|
||||
|
|
|
@ -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 -->
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue