• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.support.v4.view;
18 
19 import android.view.MotionEvent;
20 
21 /**
22  * Helper for accessing features in {@link MotionEvent} introduced
23  * after API level 4 in a backwards compatible fashion.
24  */
25 public class MotionEventCompat {
26     /**
27      * Interface for the full API.
28      */
29     interface MotionEventVersionImpl {
findPointerIndex(MotionEvent event, int pointerId)30         public int findPointerIndex(MotionEvent event, int pointerId);
getPointerId(MotionEvent event, int pointerIndex)31         public int getPointerId(MotionEvent event, int pointerIndex);
getX(MotionEvent event, int pointerIndex)32         public float getX(MotionEvent event, int pointerIndex);
getY(MotionEvent event, int pointerIndex)33         public float getY(MotionEvent event, int pointerIndex);
getPointerCount(MotionEvent event)34         public int getPointerCount(MotionEvent event);
35     }
36 
37     /**
38      * Interface implementation that doesn't use anything about v4 APIs.
39      */
40     static class BaseMotionEventVersionImpl implements MotionEventVersionImpl {
41         @Override
findPointerIndex(MotionEvent event, int pointerId)42         public int findPointerIndex(MotionEvent event, int pointerId) {
43             if (pointerId == 0) {
44                 // id 0 == index 0 and vice versa.
45                 return 0;
46             }
47             return -1;
48         }
49         @Override
getPointerId(MotionEvent event, int pointerIndex)50         public int getPointerId(MotionEvent event, int pointerIndex) {
51             if (pointerIndex == 0) {
52                 // index 0 == id 0 and vice versa.
53                 return 0;
54             }
55             throw new IndexOutOfBoundsException("Pre-Eclair does not support multiple pointers");
56         }
57         @Override
getX(MotionEvent event, int pointerIndex)58         public float getX(MotionEvent event, int pointerIndex) {
59             if (pointerIndex == 0) {
60                 return event.getX();
61             }
62             throw new IndexOutOfBoundsException("Pre-Eclair does not support multiple pointers");
63         }
64         @Override
getY(MotionEvent event, int pointerIndex)65         public float getY(MotionEvent event, int pointerIndex) {
66             if (pointerIndex == 0) {
67                 return event.getY();
68             }
69             throw new IndexOutOfBoundsException("Pre-Eclair does not support multiple pointers");
70         }
71         @Override
getPointerCount(MotionEvent event)72         public int getPointerCount(MotionEvent event) {
73             return 1;
74         }
75     }
76 
77     /**
78      * Interface implementation for devices with at least v11 APIs.
79      */
80     static class EclairMotionEventVersionImpl implements MotionEventVersionImpl {
81         @Override
findPointerIndex(MotionEvent event, int pointerId)82         public int findPointerIndex(MotionEvent event, int pointerId) {
83             return MotionEventCompatEclair.findPointerIndex(event, pointerId);
84         }
85         @Override
getPointerId(MotionEvent event, int pointerIndex)86         public int getPointerId(MotionEvent event, int pointerIndex) {
87             return MotionEventCompatEclair.getPointerId(event, pointerIndex);
88         }
89         @Override
getX(MotionEvent event, int pointerIndex)90         public float getX(MotionEvent event, int pointerIndex) {
91             return MotionEventCompatEclair.getX(event, pointerIndex);
92         }
93         @Override
getY(MotionEvent event, int pointerIndex)94         public float getY(MotionEvent event, int pointerIndex) {
95             return MotionEventCompatEclair.getY(event, pointerIndex);
96         }
97         @Override
getPointerCount(MotionEvent event)98         public int getPointerCount(MotionEvent event) {
99             return MotionEventCompatEclair.getPointerCount(event);
100         }
101     }
102 
103     /**
104      * Select the correct implementation to use for the current platform.
105      */
106     static final MotionEventVersionImpl IMPL;
107     static {
108         if (android.os.Build.VERSION.SDK_INT >= 5) {
109             IMPL = new EclairMotionEventVersionImpl();
110         } else {
111             IMPL = new BaseMotionEventVersionImpl();
112         }
113     }
114 
115     // -------------------------------------------------------------------
116 
117     /**
118      * Synonym for {@link MotionEvent#ACTION_MASK}.
119      */
120     public static final int ACTION_MASK = 0xff;
121 
122     /**
123      * Synonym for {@link MotionEvent#ACTION_POINTER_DOWN}.
124      */
125     public static final int ACTION_POINTER_DOWN = 5;
126 
127     /**
128      * Synonym for {@link MotionEvent#ACTION_POINTER_UP}.
129      */
130     public static final int ACTION_POINTER_UP = 6;
131 
132     /**
133      * Synonym for {@link MotionEvent#ACTION_HOVER_MOVE}.
134      */
135     public static final int ACTION_HOVER_MOVE = 7;
136 
137     /**
138      * Synonym for {@link MotionEvent#ACTION_SCROLL}.
139      */
140     public static final int ACTION_SCROLL = 8;
141 
142     /**
143      * Synonym for {@link MotionEvent#ACTION_POINTER_INDEX_MASK}.
144      */
145     public static final int ACTION_POINTER_INDEX_MASK  = 0xff00;
146 
147     /**
148      * Synonym for {@link MotionEvent#ACTION_POINTER_INDEX_SHIFT}.
149      */
150     public static final int ACTION_POINTER_INDEX_SHIFT = 8;
151 
152     /**
153      * Constant for {@link #getActionMasked}: The pointer is not down but has entered the
154      * boundaries of a window or view.
155      * <p>
156      * This action is always delivered to the window or view under the pointer.
157      * </p><p>
158      * This action is not a touch event so it is delivered to
159      * {@link android.view.View#onGenericMotionEvent(MotionEvent)} rather than
160      * {@link android.view.View#onTouchEvent(MotionEvent)}.
161      * </p>
162      */
163     public static final int ACTION_HOVER_ENTER = 9;
164 
165     /**
166      * Constant for {@link #getActionMasked}: The pointer is not down but has exited the
167      * boundaries of a window or view.
168      * <p>
169      * This action is always delivered to the window or view that was previously under the pointer.
170      * </p><p>
171      * This action is not a touch event so it is delivered to
172      * {@link android.view.View#onGenericMotionEvent(MotionEvent)} rather than
173      * {@link android.view.View#onTouchEvent(MotionEvent)}.
174      * </p>
175      */
176     public static final int ACTION_HOVER_EXIT = 10;
177 
178     /**
179      * Call {@link MotionEvent#getAction}, returning only the {@link #ACTION_MASK}
180      * portion.
181      */
getActionMasked(MotionEvent event)182     public static int getActionMasked(MotionEvent event) {
183         return event.getAction() & ACTION_MASK;
184     }
185 
186     /**
187      * Call {@link MotionEvent#getAction}, returning only the pointer index
188      * portion
189      */
getActionIndex(MotionEvent event)190     public static int getActionIndex(MotionEvent event) {
191         return (event.getAction() & ACTION_POINTER_INDEX_MASK)
192                 >> ACTION_POINTER_INDEX_SHIFT;
193     }
194 
195     /**
196      * Call {@link MotionEvent#findPointerIndex(int)}.
197      * If running on a pre-{@link android.os.Build.VERSION_CODES#ECLAIR} device,
198      * does nothing and returns -1.
199      */
findPointerIndex(MotionEvent event, int pointerId)200     public static int findPointerIndex(MotionEvent event, int pointerId) {
201         return IMPL.findPointerIndex(event, pointerId);
202     }
203 
204     /**
205      * Call {@link MotionEvent#getPointerId(int)}.
206      * If running on a pre-{@link android.os.Build.VERSION_CODES#ECLAIR} device,
207      * {@link IndexOutOfBoundsException} is thrown.
208      */
getPointerId(MotionEvent event, int pointerIndex)209     public static int getPointerId(MotionEvent event, int pointerIndex) {
210         return IMPL.getPointerId(event, pointerIndex);
211     }
212 
213     /**
214      * Call {@link MotionEvent#getX(int)}.
215      * If running on a pre-{@link android.os.Build.VERSION_CODES#ECLAIR} device,
216      * {@link IndexOutOfBoundsException} is thrown.
217      */
getX(MotionEvent event, int pointerIndex)218     public static float getX(MotionEvent event, int pointerIndex) {
219         return IMPL.getX(event, pointerIndex);
220     }
221 
222     /**
223      * Call {@link MotionEvent#getY(int)}.
224      * If running on a pre-{@link android.os.Build.VERSION_CODES#ECLAIR} device,
225      * {@link IndexOutOfBoundsException} is thrown.
226      */
getY(MotionEvent event, int pointerIndex)227     public static float getY(MotionEvent event, int pointerIndex) {
228         return IMPL.getY(event, pointerIndex);
229     }
230 
231     /**
232      * The number of pointers of data contained in this event.  Always
233      * >= 1.
234      */
getPointerCount(MotionEvent event)235     public static int getPointerCount(MotionEvent event) {
236         return IMPL.getPointerCount(event);
237     }
238 }
239