merge f41c640d84
w/minor conflict
This commit is contained in:
252
api/current.xml
252
api/current.xml
@ -3661,17 +3661,6 @@
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="donut_resource_pad39"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value="16843385"
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="donut_resource_pad4"
|
||||
type="int"
|
||||
transient="false"
|
||||
@ -3683,61 +3672,6 @@
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="donut_resource_pad40"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value="16843384"
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="donut_resource_pad41"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value="16843383"
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="donut_resource_pad42"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value="16843382"
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="donut_resource_pad43"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value="16843381"
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="donut_resource_pad44"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value="16843380"
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="donut_resource_pad5"
|
||||
type="int"
|
||||
transient="false"
|
||||
@ -4211,6 +4145,28 @@
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="fadeDuration"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value="16843384"
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="fadeOffset"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value="16843383"
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="fadingEdge"
|
||||
type="int"
|
||||
transient="false"
|
||||
@ -4530,6 +4486,39 @@
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="gestureColor"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value="16843381"
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="gestureStrokeWidth"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value="16843380"
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="gestures"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value="16843385"
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="gradientRadius"
|
||||
type="int"
|
||||
transient="false"
|
||||
@ -8930,6 +8919,17 @@
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="uncertainGestureColor"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value="16843382"
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="unselectedAlpha"
|
||||
type="int"
|
||||
transient="false"
|
||||
@ -49776,6 +49776,20 @@
|
||||
<parameter name="attrs" type="android.util.AttributeSet">
|
||||
</parameter>
|
||||
</constructor>
|
||||
<constructor name="GestureOverlayView"
|
||||
type="android.gesture.GestureOverlayView"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="context" type="android.content.Context">
|
||||
</parameter>
|
||||
<parameter name="attrs" type="android.util.AttributeSet">
|
||||
</parameter>
|
||||
<parameter name="defStyle" type="int">
|
||||
</parameter>
|
||||
</constructor>
|
||||
<method name="addOnGestureListener"
|
||||
return="void"
|
||||
abstract="false"
|
||||
@ -49857,6 +49871,19 @@
|
||||
visibility="public"
|
||||
>
|
||||
</method>
|
||||
<method name="processEvent"
|
||||
return="void"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="event" type="android.view.MotionEvent">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="removeOnGestureListener"
|
||||
return="void"
|
||||
abstract="false"
|
||||
@ -49922,27 +49949,6 @@
|
||||
<parameter name="color" type="int">
|
||||
</parameter>
|
||||
</method>
|
||||
<field name="DEFAULT_GESTURE_COLOR"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value="-256"
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="DEFAULT_UNCERTAIN_GESTURE_COLOR"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
</class>
|
||||
<interface name="GestureOverlayView.OnGestureListener"
|
||||
abstract="true"
|
||||
@ -162850,6 +162856,17 @@
|
||||
visibility="public"
|
||||
>
|
||||
</method>
|
||||
<method name="getGestures"
|
||||
return="int"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</method>
|
||||
<method name="getListPaddingBottom"
|
||||
return="int"
|
||||
abstract="false"
|
||||
@ -163223,6 +163240,19 @@
|
||||
<parameter name="filterText" type="java.lang.String">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="setGestures"
|
||||
return="void"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="gestures" type="int">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="setOnScrollListener"
|
||||
return="void"
|
||||
abstract="false"
|
||||
@ -163368,6 +163398,39 @@
|
||||
<parameter name="dr" type="android.graphics.drawable.Drawable">
|
||||
</parameter>
|
||||
</method>
|
||||
<field name="GESTURES_FILTER"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value="2"
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="GESTURES_JUMP"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value="1"
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="GESTURES_NONE"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value="0"
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="TRANSCRIPT_MODE_ALWAYS_SCROLL"
|
||||
type="int"
|
||||
transient="false"
|
||||
@ -172077,6 +172140,21 @@
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="width" type="int">
|
||||
</parameter>
|
||||
<parameter name="height" type="int">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="update"
|
||||
return="void"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="x" type="int">
|
||||
</parameter>
|
||||
<parameter name="y" type="int">
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2009 The Android Open Source Project
|
||||
* Copyright (C) 2009 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.
|
||||
@ -17,62 +17,54 @@
|
||||
package android.gesture;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BlurMaskFilter;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Color;
|
||||
import android.os.Handler;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.view.animation.AccelerateDecelerateInterpolator;
|
||||
import com.android.internal.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* A (transparent) overlay for gesture input that can be placed on top of other
|
||||
* widgets. The view can also be opaque.
|
||||
* widgets.
|
||||
*
|
||||
* @attr ref android.R.styleable#GestureOverlayView_gestureStrokeWidth
|
||||
* @attr ref android.R.styleable#GestureOverlayView_gestureColor
|
||||
* @attr ref android.R.styleable#GestureOverlayView_uncertainGestureColor
|
||||
* @attr ref android.R.styleable#GestureOverlayView_fadeDuration
|
||||
* @attr ref android.R.styleable#GestureOverlayView_fadeOffset
|
||||
*/
|
||||
|
||||
public class GestureOverlayView extends View {
|
||||
static final float TOUCH_TOLERANCE = 3;
|
||||
|
||||
// TODO: Move all these values into XML attributes
|
||||
private static final int TRANSPARENT_BACKGROUND = 0x00000000;
|
||||
|
||||
// TODO: SHOULD BE A TOTAL DURATION
|
||||
private static final float FADING_ALPHA_CHANGE = 0.15f;
|
||||
private static final long FADING_OFFSET = 300;
|
||||
private static final long FADING_REFRESHING_RATE = 16;
|
||||
|
||||
private static final int GESTURE_STROKE_WIDTH = 12;
|
||||
private static final boolean GESTURE_RENDERING_ANTIALIAS = true;
|
||||
|
||||
private static final boolean DITHER_FLAG = true;
|
||||
|
||||
public static final int DEFAULT_GESTURE_COLOR = 0xFFFFFF00;
|
||||
public static final int DEFAULT_UNCERTAIN_GESTURE_COLOR = Color.argb(60, 255, 255, 0);
|
||||
|
||||
private static final int REFRESH_RANGE = 10;
|
||||
|
||||
private static final BlurMaskFilter BLUR_MASK_FILTER =
|
||||
new BlurMaskFilter(1, BlurMaskFilter.Blur.NORMAL);
|
||||
|
||||
private Paint mGesturePaint;
|
||||
|
||||
private final Paint mBitmapPaint = new Paint(Paint.DITHER_FLAG);
|
||||
private Bitmap mBitmap; // with transparent background
|
||||
private Bitmap mBitmap;
|
||||
private Canvas mBitmapCanvas;
|
||||
|
||||
private int mCertainGestureColor = DEFAULT_GESTURE_COLOR;
|
||||
private int mUncertainGestureColor = DEFAULT_UNCERTAIN_GESTURE_COLOR;
|
||||
private long mFadeDuration = 300;
|
||||
private long mFadeOffset = 300;
|
||||
private long mFadingStart;
|
||||
|
||||
private float mGestureStroke = 12.0f;
|
||||
private int mCertainGestureColor = 0xFFFFFF00;
|
||||
private int mUncertainGestureColor = 0x3CFFFF00;
|
||||
private int mInvalidateExtraBorder = 10;
|
||||
|
||||
// for rendering immediate ink feedback
|
||||
private Rect mInvalidRect = new Rect();
|
||||
|
||||
private Path mPath;
|
||||
private final Rect mInvalidRect = new Rect();
|
||||
private final Path mPath = new Path();
|
||||
|
||||
private float mX;
|
||||
private float mY;
|
||||
@ -84,26 +76,32 @@ public class GestureOverlayView extends View {
|
||||
private Gesture mCurrentGesture = null;
|
||||
|
||||
// TODO: Make this a list of WeakReferences
|
||||
private final ArrayList<OnGestureListener> mOnGestureListeners = new ArrayList<OnGestureListener>();
|
||||
private ArrayList<GesturePoint> mPointBuffer = null;
|
||||
private final ArrayList<OnGestureListener> mOnGestureListeners =
|
||||
new ArrayList<OnGestureListener>();
|
||||
private final ArrayList<GesturePoint> mPointBuffer = new ArrayList<GesturePoint>(100);
|
||||
|
||||
// fading out effect
|
||||
private boolean mIsFadingOut = false;
|
||||
private float mFadingAlpha = 1;
|
||||
|
||||
private Handler mHandler = new Handler();
|
||||
private final AccelerateDecelerateInterpolator mInterpolator =
|
||||
new AccelerateDecelerateInterpolator();
|
||||
|
||||
private final Runnable mFadingOut = new Runnable() {
|
||||
public void run() {
|
||||
if (mIsFadingOut) {
|
||||
mFadingAlpha -= FADING_ALPHA_CHANGE;
|
||||
if (mFadingAlpha <= 0) {
|
||||
final long now = AnimationUtils.currentAnimationTimeMillis();
|
||||
final long duration = now - mFadingStart;
|
||||
|
||||
if (duration > mFadeDuration) {
|
||||
mIsFadingOut = false;
|
||||
mPath = null;
|
||||
mPath.rewind();
|
||||
mCurrentGesture = null;
|
||||
mBitmap.eraseColor(TRANSPARENT_BACKGROUND);
|
||||
} else {
|
||||
mHandler.postDelayed(this, FADING_REFRESHING_RATE);
|
||||
float interpolatedTime = Math.max(0.0f,
|
||||
Math.min(1.0f, duration / (float) mFadeDuration));
|
||||
mFadingAlpha = 1.0f - mInterpolator.getInterpolation(interpolatedTime);
|
||||
postDelayed(this, 16);
|
||||
}
|
||||
invalidate();
|
||||
}
|
||||
@ -116,7 +114,27 @@ public class GestureOverlayView extends View {
|
||||
}
|
||||
|
||||
public GestureOverlayView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
this(context, attrs, com.android.internal.R.attr.gestureOverlayViewStyle);
|
||||
}
|
||||
|
||||
public GestureOverlayView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
|
||||
TypedArray a = context.obtainStyledAttributes(attrs,
|
||||
R.styleable.GestureOverlayView, defStyle, 0);
|
||||
|
||||
mGestureStroke = a.getFloat(R.styleable.GestureOverlayView_gestureStrokeWidth,
|
||||
mGestureStroke);
|
||||
mInvalidateExtraBorder = Math.max(1, ((int) mGestureStroke) - 1);
|
||||
mCertainGestureColor = a.getColor(R.styleable.GestureOverlayView_gestureColor,
|
||||
mCertainGestureColor);
|
||||
mUncertainGestureColor = a.getColor(R.styleable.GestureOverlayView_uncertainGestureColor,
|
||||
mUncertainGestureColor);
|
||||
mFadeDuration = a.getInt(R.styleable.GestureOverlayView_fadeDuration, (int) mFadeDuration);
|
||||
mFadeOffset = a.getInt(R.styleable.GestureOverlayView_fadeOffset, (int) mFadeOffset);
|
||||
|
||||
a.recycle();
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
@ -139,6 +157,7 @@ public class GestureOverlayView extends View {
|
||||
mBitmap.eraseColor(TRANSPARENT_BACKGROUND);
|
||||
mCurrentGesture.draw(mBitmapCanvas, mGesturePaint);
|
||||
}
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void setGestureColor(int color) {
|
||||
@ -157,6 +176,16 @@ public class GestureOverlayView extends View {
|
||||
return mCertainGestureColor;
|
||||
}
|
||||
|
||||
public float getGestureStroke() {
|
||||
return mGestureStroke;
|
||||
}
|
||||
|
||||
public void setGestureStroke(float gestureStroke) {
|
||||
mGestureStroke = gestureStroke;
|
||||
mInvalidateExtraBorder = Math.max(1, ((int) mGestureStroke) - 1);
|
||||
mGesturePaint.setStrokeWidth(mGestureStroke);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the gesture to be shown in the view
|
||||
*
|
||||
@ -182,14 +211,12 @@ public class GestureOverlayView extends View {
|
||||
|
||||
final Paint gesturePaint = mGesturePaint;
|
||||
gesturePaint.setAntiAlias(GESTURE_RENDERING_ANTIALIAS);
|
||||
gesturePaint.setColor(DEFAULT_GESTURE_COLOR);
|
||||
gesturePaint.setColor(mCertainGestureColor);
|
||||
gesturePaint.setStyle(Paint.Style.STROKE);
|
||||
gesturePaint.setStrokeJoin(Paint.Join.ROUND);
|
||||
gesturePaint.setStrokeCap(Paint.Cap.ROUND);
|
||||
gesturePaint.setStrokeWidth(GESTURE_STROKE_WIDTH);
|
||||
gesturePaint.setStrokeWidth(mGestureStroke);
|
||||
gesturePaint.setDither(DITHER_FLAG);
|
||||
|
||||
mPath = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -226,6 +253,10 @@ public class GestureOverlayView extends View {
|
||||
mOnGestureListeners.remove(listener);
|
||||
}
|
||||
|
||||
public void removeAllOnGestureListeners() {
|
||||
mOnGestureListeners.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
@ -240,25 +271,24 @@ public class GestureOverlayView extends View {
|
||||
}
|
||||
|
||||
// draw the current stroke
|
||||
if (mPath != null) {
|
||||
canvas.drawPath(mPath, mGesturePaint);
|
||||
}
|
||||
canvas.drawPath(mPath, mGesturePaint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear up the overlay
|
||||
*
|
||||
* @param fadeOut whether the gesture on the overlay should fade out
|
||||
* gradually or disappear immediately
|
||||
* gradually or disappear immediately
|
||||
*/
|
||||
public void clear(boolean fadeOut) {
|
||||
if (fadeOut) {
|
||||
mFadingAlpha = 1;
|
||||
mFadingAlpha = 1.0f;
|
||||
mIsFadingOut = true;
|
||||
mHandler.removeCallbacks(mFadingOut);
|
||||
mHandler.postDelayed(mFadingOut, FADING_OFFSET);
|
||||
removeCallbacks(mFadingOut);
|
||||
mFadingStart = AnimationUtils.currentAnimationTimeMillis() + mFadeOffset;
|
||||
postDelayed(mFadingOut, mFadeOffset);
|
||||
} else {
|
||||
mPath = null;
|
||||
mPath.rewind();
|
||||
mCurrentGesture = null;
|
||||
if (mBitmap != null) {
|
||||
mBitmap.eraseColor(TRANSPARENT_BACKGROUND);
|
||||
@ -269,7 +299,7 @@ public class GestureOverlayView extends View {
|
||||
|
||||
public void cancelFadingOut() {
|
||||
mIsFadingOut = false;
|
||||
mHandler.removeCallbacks(mFadingOut);
|
||||
removeCallbacks(mFadingOut);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -278,6 +308,12 @@ public class GestureOverlayView extends View {
|
||||
return true;
|
||||
}
|
||||
|
||||
processEvent(event);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void processEvent(MotionEvent event) {
|
||||
switch (event.getAction()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
Rect rect = touchStart(event);
|
||||
@ -290,12 +326,14 @@ public class GestureOverlayView extends View {
|
||||
}
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
touchUp(event);
|
||||
touchUp(event, false);
|
||||
invalidate();
|
||||
break;
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
touchUp(event, true);
|
||||
invalidate();
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private Rect touchStart(MotionEvent event) {
|
||||
@ -310,7 +348,7 @@ public class GestureOverlayView extends View {
|
||||
// if there is fading out going on, stop it.
|
||||
if (mIsFadingOut) {
|
||||
mIsFadingOut = false;
|
||||
mHandler.removeCallbacks(mFadingOut);
|
||||
removeCallbacks(mFadingOut);
|
||||
mBitmap.eraseColor(TRANSPARENT_BACKGROUND);
|
||||
mCurrentGesture = null;
|
||||
}
|
||||
@ -325,14 +363,13 @@ public class GestureOverlayView extends View {
|
||||
mCurrentGesture = new Gesture();
|
||||
}
|
||||
|
||||
mPointBuffer = new ArrayList<GesturePoint>();
|
||||
mPointBuffer.add(new GesturePoint(x, y, event.getEventTime()));
|
||||
|
||||
mPath = new Path();
|
||||
mPath.rewind();
|
||||
mPath.moveTo(x, y);
|
||||
|
||||
mInvalidRect.set((int) x - REFRESH_RANGE, (int) y - REFRESH_RANGE,
|
||||
(int) x + REFRESH_RANGE, (int) y + REFRESH_RANGE);
|
||||
mInvalidRect.set((int) x - mInvalidateExtraBorder, (int) y - mInvalidateExtraBorder,
|
||||
(int) x + mInvalidateExtraBorder, (int) y + mInvalidateExtraBorder);
|
||||
|
||||
mCurveEndX = x;
|
||||
mCurveEndY = y;
|
||||
@ -343,36 +380,47 @@ public class GestureOverlayView extends View {
|
||||
private Rect touchMove(MotionEvent event) {
|
||||
Rect areaToRefresh = null;
|
||||
|
||||
float x = event.getX();
|
||||
float y = event.getY();
|
||||
final float x = event.getX();
|
||||
final float y = event.getY();
|
||||
|
||||
float dx = Math.abs(x - mX);
|
||||
float dy = Math.abs(y - mY);
|
||||
final float previousX = mX;
|
||||
final float previousY = mY;
|
||||
|
||||
final float dx = Math.abs(x - previousX);
|
||||
final float dy = Math.abs(y - previousY);
|
||||
|
||||
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
|
||||
|
||||
if (dx >= GestureStroke.TOUCH_TOLERANCE || dy >= GestureStroke.TOUCH_TOLERANCE) {
|
||||
areaToRefresh = mInvalidRect;
|
||||
|
||||
// start with the curve end
|
||||
mInvalidRect.set((int) mCurveEndX - REFRESH_RANGE, (int) mCurveEndY - REFRESH_RANGE,
|
||||
(int) mCurveEndX + REFRESH_RANGE, (int) mCurveEndY + REFRESH_RANGE);
|
||||
areaToRefresh.set(
|
||||
(int) mCurveEndX - mInvalidateExtraBorder,
|
||||
(int) mCurveEndY - mInvalidateExtraBorder,
|
||||
(int) mCurveEndX + mInvalidateExtraBorder,
|
||||
(int) mCurveEndY + mInvalidateExtraBorder);
|
||||
|
||||
mCurveEndX = (x + mX) / 2;
|
||||
mCurveEndY = (y + mY) / 2;
|
||||
mPath.quadTo(mX, mY, mCurveEndX, mCurveEndY);
|
||||
mCurveEndX = (x + previousX) / 2;
|
||||
mCurveEndY = (y + previousY) / 2;
|
||||
|
||||
mPath.quadTo(previousX, previousY, mCurveEndX, mCurveEndY);
|
||||
|
||||
// union with the control point of the new curve
|
||||
mInvalidRect.union((int) mX - REFRESH_RANGE, (int) mY - REFRESH_RANGE,
|
||||
(int) mX + REFRESH_RANGE, (int) mY + REFRESH_RANGE);
|
||||
areaToRefresh.union(
|
||||
(int) previousX - mInvalidateExtraBorder,
|
||||
(int) previousY - mInvalidateExtraBorder,
|
||||
(int) previousX + mInvalidateExtraBorder,
|
||||
(int) previousY + mInvalidateExtraBorder);
|
||||
|
||||
// union with the end point of the new curve
|
||||
mInvalidRect.union((int) mCurveEndX - REFRESH_RANGE, (int) mCurveEndY - REFRESH_RANGE,
|
||||
(int) mCurveEndX + REFRESH_RANGE, (int) mCurveEndY + REFRESH_RANGE);
|
||||
areaToRefresh.union(
|
||||
(int) mCurveEndX - mInvalidateExtraBorder,
|
||||
(int) mCurveEndY - mInvalidateExtraBorder,
|
||||
(int) mCurveEndX + mInvalidateExtraBorder,
|
||||
(int) mCurveEndY + mInvalidateExtraBorder);
|
||||
|
||||
areaToRefresh = mInvalidRect;
|
||||
|
||||
mX = x;
|
||||
mY = y;
|
||||
}
|
||||
|
||||
|
||||
mPointBuffer.add(new GesturePoint(x, y, event.getEventTime()));
|
||||
|
||||
@ -386,34 +434,43 @@ public class GestureOverlayView extends View {
|
||||
return areaToRefresh;
|
||||
}
|
||||
|
||||
private void touchUp(MotionEvent event) {
|
||||
private void touchUp(MotionEvent event, boolean cancel) {
|
||||
// add the stroke to the current gesture
|
||||
mCurrentGesture.addStroke(new GestureStroke(mPointBuffer));
|
||||
|
||||
// add the stroke to the double buffer
|
||||
mGesturePaint.setMaskFilter(BLUR_MASK_FILTER);
|
||||
mBitmapCanvas.drawPath(mPath, mGesturePaint);
|
||||
mGesturePaint.setMaskFilter(null);
|
||||
|
||||
// pass the event to handlers
|
||||
final ArrayList<OnGestureListener> listeners = mOnGestureListeners;
|
||||
final int count = listeners.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
listeners.get(i).onGestureEnded(this, event);
|
||||
|
||||
if (!cancel) {
|
||||
// pass the event to handlers
|
||||
final ArrayList<OnGestureListener> listeners = mOnGestureListeners;
|
||||
final int count = listeners.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
listeners.get(i).onGestureEnded(this, event);
|
||||
}
|
||||
} else {
|
||||
// pass the event to handlers
|
||||
final ArrayList<OnGestureListener> listeners = mOnGestureListeners;
|
||||
final int count = listeners.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
listeners.get(i).onGestureCancelled(this, event);
|
||||
}
|
||||
}
|
||||
|
||||
mPath = null;
|
||||
mPointBuffer = null;
|
||||
|
||||
mPath.rewind();
|
||||
mPointBuffer.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* An interface for processing gesture events
|
||||
*/
|
||||
public static interface OnGestureListener {
|
||||
public void onGestureStarted(GestureOverlayView overlay, MotionEvent event);
|
||||
void onGestureStarted(GestureOverlayView overlay, MotionEvent event);
|
||||
|
||||
public void onGesture(GestureOverlayView overlay, MotionEvent event);
|
||||
void onGesture(GestureOverlayView overlay, MotionEvent event);
|
||||
|
||||
public void onGestureEnded(GestureOverlayView overlay, MotionEvent event);
|
||||
void onGestureEnded(GestureOverlayView overlay, MotionEvent event);
|
||||
|
||||
void onGestureCancelled(GestureOverlayView overlay, MotionEvent event);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2009 The Android Open Source Project
|
||||
* Copyright (C) 2009 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.
|
||||
@ -31,6 +31,8 @@ import java.util.ArrayList;
|
||||
* A gesture stroke started on a touch down and ended on a touch up.
|
||||
*/
|
||||
public class GestureStroke {
|
||||
static final float TOUCH_TOLERANCE = 3;
|
||||
|
||||
public final RectF boundingBox;
|
||||
|
||||
public final float length;
|
||||
@ -156,8 +158,8 @@ public class GestureStroke {
|
||||
} else {
|
||||
float dx = Math.abs(x - mX);
|
||||
float dy = Math.abs(y - mY);
|
||||
if (dx >= GestureOverlayView.TOUCH_TOLERANCE ||
|
||||
dy >= GestureOverlayView.TOUCH_TOLERANCE) {
|
||||
if (dx >= TOUCH_TOLERANCE ||
|
||||
dy >= TOUCH_TOLERANCE) {
|
||||
path.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
|
||||
mX = x;
|
||||
mY = y;
|
||||
|
@ -45,32 +45,27 @@ public class LetterRecognizer {
|
||||
|
||||
private GestureLibrary mGestureLibrary;
|
||||
|
||||
private final Comparator<Prediction> mComparator = new PredictionComparator();
|
||||
|
||||
private static class SigmoidUnit {
|
||||
final float[] mWeights;
|
||||
|
||||
private boolean mComputed;
|
||||
private float mResult;
|
||||
|
||||
SigmoidUnit(float[] weights) {
|
||||
mWeights = weights;
|
||||
}
|
||||
|
||||
private float compute(float[] inputs) {
|
||||
if (!mComputed) {
|
||||
float sum = 0;
|
||||
float sum = 0;
|
||||
|
||||
final int count = inputs.length;
|
||||
final float[] weights = mWeights;
|
||||
final int count = inputs.length;
|
||||
final float[] weights = mWeights;
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
sum += inputs[i] * weights[i];
|
||||
}
|
||||
sum += weights[weights.length - 1];
|
||||
|
||||
mResult = 1.0f / (float) (1 + Math.exp(-sum));
|
||||
mComputed = true;
|
||||
for (int i = 0; i < count; i++) {
|
||||
sum += inputs[i] * weights[i];
|
||||
}
|
||||
return mResult;
|
||||
sum += weights[weights.length - 1];
|
||||
|
||||
return 1.0f / (float) (1 + Math.exp(-sum));
|
||||
}
|
||||
}
|
||||
|
||||
@ -91,16 +86,25 @@ public class LetterRecognizer {
|
||||
}
|
||||
|
||||
public ArrayList<Prediction> recognize(Gesture gesture) {
|
||||
return recognize(gesture, null);
|
||||
}
|
||||
|
||||
public ArrayList<Prediction> recognize(Gesture gesture, ArrayList<Prediction> predictions) {
|
||||
float[] query = GestureUtilities.spatialSampling(gesture, mPatchSize);
|
||||
ArrayList<Prediction> predictions = classify(query);
|
||||
predictions = classify(query, predictions);
|
||||
adjustPrediction(gesture, predictions);
|
||||
return predictions;
|
||||
}
|
||||
|
||||
private ArrayList<Prediction> classify(float[] vector) {
|
||||
private ArrayList<Prediction> classify(float[] vector, ArrayList<Prediction> predictions) {
|
||||
if (predictions == null) {
|
||||
predictions = new ArrayList<Prediction>();
|
||||
} else {
|
||||
predictions.clear();
|
||||
}
|
||||
|
||||
final float[] intermediateOutput = compute(mHiddenLayer, vector);
|
||||
final float[] output = compute(mOutputLayer, intermediateOutput);
|
||||
final ArrayList<Prediction> predictions = new ArrayList<Prediction>();
|
||||
|
||||
double sum = 0;
|
||||
|
||||
@ -117,19 +121,8 @@ public class LetterRecognizer {
|
||||
predictions.get(i).score /= sum;
|
||||
}
|
||||
|
||||
Collections.sort(predictions, new Comparator<Prediction>() {
|
||||
public int compare(Prediction object1, Prediction object2) {
|
||||
double score1 = object1.score;
|
||||
double score2 = object2.score;
|
||||
if (score1 > score2) {
|
||||
return -1;
|
||||
} else if (score1 < score2) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
});
|
||||
Collections.sort(predictions, mComparator);
|
||||
|
||||
return predictions;
|
||||
}
|
||||
|
||||
@ -270,4 +263,18 @@ public class LetterRecognizer {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class PredictionComparator implements Comparator<Prediction> {
|
||||
public int compare(Prediction object1, Prediction object2) {
|
||||
double score1 = object1.score;
|
||||
double score2 = object2.score;
|
||||
if (score1 > score2) {
|
||||
return -1;
|
||||
} else if (score1 < score2) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ public class TouchThroughGestureListener implements GestureOverlayView.OnGesture
|
||||
private boolean mStealEvents = false;
|
||||
|
||||
public TouchThroughGestureListener(View model) {
|
||||
this(model, false);
|
||||
this(model, true);
|
||||
}
|
||||
|
||||
public TouchThroughGestureListener(View model, boolean stealEvents) {
|
||||
@ -125,7 +125,7 @@ public class TouchThroughGestureListener implements GestureOverlayView.OnGesture
|
||||
overlay.setGestureDrawingColor(overlay.getGestureColor());
|
||||
if (mStealEvents) {
|
||||
event = MotionEvent.obtain(event.getDownTime(), System.currentTimeMillis(),
|
||||
MotionEvent.ACTION_UP, x, y, event.getPressure(), event.getSize(),
|
||||
MotionEvent.ACTION_CANCEL, x, y, event.getPressure(), event.getSize(),
|
||||
event.getMetaState(), event.getXPrecision(), event.getYPrecision(),
|
||||
event.getDeviceId(), event.getEdgeFlags());
|
||||
}
|
||||
@ -153,6 +153,13 @@ public class TouchThroughGestureListener implements GestureOverlayView.OnGesture
|
||||
}
|
||||
}
|
||||
|
||||
public void onGestureCancelled(GestureOverlayView overlay, MotionEvent event) {
|
||||
overlay.clear(mIsGesturing);
|
||||
if (!mIsGesturing) {
|
||||
dispatchEventToModel(event);
|
||||
}
|
||||
}
|
||||
|
||||
public void addOnGestureActionListener(OnGesturePerformedListener listener) {
|
||||
mPerformedListeners.add(listener);
|
||||
}
|
||||
|
@ -538,21 +538,48 @@ import java.util.WeakHashMap;
|
||||
* take care of redrawing the appropriate views until the animation completes.
|
||||
* </p>
|
||||
*
|
||||
* @attr ref android.R.styleable#View_background
|
||||
* @attr ref android.R.styleable#View_clickable
|
||||
* @attr ref android.R.styleable#View_contentDescription
|
||||
* @attr ref android.R.styleable#View_drawingCacheQuality
|
||||
* @attr ref android.R.styleable#View_duplicateParentState
|
||||
* @attr ref android.R.styleable#View_id
|
||||
* @attr ref android.R.styleable#View_fadingEdge
|
||||
* @attr ref android.R.styleable#View_fadingEdgeLength
|
||||
* @attr ref android.R.styleable#View_fitsSystemWindows
|
||||
* @attr ref android.R.styleable#View_isScrollContainer
|
||||
* @attr ref android.R.styleable#View_focusable
|
||||
* @attr ref android.R.styleable#View_focusableInTouchMode
|
||||
* @attr ref android.R.styleable#View_hapticFeedbackEnabled
|
||||
* @attr ref android.R.styleable#View_keepScreenOn
|
||||
* @attr ref android.R.styleable#View_longClickable
|
||||
* @attr ref android.R.styleable#View_minHeight
|
||||
* @attr ref android.R.styleable#View_minWidth
|
||||
* @attr ref android.R.styleable#View_nextFocusDown
|
||||
* @attr ref android.R.styleable#View_nextFocusLeft
|
||||
* @attr ref android.R.styleable#View_nextFocusRight
|
||||
* @attr ref android.R.styleable#View_nextFocusUp
|
||||
* @attr ref android.R.styleable#View_onClick
|
||||
* @attr ref android.R.styleable#View_padding
|
||||
* @attr ref android.R.styleable#View_paddingBottom
|
||||
* @attr ref android.R.styleable#View_paddingLeft
|
||||
* @attr ref android.R.styleable#View_paddingRight
|
||||
* @attr ref android.R.styleable#View_paddingTop
|
||||
* @attr ref android.R.styleable#View_saveEnabled
|
||||
* @attr ref android.R.styleable#View_scrollX
|
||||
* @attr ref android.R.styleable#View_scrollY
|
||||
* @attr ref android.R.styleable#View_scrollbarSize
|
||||
* @attr ref android.R.styleable#View_scrollbarStyle
|
||||
* @attr ref android.R.styleable#View_scrollbars
|
||||
* @attr ref android.R.styleable#View_scrollbarTrackHorizontal
|
||||
* @attr ref android.R.styleable#View_scrollbarThumbHorizontal
|
||||
* @attr ref android.R.styleable#View_scrollbarSize
|
||||
* @attr ref android.R.styleable#View_scrollbars
|
||||
* @attr ref android.R.styleable#View_scrollbarThumbVertical
|
||||
* @attr ref android.R.styleable#View_scrollbarTrackVertical
|
||||
* @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
|
||||
* @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
|
||||
* @attr ref android.R.styleable#View_soundEffectsEnabled
|
||||
* @attr ref android.R.styleable#View_tag
|
||||
* @attr ref android.R.styleable#View_visibility
|
||||
*
|
||||
* @see android.view.ViewGroup
|
||||
*/
|
||||
|
@ -53,6 +53,15 @@ import java.util.ArrayList;
|
||||
* <p>
|
||||
* Also see {@link LayoutParams} for layout attributes.
|
||||
* </p>
|
||||
*
|
||||
* @attr ref android.R.styleable#ViewGroup_clipChildren
|
||||
* @attr ref android.R.styleable#ViewGroup_clipToPadding
|
||||
* @attr ref android.R.styleable#ViewGroup_layoutAnimation
|
||||
* @attr ref android.R.styleable#ViewGroup_animationCache
|
||||
* @attr ref android.R.styleable#ViewGroup_persistentDrawingCache
|
||||
* @attr ref android.R.styleable#ViewGroup_alwaysDrawnWithCache
|
||||
* @attr ref android.R.styleable#ViewGroup_addStatesFromChildren
|
||||
* @attr ref android.R.styleable#ViewGroup_descendantFocusability
|
||||
*/
|
||||
public abstract class ViewGroup extends View implements ViewParent, ViewManager {
|
||||
private static final boolean DBG = false;
|
||||
|
@ -41,12 +41,18 @@ import android.view.ViewConfiguration;
|
||||
import android.view.ViewDebug;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.view.KeyCharacterMap;
|
||||
import android.view.inputmethod.BaseInputConnection;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputConnection;
|
||||
import android.view.inputmethod.InputConnectionWrapper;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.view.ContextMenu.ContextMenuInfo;
|
||||
import android.gesture.GestureOverlayView;
|
||||
import android.gesture.TouchThroughGestureListener;
|
||||
import android.gesture.Gesture;
|
||||
import android.gesture.LetterRecognizer;
|
||||
import android.gesture.Prediction;
|
||||
|
||||
import com.android.internal.R;
|
||||
|
||||
@ -54,7 +60,9 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Common code shared between ListView and GridView
|
||||
* Base class that can be used to implement virtualized lists of items. A list does
|
||||
* not have a spatial definition here. For instance, subclases of this class can
|
||||
* display the content of the list in a grid, in a carousel, as stack, etc.
|
||||
*
|
||||
* @attr ref android.R.styleable#AbsListView_listSelector
|
||||
* @attr ref android.R.styleable#AbsListView_drawSelectorOnTop
|
||||
@ -65,6 +73,7 @@ import java.util.List;
|
||||
* @attr ref android.R.styleable#AbsListView_cacheColorHint
|
||||
* @attr ref android.R.styleable#AbsListView_fastScrollEnabled
|
||||
* @attr ref android.R.styleable#AbsListView_smoothScrollbar
|
||||
* @attr ref android.R.styleable#AbsListView_gestures
|
||||
*/
|
||||
public abstract class AbsListView extends AdapterView<ListAdapter> implements TextWatcher,
|
||||
ViewTreeObserver.OnGlobalLayoutListener, Filter.FilterListener,
|
||||
@ -92,6 +101,31 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
||||
*/
|
||||
public static final int TRANSCRIPT_MODE_ALWAYS_SCROLL = 2;
|
||||
|
||||
/**
|
||||
* Disables gestures.
|
||||
*
|
||||
* @see #setGestures(int)
|
||||
* @see #GESTURES_JUMP
|
||||
* @see #GESTURES_FILTER
|
||||
*/
|
||||
public static final int GESTURES_NONE = 0;
|
||||
/**
|
||||
* When a letter gesture is recognized the list jumps to a matching position.
|
||||
*
|
||||
* @see #setGestures(int)
|
||||
* @see #GESTURES_NONE
|
||||
* @see #GESTURES_FILTER
|
||||
*/
|
||||
public static final int GESTURES_JUMP = 1;
|
||||
/**
|
||||
* When a letter gesture is recognized the letter is added to the filter.
|
||||
*
|
||||
* @see #setGestures(int)
|
||||
* @see #GESTURES_NONE
|
||||
* @see #GESTURES_JUMP
|
||||
*/
|
||||
public static final int GESTURES_FILTER = 2;
|
||||
|
||||
/**
|
||||
* Indicates that we are not in the middle of a touch gesture
|
||||
*/
|
||||
@ -427,8 +461,23 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
||||
*/
|
||||
private FastScroller mFastScroller;
|
||||
|
||||
private int mTouchSlop;
|
||||
/**
|
||||
* Indicates the type of gestures to use: GESTURES_NONE, GESTURES_FILTER or GESTURES_NONE
|
||||
*/
|
||||
private int mGestures;
|
||||
|
||||
// Used to implement the gestures overlay
|
||||
private GestureOverlayView mGesturesOverlay;
|
||||
private PopupWindow mGesturesPopup;
|
||||
private ViewTreeObserver.OnGlobalLayoutListener mGesturesLayoutListener;
|
||||
private boolean mGlobalLayoutListenerAddedGestures;
|
||||
private boolean mInstallGesturesOverlay;
|
||||
private TouchThroughGestureListener mGesturesListener;
|
||||
private boolean mPreviousGesturing;
|
||||
|
||||
private boolean mGlobalLayoutListenerAddedFilter;
|
||||
|
||||
private int mTouchSlop;
|
||||
private float mDensityScale;
|
||||
|
||||
private InputConnection mDefInputConnection;
|
||||
@ -535,10 +584,197 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
||||
|
||||
boolean smoothScrollbar = a.getBoolean(R.styleable.AbsListView_smoothScrollbar, true);
|
||||
setSmoothScrollbarEnabled(smoothScrollbar);
|
||||
|
||||
|
||||
int defaultGestures = GESTURES_NONE;
|
||||
if (useTextFilter) {
|
||||
defaultGestures = GESTURES_FILTER;
|
||||
} else if (enableFastScroll) {
|
||||
defaultGestures = GESTURES_JUMP;
|
||||
}
|
||||
int gestures = a.getInt(R.styleable.AbsListView_gestures, defaultGestures);
|
||||
setGestures(gestures);
|
||||
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
private void initAbsListView() {
|
||||
// Setting focusable in touch mode will set the focusable property to true
|
||||
setFocusableInTouchMode(true);
|
||||
setWillNotDraw(false);
|
||||
setAlwaysDrawnWithCacheEnabled(false);
|
||||
setScrollingCacheEnabled(true);
|
||||
|
||||
mTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
|
||||
mDensityScale = getContext().getResources().getDisplayMetrics().density;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Sets the type of gestures to use with this list. When gestures are enabled,
|
||||
* that is if the <code>gestures</code> parameter is not {@link #GESTURES_NONE},
|
||||
* the user can draw characters on top of this view. When a character is
|
||||
* recognized and matches a known character, the list will either:</p>
|
||||
* <ul>
|
||||
* <li>Jump to the appropriate position ({@link #GESTURES_JUMP})</li>
|
||||
* <li>Add the character to the current filter ({@link #GESTURES_FILTER})</li>
|
||||
* </ul>
|
||||
* <p>Using {@link #GESTURES_JUMP} requires {@link #isFastScrollEnabled()} to
|
||||
* be true. Using {@link #GESTURES_FILTER} requires {@link #isTextFilterEnabled()}
|
||||
* to be true.</p>
|
||||
*
|
||||
* @param gestures The type of gestures to enable for this list:
|
||||
* {@link #GESTURES_NONE}, {@link #GESTURES_JUMP} or {@link #GESTURES_FILTER}
|
||||
*
|
||||
* @see #GESTURES_NONE
|
||||
* @see #GESTURES_JUMP
|
||||
* @see #GESTURES_FILTER
|
||||
* @see #getGestures()
|
||||
*/
|
||||
public void setGestures(int gestures) {
|
||||
switch (gestures) {
|
||||
case GESTURES_JUMP:
|
||||
if (!mFastScrollEnabled) {
|
||||
throw new IllegalStateException("Jump gestures can only be used with "
|
||||
+ "fast scroll enabled");
|
||||
}
|
||||
break;
|
||||
case GESTURES_FILTER:
|
||||
if (!mTextFilterEnabled) {
|
||||
throw new IllegalStateException("Filter gestures can only be used with "
|
||||
+ "text filtering enabled");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
final int oldGestures = mGestures;
|
||||
mGestures = gestures;
|
||||
|
||||
// Install overlay later
|
||||
if (oldGestures == GESTURES_NONE && gestures != GESTURES_NONE) {
|
||||
mInstallGesturesOverlay = true;
|
||||
// Uninstall overlay
|
||||
} else if (oldGestures != GESTURES_NONE && gestures == GESTURES_NONE) {
|
||||
uninstallGesturesOverlay();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates what gestures are enabled on this view.
|
||||
*
|
||||
* @return {@link #GESTURES_NONE}, {@link #GESTURES_JUMP} or {@link #GESTURES_FILTER}
|
||||
*
|
||||
* @see #GESTURES_NONE
|
||||
* @see #GESTURES_JUMP
|
||||
* @see #GESTURES_FILTER
|
||||
* @see #setGestures(int)
|
||||
*/
|
||||
@ViewDebug.ExportedProperty(mapping = {
|
||||
@ViewDebug.IntToString(from = GESTURES_NONE, to = "NONE"),
|
||||
@ViewDebug.IntToString(from = GESTURES_JUMP, to = "JUMP"),
|
||||
@ViewDebug.IntToString(from = GESTURES_FILTER, to = "FILTER")
|
||||
})
|
||||
public int getGestures() {
|
||||
return mGestures;
|
||||
}
|
||||
|
||||
private void dismissGesturesPopup() {
|
||||
if (mGesturesPopup != null) {
|
||||
mGesturesPopup.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
private void showGesturesPopup() {
|
||||
// Make sure we have a window before showing the popup
|
||||
if (getWindowVisibility() == View.VISIBLE) {
|
||||
installGesturesOverlay();
|
||||
positionGesturesPopup();
|
||||
}
|
||||
}
|
||||
|
||||
private void positionGesturesPopup() {
|
||||
final int[] xy = new int[2];
|
||||
getLocationOnScreen(xy);
|
||||
if (!mGesturesPopup.isShowing()) {
|
||||
mGesturesPopup.showAtLocation(this, Gravity.LEFT | Gravity.TOP, xy[0], xy[1]);
|
||||
} else {
|
||||
mGesturesPopup.update(xy[0], xy[1], -1, -1);
|
||||
}
|
||||
}
|
||||
|
||||
private void installGesturesOverlay() {
|
||||
mInstallGesturesOverlay = false;
|
||||
|
||||
if (mGesturesPopup == null) {
|
||||
final Context c = getContext();
|
||||
final LayoutInflater layoutInflater = (LayoutInflater)
|
||||
c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
mGesturesOverlay = (GestureOverlayView)
|
||||
layoutInflater.inflate(R.layout.list_gestures_overlay, null);
|
||||
|
||||
final PopupWindow p = new PopupWindow(c);
|
||||
p.setFocusable(false);
|
||||
p.setTouchable(false);
|
||||
p.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
|
||||
p.setContentView(mGesturesOverlay);
|
||||
p.setWidth(getWidth());
|
||||
p.setHeight(getHeight());
|
||||
p.setBackgroundDrawable(null);
|
||||
|
||||
if (mGesturesLayoutListener == null) {
|
||||
mGesturesLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||
public void onGlobalLayout() {
|
||||
if (isShown()) {
|
||||
showGesturesPopup();
|
||||
} else if (mGesturesPopup.isShowing()) {
|
||||
dismissGesturesPopup();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
getViewTreeObserver().addOnGlobalLayoutListener(mGesturesLayoutListener);
|
||||
mGlobalLayoutListenerAddedGestures = true;
|
||||
|
||||
mGesturesPopup = p;
|
||||
|
||||
mGesturesOverlay.removeAllOnGestureListeners();
|
||||
mGesturesListener = new TouchThroughGestureListener(null);
|
||||
mGesturesListener.setGestureType(TouchThroughGestureListener.MULTIPLE_STROKE);
|
||||
mGesturesListener.addOnGestureActionListener(new GesturesProcessor());
|
||||
mGesturesOverlay.addOnGestureListener(mGesturesListener);
|
||||
|
||||
mPreviousGesturing = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void uninstallGesturesOverlay() {
|
||||
dismissGesturesPopup();
|
||||
mGesturesPopup = null;
|
||||
if (mGesturesLayoutListener != null) {
|
||||
getViewTreeObserver().removeGlobalOnLayoutListener(mGesturesLayoutListener);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchTouchEvent(MotionEvent ev) {
|
||||
if (mGestures != GESTURES_NONE) {
|
||||
mGesturesOverlay.processEvent(ev);
|
||||
|
||||
final boolean isGesturing = mGesturesListener.isGesturing();
|
||||
|
||||
if (!isGesturing) {
|
||||
mPreviousGesturing = isGesturing;
|
||||
return super.dispatchTouchEvent(ev);
|
||||
} else if (!mPreviousGesturing){
|
||||
mPreviousGesturing = isGesturing;
|
||||
final MotionEvent event = MotionEvent.obtain(ev);
|
||||
event.setAction(MotionEvent.ACTION_CANCEL);
|
||||
super.dispatchTouchEvent(event);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return super.dispatchTouchEvent(ev);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables fast scrolling by letting the user quickly scroll through lists by
|
||||
* dragging the fast scroll thumb. The adapter attached to the list may want
|
||||
@ -712,17 +948,6 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
||||
}
|
||||
}
|
||||
|
||||
private void initAbsListView() {
|
||||
// Setting focusable in touch mode will set the focusable property to true
|
||||
setFocusableInTouchMode(true);
|
||||
setWillNotDraw(false);
|
||||
setAlwaysDrawnWithCacheEnabled(false);
|
||||
setScrollingCacheEnabled(true);
|
||||
|
||||
mTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
|
||||
mDensityScale = getContext().getResources().getDisplayMetrics().density;
|
||||
}
|
||||
|
||||
private void useDefaultSelector() {
|
||||
setSelector(getResources().getDrawable(
|
||||
com.android.internal.R.drawable.list_selector_background));
|
||||
@ -908,11 +1133,8 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
||||
}
|
||||
|
||||
private boolean acceptFilter() {
|
||||
if (!mTextFilterEnabled || !(getAdapter() instanceof Filterable) ||
|
||||
((Filterable) getAdapter()).getFilter() == null) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return mTextFilterEnabled && getAdapter() instanceof Filterable &&
|
||||
((Filterable) getAdapter()).getFilter() != null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1096,6 +1318,10 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
||||
listPadding.bottom = mSelectionBottomPadding + mPaddingBottom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses should NOT override this method but
|
||||
* {@link #layoutChildren()} instead.
|
||||
*/
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
||||
super.onLayout(changed, l, t, r, b);
|
||||
@ -1111,17 +1337,27 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
||||
protected boolean setFrame(int left, int top, int right, int bottom) {
|
||||
final boolean changed = super.setFrame(left, top, right, bottom);
|
||||
|
||||
// Reposition the popup when the frame has changed. This includes
|
||||
// translating the widget, not just changing its dimension. The
|
||||
// filter popup needs to follow the widget.
|
||||
if (mFiltered && changed && getWindowVisibility() == View.VISIBLE && mPopup != null &&
|
||||
mPopup.isShowing()) {
|
||||
positionPopup();
|
||||
if (changed) {
|
||||
// Reposition the popup when the frame has changed. This includes
|
||||
// translating the widget, not just changing its dimension. The
|
||||
// filter popup needs to follow the widget.
|
||||
final boolean visible = getWindowVisibility() == View.VISIBLE;
|
||||
if (mFiltered && visible && mPopup != null && mPopup.isShowing()) {
|
||||
positionPopup();
|
||||
}
|
||||
|
||||
if (mGestures != GESTURES_NONE && visible && mGesturesPopup != null &&
|
||||
mGesturesPopup.isShowing()) {
|
||||
positionGesturesPopup();
|
||||
}
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses must override this method to layout their children.
|
||||
*/
|
||||
protected void layoutChildren() {
|
||||
}
|
||||
|
||||
@ -1324,9 +1560,17 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
||||
mDataChanged = true;
|
||||
rememberSyncState();
|
||||
}
|
||||
|
||||
if (mFastScroller != null) {
|
||||
mFastScroller.onSizeChanged(w, h, oldw, oldh);
|
||||
}
|
||||
|
||||
if (mInstallGesturesOverlay) {
|
||||
installGesturesOverlay();
|
||||
positionGesturesPopup();
|
||||
} else if (mGesturesPopup != null) {
|
||||
mGesturesPopup.update(w, h);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1510,6 +1754,13 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
||||
final ViewTreeObserver treeObserver = getViewTreeObserver();
|
||||
if (treeObserver != null) {
|
||||
treeObserver.addOnTouchModeChangeListener(this);
|
||||
if (mTextFilterEnabled && mPopup != null && !mGlobalLayoutListenerAddedFilter) {
|
||||
treeObserver.addOnGlobalLayoutListener(this);
|
||||
}
|
||||
if (mGestures != GESTURES_NONE && mGesturesPopup != null &&
|
||||
!mGlobalLayoutListenerAddedGestures) {
|
||||
treeObserver.addOnGlobalLayoutListener(mGesturesLayoutListener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1520,6 +1771,14 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
||||
final ViewTreeObserver treeObserver = getViewTreeObserver();
|
||||
if (treeObserver != null) {
|
||||
treeObserver.removeOnTouchModeChangeListener(this);
|
||||
if (mTextFilterEnabled && mPopup != null) {
|
||||
treeObserver.removeGlobalOnLayoutListener(this);
|
||||
mGlobalLayoutListenerAddedFilter = false;
|
||||
}
|
||||
if (mGesturesLayoutListener != null && mGesturesPopup != null) {
|
||||
mGlobalLayoutListenerAddedGestures = false;
|
||||
treeObserver.removeGlobalOnLayoutListener(mGesturesLayoutListener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1534,6 +1793,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
||||
removeCallbacks(mFlingRunnable);
|
||||
// Always hide the type filter
|
||||
dismissPopup();
|
||||
dismissGesturesPopup();
|
||||
|
||||
if (touchMode == TOUCH_MODE_OFF) {
|
||||
// Remember the last selected element
|
||||
@ -1544,6 +1804,9 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
||||
// Show the type filter only if a filter is in effect
|
||||
showPopup();
|
||||
}
|
||||
if (mGestures != GESTURES_NONE) {
|
||||
showGesturesPopup();
|
||||
}
|
||||
|
||||
// If we changed touch mode since the last time we had focus
|
||||
if (touchMode != mLastTouchMode && mLastTouchMode != TOUCH_MODE_UNKNOWN) {
|
||||
@ -2775,7 +3038,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
||||
/**
|
||||
* Removes the filter window
|
||||
*/
|
||||
void dismissPopup() {
|
||||
private void dismissPopup() {
|
||||
if (mPopup != null) {
|
||||
mPopup.dismiss();
|
||||
}
|
||||
@ -3017,6 +3280,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
||||
p.setBackgroundDrawable(null);
|
||||
mPopup = p;
|
||||
getViewTreeObserver().addOnGlobalLayoutListener(this);
|
||||
mGlobalLayoutListenerAddedFilter = true;
|
||||
}
|
||||
if (animateEntrance) {
|
||||
mPopup.setAnimationStyle(com.android.internal.R.style.Animation_TypingFilter);
|
||||
@ -3583,4 +3847,77 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class GesturesProcessor implements
|
||||
TouchThroughGestureListener.OnGesturePerformedListener {
|
||||
|
||||
private static final double SCORE_THRESHOLD = 0.1;
|
||||
|
||||
private LetterRecognizer mRecognizer;
|
||||
private ArrayList<Prediction> mPredictions;
|
||||
private final KeyCharacterMap mKeyMap;
|
||||
private final char[] mHolder;
|
||||
|
||||
GesturesProcessor() {
|
||||
mRecognizer = LetterRecognizer.getLetterRecognizer(getContext(),
|
||||
LetterRecognizer.RECOGNIZER_LATIN_LOWERCASE);
|
||||
if (mGestures == GESTURES_FILTER) {
|
||||
mKeyMap = KeyCharacterMap.load(KeyCharacterMap.BUILT_IN_KEYBOARD);
|
||||
mHolder = new char[1];
|
||||
} else {
|
||||
mKeyMap = null;
|
||||
mHolder = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
|
||||
mPredictions = mRecognizer.recognize(gesture, mPredictions);
|
||||
if (!mPredictions.isEmpty()) {
|
||||
final Prediction prediction = mPredictions.get(0);
|
||||
if (prediction.score > SCORE_THRESHOLD) {
|
||||
switch (mGestures) {
|
||||
case GESTURES_JUMP:
|
||||
processJump(prediction);
|
||||
break;
|
||||
case GESTURES_FILTER:
|
||||
processFilter(prediction);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processJump(Prediction prediction) {
|
||||
final Object[] sections = mFastScroller.getSections();
|
||||
if (sections != null) {
|
||||
final String name = prediction.name;
|
||||
final int count = sections.length;
|
||||
|
||||
int index = -1;
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (name.equalsIgnoreCase((String) sections[i])) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (index != -1) {
|
||||
final SectionIndexer indexer = mFastScroller.getSectionIndexer();
|
||||
final int position = indexer.getPositionForSection(index);
|
||||
setSelection(position);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processFilter(Prediction prediction) {
|
||||
mHolder[0] = prediction.name.charAt(0);
|
||||
final KeyEvent[] events = mKeyMap.getEvents(mHolder);
|
||||
if (events != null) {
|
||||
for (KeyEvent event : events) {
|
||||
sendToTextFilter(event.getKeyCode(), event.getRepeatCount(),
|
||||
event);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -134,7 +134,7 @@ class FastScroller {
|
||||
|
||||
mScrollCompleted = true;
|
||||
|
||||
getSections();
|
||||
getSectionsFromIndexer();
|
||||
|
||||
mOverlayPos = new RectF();
|
||||
mScrollFade = new ScrollFade();
|
||||
@ -250,7 +250,18 @@ class FastScroller {
|
||||
}
|
||||
}
|
||||
|
||||
private void getSections() {
|
||||
SectionIndexer getSectionIndexer() {
|
||||
return mSectionIndexer;
|
||||
}
|
||||
|
||||
Object[] getSections() {
|
||||
if (mListAdapter == null && mList != null) {
|
||||
getSectionsFromIndexer();
|
||||
}
|
||||
return mSections;
|
||||
}
|
||||
|
||||
private void getSectionsFromIndexer() {
|
||||
Adapter adapter = mList.getAdapter();
|
||||
mSectionIndexer = null;
|
||||
if (adapter instanceof HeaderViewListAdapter) {
|
||||
@ -411,7 +422,7 @@ class FastScroller {
|
||||
|
||||
setState(STATE_DRAGGING);
|
||||
if (mListAdapter == null && mList != null) {
|
||||
getSections();
|
||||
getSectionsFromIndexer();
|
||||
}
|
||||
|
||||
cancelFling();
|
||||
@ -448,7 +459,7 @@ class FastScroller {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public class ScrollFade implements Runnable {
|
||||
|
||||
long mStartTime;
|
||||
|
@ -1072,6 +1072,20 @@ public class PopupWindow {
|
||||
mWindowManager.updateViewLayout(mPopupView, p);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Updates the dimension of the popup window. Calling this function
|
||||
* also updates the window with the current popup state as described
|
||||
* for {@link #update()}.</p>
|
||||
*
|
||||
* @param width the new width
|
||||
* @param height the new height
|
||||
*/
|
||||
public void update(int width, int height) {
|
||||
WindowManager.LayoutParams p = (WindowManager.LayoutParams)
|
||||
mPopupView.getLayoutParams();
|
||||
update(p.x, p.y, width, height, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Updates the position and the dimension of the popup window. Width and
|
||||
|
@ -127,6 +127,8 @@ import java.util.ArrayList;
|
||||
* @attr ref android.R.styleable#TextView_textColor
|
||||
* @attr ref android.R.styleable#TextView_textColorHighlight
|
||||
* @attr ref android.R.styleable#TextView_textColorHint
|
||||
* @attr ref android.R.styleable#TextView_textAppearance
|
||||
* @attr ref android.R.styleable#TextView_textColorLink
|
||||
* @attr ref android.R.styleable#TextView_textSize
|
||||
* @attr ref android.R.styleable#TextView_textScaleX
|
||||
* @attr ref android.R.styleable#TextView_typeface
|
||||
@ -164,13 +166,22 @@ import java.util.ArrayList;
|
||||
* @attr ref android.R.styleable#TextView_capitalize
|
||||
* @attr ref android.R.styleable#TextView_autoText
|
||||
* @attr ref android.R.styleable#TextView_editable
|
||||
* @attr ref android.R.styleable#TextView_freezesText
|
||||
* @attr ref android.R.styleable#TextView_ellipsize
|
||||
* @attr ref android.R.styleable#TextView_drawableTop
|
||||
* @attr ref android.R.styleable#TextView_drawableBottom
|
||||
* @attr ref android.R.styleable#TextView_drawableRight
|
||||
* @attr ref android.R.styleable#TextView_drawableLeft
|
||||
* @attr ref android.R.styleable#TextView_drawablePadding
|
||||
* @attr ref android.R.styleable#TextView_lineSpacingExtra
|
||||
* @attr ref android.R.styleable#TextView_lineSpacingMultiplier
|
||||
* @attr ref android.R.styleable#TextView_marqueeRepeatLimit
|
||||
* @attr ref android.R.styleable#TextView_inputType
|
||||
* @attr ref android.R.styleable#TextView_imeOptions
|
||||
* @attr ref android.R.styleable#TextView_privateImeOptions
|
||||
* @attr ref android.R.styleable#TextView_imeActionLabel
|
||||
* @attr ref android.R.styleable#TextView_imeActionId
|
||||
* @attr ref android.R.styleable#TextView_editorExtras
|
||||
*/
|
||||
@RemoteView
|
||||
public class TextView extends View implements ViewTreeObserver.OnPreDrawListener {
|
||||
|
19
core/res/res/layout/list_gestures_overlay.xml
Normal file
19
core/res/res/layout/list_gestures_overlay.xml
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2009 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.
|
||||
-->
|
||||
|
||||
<android.gesture.GestureOverlayView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent" />
|
Binary file not shown.
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
@ -324,6 +324,8 @@
|
||||
<attr name="expandableListViewStyle" format="reference" />
|
||||
<!-- Default Gallery style. -->
|
||||
<attr name="galleryStyle" format="reference" />
|
||||
<!-- Default GestureOverlayView style. -->
|
||||
<attr name="gestureOverlayViewStyle" format="reference" />
|
||||
<!-- Default GridView style. -->
|
||||
<attr name="gridViewStyle" format="reference" />
|
||||
<!-- The style resource to use for an ImageButton -->
|
||||
@ -1379,6 +1381,19 @@
|
||||
will use only the number of items in the adapter and the number of items visible
|
||||
on screen to determine the scrollbar's properties. -->
|
||||
<attr name="smoothScrollbar" format="boolean" />
|
||||
<!-- Defines the type of gesture to enable for the widget. -->
|
||||
<attr name="gestures">
|
||||
<!-- No gesture -->
|
||||
<enum name="none" value="0" />
|
||||
<!-- Gestures jump to a specific position in the content. This requires
|
||||
fast scroll to be enabled. If fast scroll is enabled from XML,
|
||||
jump gestures will be enabled automatically. -->
|
||||
<enum name="jump" value="1" />
|
||||
<!-- Gestures filter the content. This requires text filtering to be enabled.
|
||||
If text filtering is enabled from XML, filter gestures will be enabled
|
||||
automatically. -->
|
||||
<enum name="filter" value="2" />
|
||||
</attr>
|
||||
</declare-styleable>
|
||||
<declare-styleable name="AbsSpinner">
|
||||
<!-- Reference to an array resource that will populate the Spinner. For static content,
|
||||
@ -1581,7 +1596,7 @@
|
||||
<!-- Height of the divider. Will use the intrinsic height of the divider if this
|
||||
is not specified. -->
|
||||
<attr name="dividerHeight" format="dimension" />
|
||||
<!-- Defines the choice behavior for the List. By default, Lists do not have
|
||||
<!-- Defines the choice behavior for the ListView. By default, lists do not have
|
||||
any choice behavior. By setting the choiceMode to singleChoice, the List
|
||||
allows up to one item to be in a chosen state. By setting the choiceMode to
|
||||
multipleChoice, the list allows any number of items to be chosen. -->
|
||||
@ -2061,6 +2076,23 @@
|
||||
<attr name="animateOnClick" format="boolean" />
|
||||
</declare-styleable>
|
||||
|
||||
<!-- GestureOverlayView specific attributes. These attributes are used to configure
|
||||
a GestureOverlayView from XML. -->
|
||||
<declare-styleable name="GestureOverlayView">
|
||||
<!-- Width of the stroke used to draw the gesture. -->
|
||||
<attr name="gestureStrokeWidth" format="float" />
|
||||
<!-- Color used to draw a gesture. -->
|
||||
<attr name="gestureColor" format="color" />
|
||||
<!-- Color used to draw the user's strokes until we are sure it's a gesture. -->
|
||||
<attr name="uncertainGestureColor" format="color" />
|
||||
<!-- Time, in milliseconds, to wait before the gesture fades out after the user
|
||||
is done drawing it. -->
|
||||
<attr name="fadeOffset" format="integer" />
|
||||
<!-- Duration, in milliseconds, of the fade out effect after the user is done
|
||||
drawing a gesture. -->
|
||||
<attr name="fadeDuration" format="integer" />
|
||||
</declare-styleable>
|
||||
|
||||
<!-- ======================================= -->
|
||||
<!-- Widget package parent layout attributes -->
|
||||
<!-- ======================================= -->
|
||||
|
@ -1101,7 +1101,13 @@
|
||||
<public type="attr" name="maxSdkVersion" />
|
||||
<public type="attr" name="testOnly" />
|
||||
<public type="attr" name="contentDescription" />
|
||||
|
||||
<public type="attr" name="gestureStrokeWidth" />
|
||||
<public type="attr" name="gestureColor" />
|
||||
<public type="attr" name="uncertainGestureColor" />
|
||||
<public type="attr" name="fadeOffset" />
|
||||
<public type="attr" name="fadeDuration" />
|
||||
<public type="attr" name="gestures" />
|
||||
|
||||
<public-padding type="attr" name="donut_resource_pad" end="0x0101029f" />
|
||||
|
||||
<public-padding type="id" name="donut_resource_pad" end="0x01020040" />
|
||||
|
@ -171,6 +171,19 @@
|
||||
<item name="android:fadingEdge">vertical</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.GestureOverlayView">
|
||||
<item name="android:gestureStrokeWidth">12.0</item>
|
||||
<item name="android:gestureColor">#ffffff00</item>
|
||||
<item name="android:uncertainGestureColor">#3cffff00</item>
|
||||
<item name="android:fadeOffset">300</item>
|
||||
<item name="android:fadeDuration">300</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.GestureOverlayView.White">
|
||||
<item name="android:gestureColor">#ff00ff00</item>
|
||||
<item name="android:uncertainGestureColor">#3c00ff00</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.Button">
|
||||
<item name="android:background">@android:drawable/btn_default</item>
|
||||
<item name="android:focusable">true</item>
|
||||
|
@ -142,7 +142,8 @@
|
||||
<item name="editTextStyle">@android:style/Widget.EditText</item>
|
||||
<item name="expandableListViewStyle">@android:style/Widget.ExpandableListView</item>
|
||||
<item name="galleryStyle">@android:style/Widget.Gallery</item>
|
||||
<item name="gridViewStyle">@android:style/Widget.GridView</item>
|
||||
<item name="gestureOverlayViewStyle">@android:style/Widget.GestureOverlayView</item>
|
||||
<item name="gridViewStyle">@android:style/Widget.GridView</item>
|
||||
<item name="imageButtonStyle">@android:style/Widget.ImageButton</item>
|
||||
<item name="imageWellStyle">@android:style/Widget.ImageWell</item>
|
||||
<item name="listViewStyle">@android:style/Widget.ListView</item>
|
||||
@ -225,6 +226,7 @@
|
||||
<item name="textCheckMark">@android:drawable/indicator_check_mark_light</item>
|
||||
<item name="textCheckMarkInverse">@android:drawable/indicator_check_mark_dark</item>
|
||||
|
||||
<item name="gestureOverlayViewStyle">@android:style/Widget.GestureOverlayView.White</item>
|
||||
<item name="listViewStyle">@android:style/Widget.ListView.White</item>
|
||||
<item name="listDivider">@drawable/divider_horizontal_bright</item>
|
||||
<item name="listSeparatorTextViewStyle">@android:style/Widget.TextView.ListSeparator.White</item>
|
||||
|
@ -25,7 +25,7 @@
|
||||
android:drawSelectorOnTop="true"
|
||||
android:prompt="@string/recognition_result"/>
|
||||
|
||||
<com.android.gesture.GestureOverlay
|
||||
<android.gesture.GestureOverlayView
|
||||
android:id="@+id/drawingpad"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -26,7 +26,7 @@
|
||||
android:drawSelectorOnTop="true"
|
||||
android:prompt="@string/recognition_result"/>
|
||||
|
||||
<com.android.gesture.GestureOverlay
|
||||
<android.gesture.GestureOverlayView
|
||||
android:id="@+id/drawingpad"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -1,12 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
<!-- Copyright (C) 2009 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.
|
||||
-->
|
||||
|
||||
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/list"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
>
|
||||
<ListView
|
||||
android:id="@+id/list"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="0dip"
|
||||
android:layout_weight="1"/>
|
||||
</LinearLayout>
|
||||
android:layout_height="fill_parent" />
|
||||
|
@ -101,9 +101,12 @@ public class ContactListGestureOverlay extends Activity {
|
||||
public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
|
||||
ArrayList<Prediction> predictions = mRecognizer.recognize(gesture);
|
||||
if (!predictions.isEmpty()) {
|
||||
Log.v(LOGTAG, "1st Prediction : " + predictions.get(0).name);
|
||||
Log.v(LOGTAG, "2nd Prediction : " + predictions.get(1).name);
|
||||
Log.v(LOGTAG, "3rd Prediction : " + predictions.get(2).name);
|
||||
Log.v(LOGTAG, "1st Prediction : " + predictions.get(0).name +
|
||||
" @" + predictions.get(0).score);
|
||||
Log.v(LOGTAG, "2nd Prediction : " + predictions.get(1).name +
|
||||
" @" + predictions.get(1).score);
|
||||
Log.v(LOGTAG, "3rd Prediction : " + predictions.get(2).name +
|
||||
" @" + predictions.get(2).score);
|
||||
int index = mContactAdapter.search(predictions.get(0).name);
|
||||
if (index != -1) {
|
||||
mContactList.setSelection(index);
|
||||
|
@ -146,6 +146,7 @@ public class Converter {
|
||||
|
||||
long start = System.nanoTime();
|
||||
|
||||
in.readShort();
|
||||
iCount = in.readInt();
|
||||
hCount = in.readInt();
|
||||
oCount = in.readInt();
|
||||
|
Reference in New Issue
Block a user