Draw gesture trail that is above the keyboard

Bug: 7233992
Change-Id: Ia848543a9d008c68d6ecbc7f715aa6ccdba9d1c6
main
Tadashi G. Takaoka 2012-09-26 15:49:23 +09:00
parent 002a502c84
commit 157fe98fd4
3 changed files with 96 additions and 46 deletions

View File

@ -826,7 +826,8 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
}
final int[] viewOrigin = new int[2];
getLocationInWindow(viewOrigin);
mPreviewPlacerView.setOrigin(viewOrigin[0], viewOrigin[1]);
mPreviewPlacerView.setKeyboardViewGeometry(
viewOrigin[0], viewOrigin[1], getWidth(), getHeight());
final View rootView = getRootView();
if (rootView == null) {
Log.w(TAG, "Cannot find root view");

View File

@ -576,18 +576,20 @@ public class PointerTracker implements PointerTrackerQueue.Element {
mDrawingProxy.showGesturePreviewTrail(this, isOldestTracker);
}
private void updateBatchInput(final long eventTime) {
synchronized (sAggregratedPointers) {
mGestureStrokeWithPreviewPoints.appendIncrementalBatchPoints(sAggregratedPointers);
final int size = sAggregratedPointers.getPointerSize();
if (size > sLastRecognitionPointSize
&& GestureStroke.hasRecognitionTimePast(eventTime, sLastRecognitionTime)) {
sLastRecognitionPointSize = size;
sLastRecognitionTime = eventTime;
if (DEBUG_LISTENER) {
Log.d(TAG, "onUpdateBatchInput: batchPoints=" + size);
private void mayUpdateBatchInput(final long eventTime, final Key key) {
if (key != null) {
synchronized (sAggregratedPointers) {
mGestureStrokeWithPreviewPoints.appendIncrementalBatchPoints(sAggregratedPointers);
final int size = sAggregratedPointers.getPointerSize();
if (size > sLastRecognitionPointSize
&& GestureStroke.hasRecognitionTimePast(eventTime, sLastRecognitionTime)) {
sLastRecognitionPointSize = size;
sLastRecognitionTime = eventTime;
if (DEBUG_LISTENER) {
Log.d(TAG, "onUpdateBatchInput: batchPoints=" + size);
}
mListener.onUpdateBatchInput(sAggregratedPointers);
}
mListener.onUpdateBatchInput(sAggregratedPointers);
}
}
final boolean isOldestTracker = sPointerTrackerQueue.getOldestElement() == this;
@ -746,8 +748,8 @@ public class PointerTracker implements PointerTrackerQueue.Element {
if (mIsDetectingGesture) {
mGestureStrokeWithPreviewPoints.addPoint(x, y, gestureTime, isMajorEvent);
mayStartBatchInput(key);
if (sInGesture && key != null) {
updateBatchInput(eventTime);
if (sInGesture) {
mayUpdateBatchInput(eventTime, key);
}
}
}

View File

@ -40,6 +40,10 @@ import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.StaticInnerHandlerWrapper;
public class PreviewPlacerView extends RelativeLayout {
// The height of extra area above the keyboard to draw gesture trails.
// Proportional to the keyboard height.
private static final float EXTRA_GESTURE_TRAIL_AREA_ABOVE_KEYBOARD_RATIO = 0.25f;
private final int mGestureFloatingPreviewTextColor;
private final int mGestureFloatingPreviewTextOffset;
private final int mGestureFloatingPreviewColor;
@ -47,14 +51,17 @@ public class PreviewPlacerView extends RelativeLayout {
private final float mGestureFloatingPreviewVerticalPadding;
private final float mGestureFloatingPreviewRoundRadius;
private int mXOrigin;
private int mYOrigin;
private int mKeyboardViewOriginX;
private int mKeyboardViewOriginY;
private final SparseArray<GesturePreviewTrail> mGesturePreviewTrails =
CollectionUtils.newSparseArray();
private final Params mGesturePreviewTrailParams;
private final Paint mGesturePaint;
private boolean mDrawsGesturePreviewTrail;
private int mOffscreenWidth;
private int mOffscreenHeight;
private int mOffscreenOffsetY;
private Bitmap mOffscreenBuffer;
private final Canvas mOffscreenCanvas = new Canvas();
private final Rect mOffscreenDirtyRect = new Rect();
@ -165,9 +172,12 @@ public class PreviewPlacerView extends RelativeLayout {
setLayerType(LAYER_TYPE_HARDWARE, layerPaint);
}
public void setOrigin(final int x, final int y) {
mXOrigin = x;
mYOrigin = y;
public void setKeyboardViewGeometry(final int x, final int y, final int w, final int h) {
mKeyboardViewOriginX = x;
mKeyboardViewOriginY = y;
mOffscreenOffsetY = (int)(h * EXTRA_GESTURE_TRAIL_AREA_ABOVE_KEYBOARD_RATIO);
mOffscreenWidth = w;
mOffscreenHeight = mOffscreenOffsetY + h;
}
public void setGesturePreviewMode(final boolean drawsGesturePreviewTrail,
@ -204,45 +214,42 @@ public class PreviewPlacerView extends RelativeLayout {
@Override
protected void onDetachedFromWindow() {
freeOffscreenBuffer();
}
private void freeOffscreenBuffer() {
if (mOffscreenBuffer != null) {
mOffscreenBuffer.recycle();
mOffscreenBuffer = null;
}
}
private void mayAllocateOffscreenBuffer() {
if (mOffscreenBuffer != null && mOffscreenBuffer.getWidth() == mOffscreenWidth
&& mOffscreenBuffer.getHeight() == mOffscreenHeight) {
return;
}
freeOffscreenBuffer();
mOffscreenBuffer = Bitmap.createBitmap(
mOffscreenWidth, mOffscreenHeight, Bitmap.Config.ARGB_8888);
mOffscreenCanvas.setBitmap(mOffscreenBuffer);
}
@Override
public void onDraw(final Canvas canvas) {
super.onDraw(canvas);
canvas.translate(mXOrigin, mYOrigin);
if (mDrawsGesturePreviewTrail) {
if (mOffscreenBuffer == null) {
mOffscreenBuffer = Bitmap.createBitmap(
getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
mOffscreenCanvas.setBitmap(mOffscreenBuffer);
}
if (!mOffscreenDirtyRect.isEmpty()) {
// Clear previous dirty rectangle.
mGesturePaint.setColor(Color.TRANSPARENT);
mGesturePaint.setStyle(Paint.Style.FILL);
mOffscreenCanvas.drawRect(mOffscreenDirtyRect, mGesturePaint);
mOffscreenDirtyRect.setEmpty();
}
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(mOffscreenCanvas, mGesturePaint,
mGesturePreviewTrailBoundsRect, mGesturePreviewTrailParams);
// {@link #mGesturePreviewTrailBoundsRect} has bounding box of the trail.
mOffscreenDirtyRect.union(mGesturePreviewTrailBoundsRect);
}
}
mayAllocateOffscreenBuffer();
// Draw gesture trails to offscreen buffer.
final boolean needsUpdatingGesturePreviewTrail = drawGestureTrails(
mOffscreenCanvas, mGesturePaint, mOffscreenDirtyRect);
// Transfer offscreen buffer to screen.
if (!mOffscreenDirtyRect.isEmpty()) {
final int offsetY = mKeyboardViewOriginY - mOffscreenOffsetY;
canvas.translate(mKeyboardViewOriginX, offsetY);
canvas.drawBitmap(mOffscreenBuffer, mOffscreenDirtyRect, mOffscreenDirtyRect,
mGesturePaint);
canvas.translate(-mKeyboardViewOriginX, -offsetY);
// Note: Defer clearing the dirty rectangle here because we will get cleared
// rectangle on the canvas.
}
@ -251,9 +258,49 @@ public class PreviewPlacerView extends RelativeLayout {
}
}
if (mDrawsGestureFloatingPreviewText) {
canvas.translate(mKeyboardViewOriginX, mKeyboardViewOriginY);
drawGestureFloatingPreviewText(canvas, mGestureFloatingPreviewText);
canvas.translate(-mKeyboardViewOriginX, -mKeyboardViewOriginY);
}
canvas.translate(-mXOrigin, -mYOrigin);
}
private boolean drawGestureTrails(final Canvas offscreenCanvas, final Paint paint,
final Rect dirtyRect) {
// Clear previous dirty rectangle.
if (!dirtyRect.isEmpty()) {
paint.setColor(Color.TRANSPARENT);
paint.setStyle(Paint.Style.FILL);
offscreenCanvas.drawRect(dirtyRect, paint);
}
dirtyRect.setEmpty();
// Draw gesture trails to offscreen buffer.
offscreenCanvas.translate(0, mOffscreenOffsetY);
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(offscreenCanvas, paint,
mGesturePreviewTrailBoundsRect, mGesturePreviewTrailParams);
// {@link #mGesturePreviewTrailBoundsRect} has bounding box of the trail.
dirtyRect.union(mGesturePreviewTrailBoundsRect);
}
}
offscreenCanvas.translate(0, -mOffscreenOffsetY);
// Clip dirty rectangle with offscreen buffer width/height.
dirtyRect.offset(0, mOffscreenOffsetY);
clipRect(dirtyRect, 0, 0, mOffscreenWidth, mOffscreenHeight);
return needsUpdatingGesturePreviewTrail;
}
private static void clipRect(final Rect out, final int left, final int top, final int right,
final int bottom) {
out.set(Math.max(out.left, left), Math.max(out.top, top), Math.min(out.right, right),
Math.min(out.bottom, bottom));
}
public void setGestureFloatingPreviewText(final String gestureFloatingPreviewText) {