Merge change 2402 into donut
* changes: Cleanup Gestures API and make it easier to use in 3rd party apps. Also fix the events processing in the gestures overlay mechanism. Give better control of the various properties of the overlay through XML attributes.
This commit is contained in:
605
api/current.xml
605
api/current.xml
@ -3529,61 +3529,6 @@
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="donut_resource_pad34"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value="16843390"
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="donut_resource_pad35"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value="16843389"
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="donut_resource_pad36"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value="16843388"
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="donut_resource_pad37"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value="16843387"
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="donut_resource_pad38"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value="16843386"
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="donut_resource_pad4"
|
||||
type="int"
|
||||
transient="false"
|
||||
@ -3947,6 +3892,17 @@
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="eventsInterceptionEnabled"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value="16843390"
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="excludeFromRecents"
|
||||
type="int"
|
||||
transient="false"
|
||||
@ -4420,6 +4376,50 @@
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="gestureStrokeAngleThreshold"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value="16843389"
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="gestureStrokeLengthThreshold"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value="16843387"
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="gestureStrokeSquarenessThreshold"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value="16843388"
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="gestureStrokeType"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value="16843386"
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="gestureStrokeWidth"
|
||||
type="int"
|
||||
transient="false"
|
||||
@ -46303,6 +46303,70 @@
|
||||
<parameter name="color" type="int">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="toPath"
|
||||
return="android.graphics.Path"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</method>
|
||||
<method name="toPath"
|
||||
return="android.graphics.Path"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="path" type="android.graphics.Path">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="toPath"
|
||||
return="android.graphics.Path"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="width" type="int">
|
||||
</parameter>
|
||||
<parameter name="height" type="int">
|
||||
</parameter>
|
||||
<parameter name="edge" type="int">
|
||||
</parameter>
|
||||
<parameter name="numSample" type="int">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="toPath"
|
||||
return="android.graphics.Path"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="path" type="android.graphics.Path">
|
||||
</parameter>
|
||||
<parameter name="width" type="int">
|
||||
</parameter>
|
||||
<parameter name="height" type="int">
|
||||
</parameter>
|
||||
<parameter name="edge" type="int">
|
||||
</parameter>
|
||||
<parameter name="numSample" type="int">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="writeToParcel"
|
||||
return="void"
|
||||
abstract="false"
|
||||
@ -46543,7 +46607,7 @@
|
||||
</field>
|
||||
</class>
|
||||
<class name="GestureOverlayView"
|
||||
extends="android.view.View"
|
||||
extends="android.widget.FrameLayout"
|
||||
abstract="false"
|
||||
static="false"
|
||||
final="false"
|
||||
@ -46599,7 +46663,31 @@
|
||||
<parameter name="listener" type="android.gesture.GestureOverlayView.OnGestureListener">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="cancelFadingOut"
|
||||
<method name="addOnGesturePerformedListener"
|
||||
return="void"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="listener" type="android.gesture.GestureOverlayView.OnGesturePerformedListener">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="cancelClearAnimation"
|
||||
return="void"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</method>
|
||||
<method name="cancelGesture"
|
||||
return="void"
|
||||
abstract="false"
|
||||
native="false"
|
||||
@ -46620,11 +46708,11 @@
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="fadeOut" type="boolean">
|
||||
<parameter name="animated" type="boolean">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="getCurrentGesture"
|
||||
return="android.gesture.Gesture"
|
||||
<method name="getCurrentStroke"
|
||||
return="java.util.ArrayList<android.gesture.GesturePoint>"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
@ -46634,8 +46722,8 @@
|
||||
visibility="public"
|
||||
>
|
||||
</method>
|
||||
<method name="getCurrentStroke"
|
||||
return="java.util.ArrayList<android.gesture.GesturePoint>"
|
||||
<method name="getGesture"
|
||||
return="android.gesture.Gesture"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
@ -46656,7 +46744,51 @@
|
||||
visibility="public"
|
||||
>
|
||||
</method>
|
||||
<method name="getGestureStroke"
|
||||
<method name="getGestureStrokeAngleThreshold"
|
||||
return="float"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</method>
|
||||
<method name="getGestureStrokeLengthThreshold"
|
||||
return="float"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</method>
|
||||
<method name="getGestureStrokeSquarenessTreshold"
|
||||
return="float"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</method>
|
||||
<method name="getGestureStrokeType"
|
||||
return="int"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</method>
|
||||
<method name="getGestureStrokeWidth"
|
||||
return="float"
|
||||
abstract="false"
|
||||
native="false"
|
||||
@ -46678,7 +46810,29 @@
|
||||
visibility="public"
|
||||
>
|
||||
</method>
|
||||
<method name="processEvent"
|
||||
<method name="isEventsInterceptionEnabled"
|
||||
return="boolean"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</method>
|
||||
<method name="isGesturing"
|
||||
return="boolean"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</method>
|
||||
<method name="removeAllOnGestureListeners"
|
||||
return="void"
|
||||
abstract="false"
|
||||
native="false"
|
||||
@ -46688,10 +46842,8 @@
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="event" type="android.view.MotionEvent">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="removeAllOnGestureListeners"
|
||||
<method name="removeAllOnGesturePerformedListeners"
|
||||
return="void"
|
||||
abstract="false"
|
||||
native="false"
|
||||
@ -46715,7 +46867,33 @@
|
||||
<parameter name="listener" type="android.gesture.GestureOverlayView.OnGestureListener">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="setCurrentGesture"
|
||||
<method name="removeOnGesturePerformedListener"
|
||||
return="void"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="listener" type="android.gesture.GestureOverlayView.OnGesturePerformedListener">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="setEventsInterceptionEnabled"
|
||||
return="void"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="enabled" type="boolean">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="setGesture"
|
||||
return="void"
|
||||
abstract="false"
|
||||
native="false"
|
||||
@ -46741,7 +46919,7 @@
|
||||
<parameter name="color" type="int">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="setGestureDrawingColor"
|
||||
<method name="setGestureStrokeAngleThreshold"
|
||||
return="void"
|
||||
abstract="false"
|
||||
native="false"
|
||||
@ -46751,10 +46929,10 @@
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="color" type="int">
|
||||
<parameter name="gestureStrokeAngleThreshold" type="float">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="setGestureStroke"
|
||||
<method name="setGestureStrokeLengthThreshold"
|
||||
return="void"
|
||||
abstract="false"
|
||||
native="false"
|
||||
@ -46764,7 +46942,46 @@
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="gestureStroke" type="float">
|
||||
<parameter name="gestureStrokeLengthThreshold" type="float">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="setGestureStrokeSquarenessTreshold"
|
||||
return="void"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="gestureStrokeSquarenessTreshold" type="float">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="setGestureStrokeType"
|
||||
return="void"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="gestureStrokeType" type="int">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="setGestureStrokeWidth"
|
||||
return="void"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="gestureStrokeWidth" type="float">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="setUncertainGestureColor"
|
||||
@ -46780,6 +46997,28 @@
|
||||
<parameter name="color" type="int">
|
||||
</parameter>
|
||||
</method>
|
||||
<field name="GESTURE_STROKE_TYPE_MULTIPLE"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value="1"
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="GESTURE_STROKE_TYPE_SINGLE"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value="0"
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
</class>
|
||||
<interface name="GestureOverlayView.OnGestureListener"
|
||||
abstract="true"
|
||||
@ -46849,6 +47088,29 @@
|
||||
</parameter>
|
||||
</method>
|
||||
</interface>
|
||||
<interface name="GestureOverlayView.OnGesturePerformedListener"
|
||||
abstract="true"
|
||||
static="true"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<method name="onGesturePerformed"
|
||||
return="void"
|
||||
abstract="true"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="overlay" type="android.gesture.GestureOverlayView">
|
||||
</parameter>
|
||||
<parameter name="gesture" type="android.gesture.Gesture">
|
||||
</parameter>
|
||||
</method>
|
||||
</interface>
|
||||
<class name="GesturePoint"
|
||||
extends="java.lang.Object"
|
||||
abstract="false"
|
||||
@ -46942,6 +47204,17 @@
|
||||
visibility="public"
|
||||
>
|
||||
</method>
|
||||
<method name="getPath"
|
||||
return="android.graphics.Path"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</method>
|
||||
<method name="toPath"
|
||||
return="android.graphics.Path"
|
||||
abstract="false"
|
||||
@ -47152,194 +47425,6 @@
|
||||
>
|
||||
</field>
|
||||
</class>
|
||||
<class name="TouchThroughGestureListener"
|
||||
extends="java.lang.Object"
|
||||
abstract="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<implements name="android.gesture.GestureOverlayView.OnGestureListener">
|
||||
</implements>
|
||||
<constructor name="TouchThroughGestureListener"
|
||||
type="android.gesture.TouchThroughGestureListener"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="model" type="android.view.View">
|
||||
</parameter>
|
||||
</constructor>
|
||||
<constructor name="TouchThroughGestureListener"
|
||||
type="android.gesture.TouchThroughGestureListener"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="model" type="android.view.View">
|
||||
</parameter>
|
||||
<parameter name="stealEvents" type="boolean">
|
||||
</parameter>
|
||||
</constructor>
|
||||
<method name="addOnGestureActionListener"
|
||||
return="void"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="listener" type="android.gesture.TouchThroughGestureListener.OnGesturePerformedListener">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="isGesturing"
|
||||
return="boolean"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</method>
|
||||
<method name="onGesture"
|
||||
return="void"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="overlay" type="android.gesture.GestureOverlayView">
|
||||
</parameter>
|
||||
<parameter name="event" type="android.view.MotionEvent">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="onGestureCancelled"
|
||||
return="void"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="overlay" type="android.gesture.GestureOverlayView">
|
||||
</parameter>
|
||||
<parameter name="event" type="android.view.MotionEvent">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="onGestureEnded"
|
||||
return="void"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="overlay" type="android.gesture.GestureOverlayView">
|
||||
</parameter>
|
||||
<parameter name="event" type="android.view.MotionEvent">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="onGestureStarted"
|
||||
return="void"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="overlay" type="android.gesture.GestureOverlayView">
|
||||
</parameter>
|
||||
<parameter name="event" type="android.view.MotionEvent">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="removeOnGestureActionListener"
|
||||
return="void"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="listener" type="android.gesture.TouchThroughGestureListener.OnGesturePerformedListener">
|
||||
</parameter>
|
||||
</method>
|
||||
<method name="setGestureType"
|
||||
return="void"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="type" type="int">
|
||||
</parameter>
|
||||
</method>
|
||||
<field name="MULTIPLE_STROKE"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value="1"
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
<field name="SINGLE_STROKE"
|
||||
type="int"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value="0"
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
</class>
|
||||
<interface name="TouchThroughGestureListener.OnGesturePerformedListener"
|
||||
abstract="true"
|
||||
static="true"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<method name="onGesturePerformed"
|
||||
return="void"
|
||||
abstract="true"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="overlay" type="android.gesture.GestureOverlayView">
|
||||
</parameter>
|
||||
<parameter name="gesture" type="android.gesture.Gesture">
|
||||
</parameter>
|
||||
</method>
|
||||
</interface>
|
||||
</package>
|
||||
<package name="android.graphics"
|
||||
>
|
||||
|
@ -57,6 +57,11 @@ public class Gesture implements Parcelable {
|
||||
mGestureID = GESTURE_ID_BASE + sGestureCount++;
|
||||
}
|
||||
|
||||
void recycle() {
|
||||
mStrokes.clear();
|
||||
mBoundingBox.setEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return all the strokes of the gesture
|
||||
*/
|
||||
@ -111,6 +116,40 @@ public class Gesture implements Parcelable {
|
||||
return mBoundingBox;
|
||||
}
|
||||
|
||||
public Path toPath() {
|
||||
return toPath(null);
|
||||
}
|
||||
|
||||
public Path toPath(Path path) {
|
||||
if (path == null) path = new Path();
|
||||
|
||||
final ArrayList<GestureStroke> strokes = mStrokes;
|
||||
final int count = strokes.size();
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
path.addPath(strokes.get(i).getPath());
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
public Path toPath(int width, int height, int edge, int numSample) {
|
||||
return toPath(null, width, height, edge, numSample);
|
||||
}
|
||||
|
||||
public Path toPath(Path path, int width, int height, int edge, int numSample) {
|
||||
if (path == null) path = new Path();
|
||||
|
||||
final ArrayList<GestureStroke> strokes = mStrokes;
|
||||
final int count = strokes.size();
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
path.addPath(strokes.get(i).toPath(width - 2 * edge, height - 2 * edge, numSample));
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the id of the gesture
|
||||
*
|
||||
|
@ -18,51 +18,62 @@ package android.gesture;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.view.animation.AccelerateDecelerateInterpolator;
|
||||
import android.widget.FrameLayout;
|
||||
import android.os.SystemClock;
|
||||
import com.android.internal.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* A (transparent) overlay for gesture input that can be placed on top of other
|
||||
* widgets.
|
||||
* A transparent overlay for gesture input that can be placed on top of other
|
||||
* widgets or contain other 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_eventsInterceptionEnabled
|
||||
* @attr ref android.R.styleable#GestureOverlayView_fadeDuration
|
||||
* @attr ref android.R.styleable#GestureOverlayView_fadeOffset
|
||||
* @attr ref android.R.styleable#GestureOverlayView_gestureStrokeWidth
|
||||
* @attr ref android.R.styleable#GestureOverlayView_gestureStrokeAngleThreshold
|
||||
* @attr ref android.R.styleable#GestureOverlayView_gestureStrokeLengthThreshold
|
||||
* @attr ref android.R.styleable#GestureOverlayView_gestureStrokeSquarenessThreshold
|
||||
* @attr ref android.R.styleable#GestureOverlayView_gestureStrokeType
|
||||
* @attr ref android.R.styleable#GestureOverlayView_gestureColor
|
||||
* @attr ref android.R.styleable#GestureOverlayView_uncertainGestureColor
|
||||
*/
|
||||
public class GestureOverlayView extends View {
|
||||
private static final int TRANSPARENT_BACKGROUND = 0x00000000;
|
||||
public class GestureOverlayView extends FrameLayout {
|
||||
public static final int GESTURE_STROKE_TYPE_SINGLE = 0;
|
||||
public static final int GESTURE_STROKE_TYPE_MULTIPLE = 1;
|
||||
|
||||
private static final int FADE_ANIMATION_RATE = 16;
|
||||
private static final boolean GESTURE_RENDERING_ANTIALIAS = true;
|
||||
private static final boolean DITHER_FLAG = true;
|
||||
|
||||
private Paint mGesturePaint;
|
||||
private final Paint mGesturePaint = new Paint();
|
||||
|
||||
private final Paint mBitmapPaint = new Paint(Paint.DITHER_FLAG);
|
||||
private Bitmap mBitmap;
|
||||
private Canvas mBitmapCanvas;
|
||||
|
||||
private long mFadeDuration = 300;
|
||||
private long mFadeOffset = 300;
|
||||
private long mFadeDuration = 150;
|
||||
private long mFadeOffset = 420;
|
||||
private long mFadingStart;
|
||||
private boolean mFadingHasStarted;
|
||||
|
||||
private float mGestureStroke = 12.0f;
|
||||
private int mCurrentColor;
|
||||
private int mCertainGestureColor = 0xFFFFFF00;
|
||||
private int mUncertainGestureColor = 0x3CFFFF00;
|
||||
private int mUncertainGestureColor = 0x48FFFF00;
|
||||
private float mGestureStrokeWidth = 12.0f;
|
||||
private int mInvalidateExtraBorder = 10;
|
||||
|
||||
// for rendering immediate ink feedback
|
||||
private int mGestureStrokeType = GESTURE_STROKE_TYPE_SINGLE;
|
||||
private float mGestureStrokeLengthThreshold = 30.0f;
|
||||
private float mGestureStrokeSquarenessTreshold = 0.275f;
|
||||
private float mGestureStrokeAngleThreshold = 40.0f;
|
||||
|
||||
private final Rect mInvalidRect = new Rect();
|
||||
private final Path mPath = new Path();
|
||||
|
||||
@ -72,41 +83,31 @@ public class GestureOverlayView extends View {
|
||||
private float mCurveEndX;
|
||||
private float mCurveEndY;
|
||||
|
||||
private float mTotalLength;
|
||||
private boolean mIsGesturing = false;
|
||||
private boolean mInterceptEvents = true;
|
||||
private boolean mIsListeningForGestures;
|
||||
|
||||
// current gesture
|
||||
private Gesture mCurrentGesture = null;
|
||||
private Gesture mCurrentGesture;
|
||||
private final ArrayList<GesturePoint> mStrokeBuffer = new ArrayList<GesturePoint>(100);
|
||||
|
||||
// TODO: Make this a list of WeakReferences
|
||||
private final ArrayList<OnGestureListener> mOnGestureListeners =
|
||||
new ArrayList<OnGestureListener>();
|
||||
private final ArrayList<GesturePoint> mPointBuffer = new ArrayList<GesturePoint>(100);
|
||||
// TODO: Make this a list of WeakReferences
|
||||
private final ArrayList<OnGesturePerformedListener> mOnGesturePerformedListeners =
|
||||
new ArrayList<OnGesturePerformedListener>();
|
||||
|
||||
private boolean mHandleGestureActions;
|
||||
|
||||
// fading out effect
|
||||
private boolean mIsFadingOut = false;
|
||||
private float mFadingAlpha = 1;
|
||||
private float mFadingAlpha = 1.0f;
|
||||
private final AccelerateDecelerateInterpolator mInterpolator =
|
||||
new AccelerateDecelerateInterpolator();
|
||||
|
||||
private final Runnable mFadingOut = new Runnable() {
|
||||
public void run() {
|
||||
if (mIsFadingOut) {
|
||||
final long now = AnimationUtils.currentAnimationTimeMillis();
|
||||
final long duration = now - mFadingStart;
|
||||
|
||||
if (duration > mFadeDuration) {
|
||||
mIsFadingOut = false;
|
||||
mPath.rewind();
|
||||
mCurrentGesture = null;
|
||||
mBitmap.eraseColor(TRANSPARENT_BACKGROUND);
|
||||
} else {
|
||||
float interpolatedTime = Math.max(0.0f,
|
||||
Math.min(1.0f, duration / (float) mFadeDuration));
|
||||
mFadingAlpha = 1.0f - mInterpolator.getInterpolation(interpolatedTime);
|
||||
postDelayed(this, 16);
|
||||
}
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
};
|
||||
private final FadeOutRunnable mFadingOut = new FadeOutRunnable();
|
||||
|
||||
public GestureOverlayView(Context context) {
|
||||
super(context);
|
||||
@ -123,41 +124,52 @@ public class GestureOverlayView extends View {
|
||||
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);
|
||||
mGestureStrokeWidth = a.getFloat(R.styleable.GestureOverlayView_gestureStrokeWidth,
|
||||
mGestureStrokeWidth);
|
||||
mInvalidateExtraBorder = Math.max(1, ((int) mGestureStrokeWidth) - 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);
|
||||
mGestureStrokeType = a.getInt(R.styleable.GestureOverlayView_gestureStrokeType,
|
||||
mGestureStrokeType);
|
||||
mGestureStrokeLengthThreshold = a.getFloat(
|
||||
R.styleable.GestureOverlayView_gestureStrokeLengthThreshold,
|
||||
mGestureStrokeLengthThreshold);
|
||||
mGestureStrokeAngleThreshold = a.getFloat(
|
||||
R.styleable.GestureOverlayView_gestureStrokeAngleThreshold,
|
||||
mGestureStrokeAngleThreshold);
|
||||
mGestureStrokeSquarenessTreshold = a.getFloat(
|
||||
R.styleable.GestureOverlayView_gestureStrokeSquarenessThreshold,
|
||||
mGestureStrokeSquarenessTreshold);
|
||||
mInterceptEvents = a.getBoolean(R.styleable.GestureOverlayView_eventsInterceptionEnabled,
|
||||
mInterceptEvents);
|
||||
|
||||
a.recycle();
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
setWillNotDraw(false);
|
||||
|
||||
final Paint gesturePaint = mGesturePaint;
|
||||
gesturePaint.setAntiAlias(GESTURE_RENDERING_ANTIALIAS);
|
||||
gesturePaint.setColor(mCertainGestureColor);
|
||||
gesturePaint.setStyle(Paint.Style.STROKE);
|
||||
gesturePaint.setStrokeJoin(Paint.Join.ROUND);
|
||||
gesturePaint.setStrokeCap(Paint.Cap.ROUND);
|
||||
gesturePaint.setStrokeWidth(mGestureStrokeWidth);
|
||||
gesturePaint.setDither(DITHER_FLAG);
|
||||
|
||||
mCurrentColor = mCertainGestureColor;
|
||||
setPaintAlpha(255);
|
||||
}
|
||||
|
||||
public ArrayList<GesturePoint> getCurrentStroke() {
|
||||
return mPointBuffer;
|
||||
}
|
||||
|
||||
public Gesture getCurrentGesture() {
|
||||
return mCurrentGesture;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Gesture color
|
||||
*
|
||||
* @param color
|
||||
*/
|
||||
public void setGestureDrawingColor(int color) {
|
||||
mGesturePaint.setColor(color);
|
||||
if (mCurrentGesture != null) {
|
||||
mBitmap.eraseColor(TRANSPARENT_BACKGROUND);
|
||||
mCurrentGesture.draw(mBitmapCanvas, mGesturePaint);
|
||||
}
|
||||
invalidate();
|
||||
return mStrokeBuffer;
|
||||
}
|
||||
|
||||
public void setGestureColor(int color) {
|
||||
@ -176,73 +188,77 @@ public class GestureOverlayView extends View {
|
||||
return mCertainGestureColor;
|
||||
}
|
||||
|
||||
public float getGestureStroke() {
|
||||
return mGestureStroke;
|
||||
public float getGestureStrokeWidth() {
|
||||
return mGestureStrokeWidth;
|
||||
}
|
||||
|
||||
public void setGestureStroke(float gestureStroke) {
|
||||
mGestureStroke = gestureStroke;
|
||||
mInvalidateExtraBorder = Math.max(1, ((int) mGestureStroke) - 1);
|
||||
mGesturePaint.setStrokeWidth(mGestureStroke);
|
||||
public void setGestureStrokeWidth(float gestureStrokeWidth) {
|
||||
mGestureStrokeWidth = gestureStrokeWidth;
|
||||
mInvalidateExtraBorder = Math.max(1, ((int) gestureStrokeWidth) - 1);
|
||||
mGesturePaint.setStrokeWidth(gestureStrokeWidth);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the gesture to be shown in the view
|
||||
*
|
||||
* @param gesture
|
||||
*/
|
||||
public void setCurrentGesture(Gesture gesture) {
|
||||
public int getGestureStrokeType() {
|
||||
return mGestureStrokeType;
|
||||
}
|
||||
|
||||
public void setGestureStrokeType(int gestureStrokeType) {
|
||||
mGestureStrokeType = gestureStrokeType;
|
||||
}
|
||||
|
||||
public float getGestureStrokeLengthThreshold() {
|
||||
return mGestureStrokeLengthThreshold;
|
||||
}
|
||||
|
||||
public void setGestureStrokeLengthThreshold(float gestureStrokeLengthThreshold) {
|
||||
mGestureStrokeLengthThreshold = gestureStrokeLengthThreshold;
|
||||
}
|
||||
|
||||
public float getGestureStrokeSquarenessTreshold() {
|
||||
return mGestureStrokeSquarenessTreshold;
|
||||
}
|
||||
|
||||
public void setGestureStrokeSquarenessTreshold(float gestureStrokeSquarenessTreshold) {
|
||||
mGestureStrokeSquarenessTreshold = gestureStrokeSquarenessTreshold;
|
||||
}
|
||||
|
||||
public float getGestureStrokeAngleThreshold() {
|
||||
return mGestureStrokeAngleThreshold;
|
||||
}
|
||||
|
||||
public void setGestureStrokeAngleThreshold(float gestureStrokeAngleThreshold) {
|
||||
mGestureStrokeAngleThreshold = gestureStrokeAngleThreshold;
|
||||
}
|
||||
|
||||
public boolean isEventsInterceptionEnabled() {
|
||||
return mInterceptEvents;
|
||||
}
|
||||
|
||||
public void setEventsInterceptionEnabled(boolean enabled) {
|
||||
mInterceptEvents = enabled;
|
||||
}
|
||||
|
||||
public Gesture getGesture() {
|
||||
return mCurrentGesture;
|
||||
}
|
||||
|
||||
public void setGesture(Gesture gesture) {
|
||||
if (mCurrentGesture != null) {
|
||||
clear(false);
|
||||
}
|
||||
|
||||
setCurrentColor(mCertainGestureColor);
|
||||
mCurrentGesture = gesture;
|
||||
|
||||
if (gesture != null) {
|
||||
if (mBitmapCanvas != null) {
|
||||
gesture.draw(mBitmapCanvas, mGesturePaint);
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
final Path path = mCurrentGesture.toPath();
|
||||
final RectF bounds = new RectF();
|
||||
path.computeBounds(bounds, true);
|
||||
|
||||
private void init() {
|
||||
mGesturePaint = new Paint();
|
||||
mPath.rewind();
|
||||
mPath.addPath(path, (getWidth() - bounds.width()) / 2.0f,
|
||||
(getHeight() - bounds.height()) / 2.0f);
|
||||
|
||||
final Paint gesturePaint = mGesturePaint;
|
||||
gesturePaint.setAntiAlias(GESTURE_RENDERING_ANTIALIAS);
|
||||
gesturePaint.setColor(mCertainGestureColor);
|
||||
gesturePaint.setStyle(Paint.Style.STROKE);
|
||||
gesturePaint.setStrokeJoin(Paint.Join.ROUND);
|
||||
gesturePaint.setStrokeCap(Paint.Cap.ROUND);
|
||||
gesturePaint.setStrokeWidth(mGestureStroke);
|
||||
gesturePaint.setDither(DITHER_FLAG);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) {
|
||||
super.onSizeChanged(width, height, oldWidth, oldHeight);
|
||||
|
||||
if (width <= 0 || height <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int targetWidth = width > oldWidth ? width : oldWidth;
|
||||
int targetHeight = height > oldHeight ? height : oldHeight;
|
||||
|
||||
if (mBitmap != null) mBitmap.recycle();
|
||||
|
||||
mBitmap = Bitmap.createBitmap(targetWidth, targetHeight, Bitmap.Config.ARGB_8888);
|
||||
if (mBitmapCanvas != null) {
|
||||
mBitmapCanvas.setBitmap(mBitmap);
|
||||
} else {
|
||||
mBitmapCanvas = new Canvas(mBitmap);
|
||||
}
|
||||
mBitmapCanvas.drawColor(TRANSPARENT_BACKGROUND);
|
||||
|
||||
if (mCurrentGesture != null) {
|
||||
mCurrentGesture.draw(mBitmapCanvas, mGesturePaint);
|
||||
}
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void addOnGestureListener(OnGestureListener listener) {
|
||||
@ -257,100 +273,172 @@ public class GestureOverlayView extends View {
|
||||
mOnGestureListeners.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
|
||||
// draw double buffer
|
||||
if (mIsFadingOut) {
|
||||
mBitmapPaint.setAlpha((int) (255 * mFadingAlpha));
|
||||
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
|
||||
} else {
|
||||
mBitmapPaint.setAlpha(255);
|
||||
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
|
||||
public void addOnGesturePerformedListener(OnGesturePerformedListener listener) {
|
||||
mOnGesturePerformedListeners.add(listener);
|
||||
if (mOnGesturePerformedListeners.size() > 0) {
|
||||
mHandleGestureActions = true;
|
||||
}
|
||||
|
||||
// draw the current stroke
|
||||
canvas.drawPath(mPath, mGesturePaint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear up the overlay
|
||||
*
|
||||
* @param fadeOut whether the gesture on the overlay should fade out
|
||||
* gradually or disappear immediately
|
||||
*/
|
||||
public void clear(boolean fadeOut) {
|
||||
if (fadeOut) {
|
||||
public void removeOnGesturePerformedListener(OnGesturePerformedListener listener) {
|
||||
mOnGesturePerformedListeners.remove(listener);
|
||||
if (mOnGesturePerformedListeners.size() <= 0) {
|
||||
mHandleGestureActions = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAllOnGesturePerformedListeners() {
|
||||
mOnGesturePerformedListeners.clear();
|
||||
mHandleGestureActions = false;
|
||||
}
|
||||
|
||||
public boolean isGesturing() {
|
||||
return mIsGesturing;
|
||||
}
|
||||
|
||||
private void setCurrentColor(int color) {
|
||||
mCurrentColor = color;
|
||||
if (mFadingHasStarted) {
|
||||
setPaintAlpha((int) (255 * mFadingAlpha));
|
||||
} else {
|
||||
setPaintAlpha(255);
|
||||
}
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
super.draw(canvas);
|
||||
|
||||
if (mCurrentGesture != null) {
|
||||
canvas.drawPath(mPath, mGesturePaint);
|
||||
}
|
||||
}
|
||||
|
||||
private void setPaintAlpha(int alpha) {
|
||||
alpha += alpha >> 7;
|
||||
final int baseAlpha = mCurrentColor >>> 24;
|
||||
final int useAlpha = baseAlpha * alpha >> 8;
|
||||
mGesturePaint.setColor((mCurrentColor << 8 >>> 8) | (useAlpha << 24));
|
||||
}
|
||||
|
||||
public void clear(boolean animated) {
|
||||
clear(animated, false);
|
||||
}
|
||||
|
||||
private void clear(boolean animated, boolean fireActionPerformed) {
|
||||
setPaintAlpha(255);
|
||||
if (animated && mCurrentGesture != null) {
|
||||
mFadingAlpha = 1.0f;
|
||||
mIsFadingOut = true;
|
||||
mFadingHasStarted = false;
|
||||
mFadingOut.fireActionPerformed = fireActionPerformed;
|
||||
removeCallbacks(mFadingOut);
|
||||
mFadingStart = AnimationUtils.currentAnimationTimeMillis() + mFadeOffset;
|
||||
postDelayed(mFadingOut, mFadeOffset);
|
||||
} else {
|
||||
mPath.rewind();
|
||||
mCurrentGesture = null;
|
||||
if (mBitmap != null) {
|
||||
mBitmap.eraseColor(TRANSPARENT_BACKGROUND);
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void cancelFadingOut() {
|
||||
public void cancelClearAnimation() {
|
||||
setPaintAlpha(255);
|
||||
mIsFadingOut = false;
|
||||
mFadingHasStarted = false;
|
||||
removeCallbacks(mFadingOut);
|
||||
mPath.rewind();
|
||||
mCurrentGesture = null;
|
||||
}
|
||||
|
||||
public void cancelGesture() {
|
||||
mIsListeningForGestures = false;
|
||||
|
||||
// add the stroke to the current gesture
|
||||
mCurrentGesture.addStroke(new GestureStroke(mStrokeBuffer));
|
||||
|
||||
// pass the event to handlers
|
||||
final long now = SystemClock.uptimeMillis();
|
||||
final MotionEvent event = MotionEvent.obtain(now, now,
|
||||
MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0);
|
||||
|
||||
final ArrayList<OnGestureListener> listeners = mOnGestureListeners;
|
||||
final int count = listeners.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
listeners.get(i).onGestureCancelled(this, event);
|
||||
}
|
||||
|
||||
event.recycle();
|
||||
|
||||
clear(false);
|
||||
mIsGesturing = false;
|
||||
mStrokeBuffer.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
if (!isEnabled()) {
|
||||
protected void onDetachedFromWindow() {
|
||||
cancelClearAnimation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchTouchEvent(MotionEvent event) {
|
||||
if (isEnabled()) {
|
||||
boolean cancelDispatch = (mIsGesturing || (mCurrentGesture != null &&
|
||||
mCurrentGesture.getStrokesCount() > 0)) && mInterceptEvents;
|
||||
processEvent(event);
|
||||
|
||||
if (cancelDispatch) {
|
||||
event.setAction(MotionEvent.ACTION_CANCEL);
|
||||
}
|
||||
|
||||
super.dispatchTouchEvent(event);
|
||||
return true;
|
||||
}
|
||||
|
||||
processEvent(event);
|
||||
|
||||
return true;
|
||||
return super.dispatchTouchEvent(event);
|
||||
}
|
||||
|
||||
public void processEvent(MotionEvent event) {
|
||||
private boolean processEvent(MotionEvent event) {
|
||||
switch (event.getAction()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
Rect rect = touchStart(event);
|
||||
invalidate(rect);
|
||||
break;
|
||||
touchStart(event);
|
||||
invalidate();
|
||||
return true;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
rect = touchMove(event);
|
||||
if (rect != null) {
|
||||
invalidate(rect);
|
||||
if (mIsListeningForGestures) {
|
||||
Rect rect = touchMove(event);
|
||||
if (rect != null) {
|
||||
invalidate(rect);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
touchUp(event, false);
|
||||
invalidate();
|
||||
if (mIsListeningForGestures) {
|
||||
touchUp(event, false);
|
||||
invalidate();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
touchUp(event, true);
|
||||
invalidate();
|
||||
break;
|
||||
if (mIsListeningForGestures) {
|
||||
touchUp(event, true);
|
||||
invalidate();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private Rect touchStart(MotionEvent event) {
|
||||
private void touchStart(MotionEvent event) {
|
||||
mIsListeningForGestures = true;
|
||||
|
||||
// pass the event to handlers
|
||||
final ArrayList<OnGestureListener> listeners = mOnGestureListeners;
|
||||
final int count = listeners.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
OnGestureListener listener = listeners.get(i);
|
||||
listener.onGestureStarted(this, event);
|
||||
}
|
||||
|
||||
// if there is fading out going on, stop it.
|
||||
if (mIsFadingOut) {
|
||||
mIsFadingOut = false;
|
||||
removeCallbacks(mFadingOut);
|
||||
mBitmap.eraseColor(TRANSPARENT_BACKGROUND);
|
||||
mCurrentGesture = null;
|
||||
listeners.get(i).onGestureStarted(this, event);
|
||||
}
|
||||
|
||||
float x = event.getX();
|
||||
@ -359,22 +447,39 @@ public class GestureOverlayView extends View {
|
||||
mX = x;
|
||||
mY = y;
|
||||
|
||||
mTotalLength = 0;
|
||||
mIsGesturing = false;
|
||||
|
||||
if (mGestureStrokeType == GESTURE_STROKE_TYPE_SINGLE) {
|
||||
if (mHandleGestureActions) setCurrentColor(mUncertainGestureColor);
|
||||
mCurrentGesture = null;
|
||||
mPath.rewind();
|
||||
} else if (mCurrentGesture == null || mCurrentGesture.getStrokesCount() == 0) {
|
||||
if (mHandleGestureActions) setCurrentColor(mUncertainGestureColor);
|
||||
}
|
||||
|
||||
// if there is fading out going on, stop it.
|
||||
if (mFadingHasStarted) {
|
||||
cancelClearAnimation();
|
||||
} else if (mIsFadingOut) {
|
||||
setPaintAlpha(255);
|
||||
mIsFadingOut = false;
|
||||
mFadingHasStarted = false;
|
||||
removeCallbacks(mFadingOut);
|
||||
}
|
||||
|
||||
if (mCurrentGesture == null) {
|
||||
mCurrentGesture = new Gesture();
|
||||
}
|
||||
|
||||
mPointBuffer.add(new GesturePoint(x, y, event.getEventTime()));
|
||||
|
||||
mPath.rewind();
|
||||
mStrokeBuffer.add(new GesturePoint(x, y, event.getEventTime()));
|
||||
mPath.moveTo(x, y);
|
||||
|
||||
mInvalidRect.set((int) x - mInvalidateExtraBorder, (int) y - mInvalidateExtraBorder,
|
||||
(int) x + mInvalidateExtraBorder, (int) y + mInvalidateExtraBorder);
|
||||
|
||||
final int border = mInvalidateExtraBorder;
|
||||
mInvalidRect.set((int) x - border, (int) y - border, (int) x + border, (int) y + border);
|
||||
|
||||
mCurveEndX = x;
|
||||
mCurveEndY = y;
|
||||
|
||||
return mInvalidRect;
|
||||
}
|
||||
|
||||
private Rect touchMove(MotionEvent event) {
|
||||
@ -393,36 +498,28 @@ public class GestureOverlayView extends View {
|
||||
areaToRefresh = mInvalidRect;
|
||||
|
||||
// start with the curve end
|
||||
areaToRefresh.set(
|
||||
(int) mCurveEndX - mInvalidateExtraBorder,
|
||||
(int) mCurveEndY - mInvalidateExtraBorder,
|
||||
(int) mCurveEndX + mInvalidateExtraBorder,
|
||||
(int) mCurveEndY + mInvalidateExtraBorder);
|
||||
final int border = mInvalidateExtraBorder;
|
||||
areaToRefresh.set((int) mCurveEndX - border, (int) mCurveEndY - border,
|
||||
(int) mCurveEndX + border, (int) mCurveEndY + border);
|
||||
|
||||
mCurveEndX = (x + previousX) / 2;
|
||||
mCurveEndY = (y + previousY) / 2;
|
||||
float cX = mCurveEndX = (x + previousX) / 2;
|
||||
float cY = mCurveEndY = (y + previousY) / 2;
|
||||
|
||||
mPath.quadTo(previousX, previousY, mCurveEndX, mCurveEndY);
|
||||
mPath.quadTo(previousX, previousY, cX, cY);
|
||||
|
||||
// union with the control point of the new curve
|
||||
areaToRefresh.union(
|
||||
(int) previousX - mInvalidateExtraBorder,
|
||||
(int) previousY - mInvalidateExtraBorder,
|
||||
(int) previousX + mInvalidateExtraBorder,
|
||||
(int) previousY + mInvalidateExtraBorder);
|
||||
areaToRefresh.union((int) previousX - border, (int) previousY - border,
|
||||
(int) previousX + border, (int) previousY + border);
|
||||
|
||||
// union with the end point of the new curve
|
||||
areaToRefresh.union(
|
||||
(int) mCurveEndX - mInvalidateExtraBorder,
|
||||
(int) mCurveEndY - mInvalidateExtraBorder,
|
||||
(int) mCurveEndX + mInvalidateExtraBorder,
|
||||
(int) mCurveEndY + mInvalidateExtraBorder);
|
||||
areaToRefresh.union((int) cX - border, (int) cY - border,
|
||||
(int) cX + border, (int) cY + border);
|
||||
|
||||
mX = x;
|
||||
mY = y;
|
||||
}
|
||||
|
||||
mPointBuffer.add(new GesturePoint(x, y, event.getEventTime()));
|
||||
mStrokeBuffer.add(new GesturePoint(x, y, event.getEventTime()));
|
||||
|
||||
// pass the event to handlers
|
||||
final ArrayList<OnGestureListener> listeners = mOnGestureListeners;
|
||||
@ -430,24 +527,48 @@ public class GestureOverlayView extends View {
|
||||
for (int i = 0; i < count; i++) {
|
||||
listeners.get(i).onGesture(this, event);
|
||||
}
|
||||
|
||||
|
||||
if (mHandleGestureActions && !mIsGesturing) {
|
||||
mTotalLength += (float) Math.sqrt(dx * dx + dy * dy);
|
||||
|
||||
if (mTotalLength > mGestureStrokeLengthThreshold) {
|
||||
final OrientedBoundingBox box =
|
||||
GestureUtilities.computeOrientedBoundingBox(mStrokeBuffer);
|
||||
|
||||
float angle = Math.abs(box.orientation);
|
||||
if (angle > 90) {
|
||||
angle = 180 - angle;
|
||||
}
|
||||
|
||||
if (box.squareness > mGestureStrokeSquarenessTreshold ||
|
||||
angle < mGestureStrokeAngleThreshold) {
|
||||
|
||||
mIsGesturing = true;
|
||||
setCurrentColor(mCertainGestureColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return areaToRefresh;
|
||||
}
|
||||
|
||||
private void touchUp(MotionEvent event, boolean cancel) {
|
||||
// add the stroke to the current gesture
|
||||
mCurrentGesture.addStroke(new GestureStroke(mPointBuffer));
|
||||
mIsListeningForGestures = false;
|
||||
|
||||
// add the stroke to the double buffer
|
||||
mBitmapCanvas.drawPath(mPath, mGesturePaint);
|
||||
// add the stroke to the current gesture
|
||||
mCurrentGesture.addStroke(new GestureStroke(mStrokeBuffer));
|
||||
|
||||
if (!cancel) {
|
||||
// pass the event to handlers
|
||||
final ArrayList<OnGestureListener> listeners = mOnGestureListeners;
|
||||
final int count = listeners.size();
|
||||
int count = listeners.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
listeners.get(i).onGestureEnded(this, event);
|
||||
}
|
||||
|
||||
if (mHandleGestureActions) {
|
||||
clear(true, mIsGesturing);
|
||||
}
|
||||
} else {
|
||||
// pass the event to handlers
|
||||
final ArrayList<OnGestureListener> listeners = mOnGestureListeners;
|
||||
@ -455,15 +576,52 @@ public class GestureOverlayView extends View {
|
||||
for (int i = 0; i < count; i++) {
|
||||
listeners.get(i).onGestureCancelled(this, event);
|
||||
}
|
||||
|
||||
clear(false);
|
||||
}
|
||||
|
||||
mPath.rewind();
|
||||
mPointBuffer.clear();
|
||||
mIsGesturing = false;
|
||||
mStrokeBuffer.clear();
|
||||
}
|
||||
|
||||
private class FadeOutRunnable implements Runnable {
|
||||
boolean fireActionPerformed;
|
||||
|
||||
public void run() {
|
||||
if (mIsFadingOut) {
|
||||
final long now = AnimationUtils.currentAnimationTimeMillis();
|
||||
final long duration = now - mFadingStart;
|
||||
|
||||
if (duration > mFadeDuration) {
|
||||
if (fireActionPerformed) {
|
||||
final ArrayList<OnGesturePerformedListener> actionListeners =
|
||||
mOnGesturePerformedListeners;
|
||||
final int count = actionListeners.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
actionListeners.get(i).onGesturePerformed(GestureOverlayView.this,
|
||||
mCurrentGesture);
|
||||
}
|
||||
}
|
||||
|
||||
mIsFadingOut = false;
|
||||
mFadingHasStarted = false;
|
||||
mPath.rewind();
|
||||
mCurrentGesture = null;
|
||||
setPaintAlpha(255);
|
||||
} else {
|
||||
mFadingHasStarted = true;
|
||||
float interpolatedTime = Math.max(0.0f,
|
||||
Math.min(1.0f, duration / (float) mFadeDuration));
|
||||
mFadingAlpha = 1.0f - mInterpolator.getInterpolation(interpolatedTime);
|
||||
setPaintAlpha((int) (255 * mFadingAlpha));
|
||||
postDelayed(this, FADE_ANIMATION_RATE);
|
||||
}
|
||||
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An interface for processing gesture events
|
||||
*/
|
||||
public static interface OnGestureListener {
|
||||
void onGestureStarted(GestureOverlayView overlay, MotionEvent event);
|
||||
|
||||
@ -473,4 +631,8 @@ public class GestureOverlayView extends View {
|
||||
|
||||
void onGestureCancelled(GestureOverlayView overlay, MotionEvent event);
|
||||
}
|
||||
|
||||
public static interface OnGesturePerformedListener {
|
||||
void onGesturePerformed(GestureOverlayView overlay, Gesture gesture);
|
||||
}
|
||||
}
|
||||
|
@ -89,39 +89,51 @@ public class GestureStroke {
|
||||
*/
|
||||
void draw(Canvas canvas, Paint paint) {
|
||||
if (mCachedPath == null) {
|
||||
final float[] localPoints = points;
|
||||
final int count = localPoints.length;
|
||||
|
||||
Path path = null;
|
||||
|
||||
float mX = 0;
|
||||
float mY = 0;
|
||||
|
||||
for (int i = 0; i < count; i += 2) {
|
||||
float x = localPoints[i];
|
||||
float y = localPoints[i + 1];
|
||||
if (path == null) {
|
||||
path = new Path();
|
||||
path.moveTo(x, y);
|
||||
mX = x;
|
||||
mY = y;
|
||||
} else {
|
||||
float dx = Math.abs(x - mX);
|
||||
float dy = Math.abs(y - mY);
|
||||
if (dx >= 3 || dy >= 3) {
|
||||
path.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
|
||||
mX = x;
|
||||
mY = y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mCachedPath = path;
|
||||
makePath();
|
||||
}
|
||||
|
||||
canvas.drawPath(mCachedPath, paint);
|
||||
}
|
||||
|
||||
public Path getPath() {
|
||||
if (mCachedPath == null) {
|
||||
makePath();
|
||||
}
|
||||
|
||||
return mCachedPath;
|
||||
}
|
||||
|
||||
private void makePath() {
|
||||
final float[] localPoints = points;
|
||||
final int count = localPoints.length;
|
||||
|
||||
Path path = null;
|
||||
|
||||
float mX = 0;
|
||||
float mY = 0;
|
||||
|
||||
for (int i = 0; i < count; i += 2) {
|
||||
float x = localPoints[i];
|
||||
float y = localPoints[i + 1];
|
||||
if (path == null) {
|
||||
path = new Path();
|
||||
path.moveTo(x, y);
|
||||
mX = x;
|
||||
mY = y;
|
||||
} else {
|
||||
float dx = Math.abs(x - mX);
|
||||
float dy = Math.abs(y - mY);
|
||||
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
|
||||
path.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
|
||||
mX = x;
|
||||
mY = y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mCachedPath = path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the stroke to a Path based on the number of points
|
||||
*
|
||||
@ -158,8 +170,7 @@ public class GestureStroke {
|
||||
} else {
|
||||
float dx = Math.abs(x - mX);
|
||||
float dy = Math.abs(y - mY);
|
||||
if (dx >= TOUCH_TOLERANCE ||
|
||||
dy >= TOUCH_TOLERANCE) {
|
||||
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
|
||||
path.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
|
||||
mX = x;
|
||||
mY = y;
|
||||
|
@ -388,7 +388,7 @@ final class GestureUtilities {
|
||||
} else { // -PI<alpha<PI
|
||||
angle = (float) Math.atan2(targetVector[1], targetVector[0]);
|
||||
angle = (float) (180 * angle / Math.PI);
|
||||
android.graphics.Matrix trans = new android.graphics.Matrix();
|
||||
Matrix trans = new Matrix();
|
||||
trans.setRotate(-angle);
|
||||
trans.mapPoints(points);
|
||||
}
|
||||
|
@ -1,178 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2008-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.
|
||||
*/
|
||||
|
||||
package android.gesture;
|
||||
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
/**
|
||||
* TouchThroughGesturing implements the interaction behavior that allows a user
|
||||
* to gesture over a regular UI widget such as ListView and at the same time,
|
||||
* still allows a user to perform basic interactions (clicking, scrolling and panning)
|
||||
* with the underlying widget.
|
||||
*/
|
||||
public class TouchThroughGestureListener implements GestureOverlayView.OnGestureListener {
|
||||
public static final int SINGLE_STROKE = 0;
|
||||
public static final int MULTIPLE_STROKE = 1;
|
||||
|
||||
// TODO: Add properties for all these
|
||||
private static final float STROKE_LENGTH_THRESHOLD = 30;
|
||||
private static final float SQUARENESS_THRESHOLD = 0.275f;
|
||||
private static final float ANGLE_THRESHOLD = 40;
|
||||
|
||||
private boolean mIsGesturing = false;
|
||||
|
||||
private float mTotalLength;
|
||||
|
||||
private float mX;
|
||||
private float mY;
|
||||
|
||||
private WeakReference<View> mModel;
|
||||
|
||||
private int mGestureType = SINGLE_STROKE;
|
||||
|
||||
// TODO: Use WeakReferences
|
||||
private final ArrayList<OnGesturePerformedListener> mPerformedListeners =
|
||||
new ArrayList<OnGesturePerformedListener>();
|
||||
|
||||
private boolean mStealEvents = false;
|
||||
|
||||
public TouchThroughGestureListener(View model) {
|
||||
this(model, true);
|
||||
}
|
||||
|
||||
public TouchThroughGestureListener(View model, boolean stealEvents) {
|
||||
mModel = new WeakReference<View>(model);
|
||||
mStealEvents = stealEvents;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param type SINGLE_STROKE or MULTIPLE_STROKE
|
||||
*/
|
||||
public void setGestureType(int type) {
|
||||
mGestureType = type;
|
||||
}
|
||||
|
||||
public void onGestureStarted(GestureOverlayView overlay, MotionEvent event) {
|
||||
if (mGestureType == MULTIPLE_STROKE) {
|
||||
overlay.cancelFadingOut();
|
||||
}
|
||||
|
||||
mX = event.getX();
|
||||
mY = event.getY();
|
||||
mTotalLength = 0;
|
||||
mIsGesturing = false;
|
||||
|
||||
if (mGestureType == SINGLE_STROKE || overlay.getCurrentGesture() == null
|
||||
|| overlay.getCurrentGesture().getStrokesCount() == 0) {
|
||||
overlay.setGestureDrawingColor(overlay.getUncertainGestureColor());
|
||||
}
|
||||
|
||||
dispatchEventToModel(event);
|
||||
}
|
||||
|
||||
private void dispatchEventToModel(MotionEvent event) {
|
||||
View v = mModel.get();
|
||||
if (v != null) v.dispatchTouchEvent(event);
|
||||
}
|
||||
|
||||
public void onGesture(GestureOverlayView overlay, MotionEvent event) {
|
||||
//noinspection PointlessBooleanExpression
|
||||
if (!mStealEvents) {
|
||||
dispatchEventToModel(event);
|
||||
}
|
||||
|
||||
if (mIsGesturing) {
|
||||
return;
|
||||
}
|
||||
|
||||
final float x = event.getX();
|
||||
final float y = event.getY();
|
||||
final float dx = x - mX;
|
||||
final float dy = y - mY;
|
||||
|
||||
mTotalLength += (float) Math.sqrt(dx * dx + dy * dy);
|
||||
mX = x;
|
||||
mY = y;
|
||||
|
||||
if (mTotalLength > STROKE_LENGTH_THRESHOLD) {
|
||||
final OrientedBoundingBox box =
|
||||
GestureUtilities.computeOrientedBoundingBox(overlay.getCurrentStroke());
|
||||
float angle = Math.abs(box.orientation);
|
||||
if (angle > 90) {
|
||||
angle = 180 - angle;
|
||||
}
|
||||
if (box.squareness > SQUARENESS_THRESHOLD || angle < ANGLE_THRESHOLD) {
|
||||
mIsGesturing = true;
|
||||
overlay.setGestureDrawingColor(overlay.getGestureColor());
|
||||
if (mStealEvents) {
|
||||
event = MotionEvent.obtain(event.getDownTime(), System.currentTimeMillis(),
|
||||
MotionEvent.ACTION_CANCEL, x, y, event.getPressure(), event.getSize(),
|
||||
event.getMetaState(), event.getXPrecision(), event.getYPrecision(),
|
||||
event.getDeviceId(), event.getEdgeFlags());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mStealEvents) {
|
||||
dispatchEventToModel(event);
|
||||
}
|
||||
}
|
||||
|
||||
public void onGestureEnded(GestureOverlayView overlay, MotionEvent event) {
|
||||
if (mIsGesturing) {
|
||||
overlay.clear(true);
|
||||
|
||||
final ArrayList<OnGesturePerformedListener> listeners = mPerformedListeners;
|
||||
final int count = listeners.size();
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
listeners.get(i).onGesturePerformed(overlay, overlay.getCurrentGesture());
|
||||
}
|
||||
} else {
|
||||
dispatchEventToModel(event);
|
||||
overlay.clear(false);
|
||||
}
|
||||
}
|
||||
|
||||
public void onGestureCancelled(GestureOverlayView overlay, MotionEvent event) {
|
||||
overlay.clear(mIsGesturing);
|
||||
if (!mIsGesturing) {
|
||||
dispatchEventToModel(event);
|
||||
}
|
||||
}
|
||||
|
||||
public void addOnGestureActionListener(OnGesturePerformedListener listener) {
|
||||
mPerformedListeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeOnGestureActionListener(OnGesturePerformedListener listener) {
|
||||
mPerformedListeners.remove(listener);
|
||||
}
|
||||
|
||||
public boolean isGesturing() {
|
||||
return mIsGesturing;
|
||||
}
|
||||
|
||||
public static interface OnGesturePerformedListener {
|
||||
public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture);
|
||||
}
|
||||
}
|
@ -49,7 +49,6 @@ 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;
|
||||
@ -472,7 +471,6 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
||||
private ViewTreeObserver.OnGlobalLayoutListener mGesturesLayoutListener;
|
||||
private boolean mGlobalLayoutListenerAddedGestures;
|
||||
private boolean mInstallGesturesOverlay;
|
||||
private TouchThroughGestureListener mGesturesListener;
|
||||
private boolean mPreviousGesturing;
|
||||
|
||||
private boolean mGlobalLayoutListenerAddedFilter;
|
||||
@ -736,10 +734,8 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
||||
mGesturesPopup = p;
|
||||
|
||||
mGesturesOverlay.removeAllOnGestureListeners();
|
||||
mGesturesListener = new TouchThroughGestureListener(null);
|
||||
mGesturesListener.setGestureType(TouchThroughGestureListener.MULTIPLE_STROKE);
|
||||
mGesturesListener.addOnGestureActionListener(new GesturesProcessor());
|
||||
mGesturesOverlay.addOnGestureListener(mGesturesListener);
|
||||
mGesturesOverlay.setGestureStrokeType(GestureOverlayView.GESTURE_STROKE_TYPE_MULTIPLE);
|
||||
mGesturesOverlay.addOnGesturePerformedListener(new GesturesProcessor());
|
||||
|
||||
mPreviousGesturing = false;
|
||||
}
|
||||
@ -756,19 +752,23 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
||||
@Override
|
||||
public boolean dispatchTouchEvent(MotionEvent ev) {
|
||||
if (mGestures != GESTURES_NONE) {
|
||||
mGesturesOverlay.processEvent(ev);
|
||||
if (ev.getAction() != MotionEvent.ACTION_DOWN || mFastScroller == null ||
|
||||
!mFastScroller.isPointInside(ev.getX(), ev.getY())) {
|
||||
|
||||
final boolean isGesturing = mGesturesListener.isGesturing();
|
||||
mGesturesOverlay.dispatchTouchEvent(ev);
|
||||
|
||||
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;
|
||||
final boolean isGesturing = mGesturesOverlay.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2130,13 +2130,13 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent ev) {
|
||||
|
||||
if (mFastScroller != null) {
|
||||
boolean intercepted = mFastScroller.onTouchEvent(ev);
|
||||
if (intercepted) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
final int action = ev.getAction();
|
||||
final int x = (int) ev.getX();
|
||||
final int y = (int) ev.getY();
|
||||
@ -3848,8 +3848,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
||||
}
|
||||
}
|
||||
|
||||
private class GesturesProcessor implements
|
||||
TouchThroughGestureListener.OnGesturePerformedListener {
|
||||
private class GesturesProcessor implements GestureOverlayView.OnGesturePerformedListener {
|
||||
|
||||
private static final double SCORE_THRESHOLD = 0.1;
|
||||
|
||||
|
@ -402,8 +402,7 @@ class FastScroller {
|
||||
|
||||
boolean onInterceptTouchEvent(MotionEvent ev) {
|
||||
if (mState > STATE_NONE && ev.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
if (ev.getX() > mList.getWidth() - mThumbW && ev.getY() >= mThumbY &&
|
||||
ev.getY() <= mThumbY + mThumbH) {
|
||||
if (isPointInside(ev.getX(), ev.getY())) {
|
||||
setState(STATE_DRAGGING);
|
||||
return true;
|
||||
}
|
||||
@ -415,11 +414,11 @@ class FastScroller {
|
||||
if (mState == STATE_NONE) {
|
||||
return false;
|
||||
}
|
||||
if (me.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
if (me.getX() > mList.getWidth() - mThumbW
|
||||
&& me.getY() >= mThumbY
|
||||
&& me.getY() <= mThumbY + mThumbH) {
|
||||
|
||||
|
||||
final int action = me.getAction();
|
||||
|
||||
if (action == MotionEvent.ACTION_DOWN) {
|
||||
if (isPointInside(me.getX(), me.getY())) {
|
||||
setState(STATE_DRAGGING);
|
||||
if (mListAdapter == null && mList != null) {
|
||||
getSectionsFromIndexer();
|
||||
@ -428,7 +427,7 @@ class FastScroller {
|
||||
cancelFling();
|
||||
return true;
|
||||
}
|
||||
} else if (me.getAction() == MotionEvent.ACTION_UP) {
|
||||
} else if (action == MotionEvent.ACTION_UP) {
|
||||
if (mState == STATE_DRAGGING) {
|
||||
setState(STATE_VISIBLE);
|
||||
final Handler handler = mHandler;
|
||||
@ -436,7 +435,7 @@ class FastScroller {
|
||||
handler.postDelayed(mScrollFade, 1000);
|
||||
return true;
|
||||
}
|
||||
} else if (me.getAction() == MotionEvent.ACTION_MOVE) {
|
||||
} else if (action == MotionEvent.ACTION_MOVE) {
|
||||
if (mState == STATE_DRAGGING) {
|
||||
final int viewHeight = mList.getHeight();
|
||||
// Jitter
|
||||
@ -460,6 +459,10 @@ class FastScroller {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean isPointInside(float x, float y) {
|
||||
return x > mList.getWidth() - mThumbW && y >= mThumbY && y <= mThumbY + mThumbH;
|
||||
}
|
||||
|
||||
public class ScrollFade implements Runnable {
|
||||
|
||||
long mStartTime;
|
||||
|
@ -353,25 +353,24 @@ public class FrameLayout extends ViewGroup {
|
||||
|
||||
if (mForeground != null) {
|
||||
final Drawable foreground = mForeground;
|
||||
|
||||
if (mForegroundBoundsChanged) {
|
||||
mForegroundBoundsChanged = false;
|
||||
if (foreground != null) {
|
||||
final Rect selfBounds = mSelfBounds;
|
||||
final Rect overlayBounds = mOverlayBounds;
|
||||
final Rect selfBounds = mSelfBounds;
|
||||
final Rect overlayBounds = mOverlayBounds;
|
||||
|
||||
final int w = mRight-mLeft;
|
||||
final int h = mBottom-mTop;
|
||||
|
||||
if (mForegroundInPadding) {
|
||||
selfBounds.set(0, 0, w, h);
|
||||
} else {
|
||||
selfBounds.set(mPaddingLeft, mPaddingTop, w - mPaddingRight, h - mPaddingBottom);
|
||||
}
|
||||
final int w = mRight-mLeft;
|
||||
final int h = mBottom-mTop;
|
||||
|
||||
Gravity.apply(mForegroundGravity, foreground.getIntrinsicWidth(),
|
||||
foreground.getIntrinsicHeight(), selfBounds, overlayBounds);
|
||||
foreground.setBounds(overlayBounds);
|
||||
if (mForegroundInPadding) {
|
||||
selfBounds.set(0, 0, w, h);
|
||||
} else {
|
||||
selfBounds.set(mPaddingLeft, mPaddingTop, w - mPaddingRight, h - mPaddingBottom);
|
||||
}
|
||||
|
||||
Gravity.apply(mForegroundGravity, foreground.getIntrinsicWidth(),
|
||||
foreground.getIntrinsicHeight(), selfBounds, overlayBounds);
|
||||
foreground.setBounds(overlayBounds);
|
||||
}
|
||||
|
||||
foreground.draw(canvas);
|
||||
|
@ -2091,6 +2091,22 @@
|
||||
<!-- Duration, in milliseconds, of the fade out effect after the user is done
|
||||
drawing a gesture. -->
|
||||
<attr name="fadeDuration" format="integer" />
|
||||
<!-- Defines the type of strokes that define a gesture. -->
|
||||
<attr name="gestureStrokeType">
|
||||
<!-- A gesture is made of only one stroke. -->
|
||||
<enum name="single" value="0" />
|
||||
<!-- A gesture is made of multiple strokes. -->
|
||||
<enum name="multiple" value="1" />
|
||||
</attr>
|
||||
<!-- Minimum length of a stroke before it is recognized as a gesture. -->
|
||||
<attr name="gestureStrokeLengthThreshold" format="float" />
|
||||
<!-- Squareness threshold of a stroke before it is recognized as a gesture. -->
|
||||
<attr name="gestureStrokeSquarenessThreshold" format="float" />
|
||||
<!-- Minimum curve angle a stroke must contain before it is recognized as a gesture. -->
|
||||
<attr name="gestureStrokeAngleThreshold" format="float" />
|
||||
<!-- Defines whether the overlay should intercept the motion events when a gesture
|
||||
is recognized. -->
|
||||
<attr name="eventsInterceptionEnabled" format="boolean" />
|
||||
</declare-styleable>
|
||||
|
||||
<!-- ======================================= -->
|
||||
|
@ -1107,6 +1107,11 @@
|
||||
<public type="attr" name="fadeOffset" />
|
||||
<public type="attr" name="fadeDuration" />
|
||||
<public type="attr" name="gestures" />
|
||||
<public type="attr" name="gestureStrokeType" />
|
||||
<public type="attr" name="gestureStrokeLengthThreshold" />
|
||||
<public type="attr" name="gestureStrokeSquarenessThreshold" />
|
||||
<public type="attr" name="gestureStrokeAngleThreshold" />
|
||||
<public type="attr" name="eventsInterceptionEnabled" />
|
||||
|
||||
<public-padding type="attr" name="donut_resource_pad" end="0x0101029f" />
|
||||
|
||||
|
@ -174,14 +174,18 @@
|
||||
<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>
|
||||
<item name="android:uncertainGestureColor">#48ffff00</item>
|
||||
<item name="android:fadeOffset">420</item>
|
||||
<item name="android:fadeDuration">150</item>
|
||||
<item name="android:gestureStrokeLengthThreshold">30.0</item>
|
||||
<item name="android:gestureStrokeSquarenessThreshold">0.275</item>
|
||||
<item name="android:gestureStrokeAngleThreshold">40.0</item>
|
||||
<item name="android:eventsInterceptionEnabled">true</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.GestureOverlayView.White">
|
||||
<item name="android:gestureColor">#ff00ff00</item>
|
||||
<item name="android:uncertainGestureColor">#3c00ff00</item>
|
||||
<item name="android:uncertainGestureColor">#4800ff00</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.Button">
|
||||
|
@ -17,7 +17,8 @@
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content">
|
||||
android:layout_height="fill_parent">
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/spinner"
|
||||
android:layout_width="fill_parent"
|
||||
@ -29,6 +30,6 @@
|
||||
android:id="@+id/drawingpad"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"/>
|
||||
android:layout_weight="1" />
|
||||
|
||||
</LinearLayout>
|
||||
|
@ -17,7 +17,7 @@
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content">
|
||||
android:layout_height="fill_parent">
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/spinner"
|
||||
@ -30,7 +30,7 @@
|
||||
android:id="@+id/drawingpad"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"/>
|
||||
android:layout_weight="1" />
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
|
@ -14,7 +14,14 @@
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/list"
|
||||
<android.gesture.GestureOverlayView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/overlay"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent" />
|
||||
android:layout_height="fill_parent">
|
||||
|
||||
<ListView
|
||||
android:id="@+id/list"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent" />
|
||||
|
||||
</android.gesture.GestureOverlayView>
|
||||
|
@ -25,7 +25,6 @@ import android.os.Bundle;
|
||||
import android.provider.Contacts.People;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ListView;
|
||||
@ -34,16 +33,12 @@ import android.gesture.Gesture;
|
||||
import android.gesture.GestureOverlayView;
|
||||
import android.gesture.LetterRecognizer;
|
||||
import android.gesture.Prediction;
|
||||
import android.gesture.TouchThroughGestureListener;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class ContactListGestureOverlay extends Activity {
|
||||
|
||||
private static final String LOGTAG = "ContactListGestureOverlay";
|
||||
|
||||
private static final String LOG_TAG = "ContactListGestureOverlay";
|
||||
private static final String SORT_ORDER = People.DISPLAY_NAME + " COLLATE LOCALIZED ASC";
|
||||
|
||||
private static final String[] CONTACTS_PROJECTION = new String[] {
|
||||
People._ID, // 0
|
||||
People.DISPLAY_NAME, // 1
|
||||
@ -51,11 +46,9 @@ public class ContactListGestureOverlay extends Activity {
|
||||
|
||||
private ContactAdapter mContactAdapter;
|
||||
|
||||
private TouchThroughGestureListener mGestureProcessor;
|
||||
|
||||
private LetterRecognizer mRecognizer;
|
||||
|
||||
private ListView mContactList;
|
||||
private LetterRecognizer mRecognizer;
|
||||
private GestureOverlayView mOverlay;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
@ -63,10 +56,10 @@ public class ContactListGestureOverlay extends Activity {
|
||||
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
|
||||
setContentView(R.layout.overlaydemo);
|
||||
|
||||
setProgressBarIndeterminateVisibility(true);
|
||||
|
||||
// create a letter recognizer
|
||||
mRecognizer = LetterRecognizer.getLetterRecognizer(this, LetterRecognizer.RECOGNIZER_LATIN_LOWERCASE);
|
||||
mRecognizer = LetterRecognizer.getLetterRecognizer(this,
|
||||
LetterRecognizer.RECOGNIZER_LATIN_LOWERCASE);
|
||||
mOverlay = (GestureOverlayView) findViewById(R.id.overlay);
|
||||
|
||||
// load the contact list
|
||||
mContactList = (ListView) findViewById(R.id.list);
|
||||
@ -74,13 +67,14 @@ public class ContactListGestureOverlay extends Activity {
|
||||
mContactList.setTextFilterEnabled(true);
|
||||
mContactList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
|
||||
if (!mGestureProcessor.isGesturing()) {
|
||||
if (!mOverlay.isGesturing()) {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW, ContentUris.withAppendedId(
|
||||
People.CONTENT_URI, id));
|
||||
startActivity(intent);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
ContentResolver resolver = getContentResolver();
|
||||
Cursor cursor = resolver.query(People.CONTENT_URI, CONTACTS_PROJECTION, null, null,
|
||||
SORT_ORDER);
|
||||
@ -91,21 +85,16 @@ public class ContactListGestureOverlay extends Activity {
|
||||
mContactAdapter = new ContactAdapter(this, list);
|
||||
mContactList.setAdapter(mContactAdapter);
|
||||
|
||||
setProgressBarIndeterminateVisibility(false);
|
||||
|
||||
// add a gesture overlay on top of the ListView
|
||||
GestureOverlayView overlay = new GestureOverlayView(this);
|
||||
mGestureProcessor = new TouchThroughGestureListener(mContactList);
|
||||
mGestureProcessor.setGestureType(TouchThroughGestureListener.MULTIPLE_STROKE);
|
||||
mGestureProcessor.addOnGestureActionListener(new TouchThroughGestureListener.OnGesturePerformedListener() {
|
||||
mOverlay.setGestureStrokeType(GestureOverlayView.GESTURE_STROKE_TYPE_MULTIPLE);
|
||||
mOverlay.addOnGesturePerformedListener(new GestureOverlayView.OnGesturePerformedListener() {
|
||||
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(LOG_TAG, "1st Prediction : " + predictions.get(0).name +
|
||||
" @" + predictions.get(0).score);
|
||||
Log.v(LOGTAG, "2nd Prediction : " + predictions.get(1).name +
|
||||
Log.v(LOG_TAG, "2nd Prediction : " + predictions.get(1).name +
|
||||
" @" + predictions.get(1).score);
|
||||
Log.v(LOGTAG, "3rd Prediction : " + predictions.get(2).name +
|
||||
Log.v(LOG_TAG, "3rd Prediction : " + predictions.get(2).name +
|
||||
" @" + predictions.get(2).score);
|
||||
int index = mContactAdapter.search(predictions.get(0).name);
|
||||
if (index != -1) {
|
||||
@ -114,9 +103,5 @@ public class ContactListGestureOverlay extends Activity {
|
||||
}
|
||||
}
|
||||
});
|
||||
overlay.addOnGestureListener(mGestureProcessor);
|
||||
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(
|
||||
ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT);
|
||||
this.addContentView(overlay, params);
|
||||
}
|
||||
}
|
||||
|
@ -47,8 +47,9 @@ public class GestureEntry extends Activity {
|
||||
|
||||
private static final String PARCEL_KEY = "gesture";
|
||||
|
||||
static final String GESTURE_FILE_NAME = Environment.getExternalStorageDirectory().getAbsolutePath()
|
||||
+ File.separator + "demo_library.gestures";
|
||||
static final String GESTURE_FILE_NAME =
|
||||
Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator +
|
||||
"demo_library.gestures";
|
||||
|
||||
private static final int DIALOG_NEW_ENTRY = 1;
|
||||
|
||||
@ -82,7 +83,7 @@ public class GestureEntry extends Activity {
|
||||
// correct the recognition result by adding the new example
|
||||
if (!mChangedByRecognizer) {
|
||||
mGestureLibrary.addGesture(parent.getSelectedItem().toString(), mGesturePad
|
||||
.getCurrentGesture());
|
||||
.getGesture());
|
||||
} else {
|
||||
mChangedByRecognizer = false;
|
||||
}
|
||||
@ -99,7 +100,7 @@ public class GestureEntry extends Activity {
|
||||
mGesturePad.setBackgroundColor(Color.BLACK);
|
||||
mGesturePad.addOnGestureListener(new GestureOverlayView.OnGestureListener() {
|
||||
public void onGestureEnded(GestureOverlayView overlay, MotionEvent event) {
|
||||
recognize(overlay.getCurrentGesture());
|
||||
recognize(overlay.getGesture());
|
||||
}
|
||||
|
||||
public void onGesture(GestureOverlayView overlay, MotionEvent event) {
|
||||
@ -116,7 +117,7 @@ public class GestureEntry extends Activity {
|
||||
if (savedInstanceState != null) {
|
||||
Gesture gesture = (Gesture) savedInstanceState.getParcelable(PARCEL_KEY);
|
||||
if (gesture != null) {
|
||||
mGesturePad.setCurrentGesture(gesture);
|
||||
mGesturePad.setGesture(gesture);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -133,7 +134,7 @@ public class GestureEntry extends Activity {
|
||||
.findViewById(R.id.gesturename_edit);
|
||||
String text = edittext.getText().toString().trim();
|
||||
if (text.length() > 0) {
|
||||
mGestureLibrary.addGesture(text, mGesturePad.getCurrentGesture());
|
||||
mGestureLibrary.addGesture(text, mGesturePad.getGesture());
|
||||
}
|
||||
}
|
||||
}).setNegativeButton(R.string.newgesture_dialog_cancel,
|
||||
@ -157,7 +158,7 @@ public class GestureEntry extends Activity {
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case NEW_ID:
|
||||
if (mGesturePad.getCurrentGesture() != null) {
|
||||
if (mGesturePad.getGesture() != null) {
|
||||
showDialog(DIALOG_NEW_ENTRY);
|
||||
}
|
||||
break;
|
||||
@ -190,7 +191,7 @@ public class GestureEntry extends Activity {
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
Gesture gesture = mGesturePad.getCurrentGesture();
|
||||
Gesture gesture = mGesturePad.getGesture();
|
||||
if (gesture != null) {
|
||||
outState.putParcelable(PARCEL_KEY, gesture);
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ public class GestureLibViewer extends Activity {
|
||||
mCurrentGestureIndex--;
|
||||
}
|
||||
gesture = mGestures.get(mCurrentGestureIndex);
|
||||
mGesturePad.setCurrentGesture(gesture);
|
||||
mGesturePad.setGesture(gesture);
|
||||
mGesturePad.invalidate();
|
||||
}
|
||||
}
|
||||
@ -109,7 +109,7 @@ public class GestureLibViewer extends Activity {
|
||||
mGestures = mGesureLibrary.getGestures(list.get(0));
|
||||
mCurrentGestureIndex = 0;
|
||||
Gesture gesture = mGestures.get(mCurrentGestureIndex);
|
||||
mGesturePad.setCurrentGesture(gesture);
|
||||
mGesturePad.setGesture(gesture);
|
||||
}
|
||||
|
||||
mGestureCategory.setOnItemSelectedListener(new OnItemSelectedListener() {
|
||||
@ -118,7 +118,7 @@ public class GestureLibViewer extends Activity {
|
||||
if (!mGestures.isEmpty()) {
|
||||
mCurrentGestureIndex = 0;
|
||||
Gesture gesture = mGestures.get(mCurrentGestureIndex);
|
||||
mGesturePad.setCurrentGesture(gesture);
|
||||
mGesturePad.setGesture(gesture);
|
||||
}
|
||||
mGesturePad.invalidate();
|
||||
}
|
||||
@ -139,7 +139,7 @@ public class GestureLibViewer extends Activity {
|
||||
}
|
||||
mCurrentGestureIndex++;
|
||||
Gesture gesture = mGestures.get(mCurrentGestureIndex);
|
||||
mGesturePad.setCurrentGesture(gesture);
|
||||
mGesturePad.setGesture(gesture);
|
||||
mGesturePad.invalidate();
|
||||
}
|
||||
});
|
||||
@ -150,7 +150,7 @@ public class GestureLibViewer extends Activity {
|
||||
if (mCurrentGestureIndex >= 1 && !mGestures.isEmpty()) {
|
||||
mCurrentGestureIndex--;
|
||||
Gesture gesture = mGestures.get(mCurrentGestureIndex);
|
||||
mGesturePad.setCurrentGesture(gesture);
|
||||
mGesturePad.setGesture(gesture);
|
||||
mGesturePad.invalidate();
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user