MotionEventCompat.java revision e350edbd81af058201ac1b5dbe6631dafaffdadb
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
17package android.support.v4.view;
18
19import 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 */
25public class MotionEventCompat {
26    /**
27     * Interface for the full API.
28     */
29    interface MotionEventVersionImpl {
30        public int findPointerIndex(MotionEvent event, int pointerId);
31        public int getPointerId(MotionEvent event, int pointerIndex);
32        public float getX(MotionEvent event, int pointerIndex);
33        public float getY(MotionEvent event, int pointerIndex);
34    }
35
36    /**
37     * Interface implementation that doesn't use anything about v4 APIs.
38     */
39    static class BaseMotionEventVersionImpl implements MotionEventVersionImpl {
40        @Override
41        public int findPointerIndex(MotionEvent event, int pointerId) {
42            if (pointerId == 0) {
43                // id 0 == index 0 and vice versa.
44                return 0;
45            }
46            return -1;
47        }
48        @Override
49        public int getPointerId(MotionEvent event, int pointerIndex) {
50            if (pointerIndex == 0) {
51                // index 0 == id 0 and vice versa.
52                return 0;
53            }
54            throw new IndexOutOfBoundsException("Pre-Eclair does not support multiple pointers");
55        }
56        @Override
57        public float getX(MotionEvent event, int pointerIndex) {
58            if (pointerIndex == 0) {
59                return event.getX();
60            }
61            throw new IndexOutOfBoundsException("Pre-Eclair does not support multiple pointers");
62        }
63        @Override
64        public float getY(MotionEvent event, int pointerIndex) {
65            if (pointerIndex == 0) {
66                return event.getY();
67            }
68            throw new IndexOutOfBoundsException("Pre-Eclair does not support multiple pointers");
69        }
70    }
71
72    /**
73     * Interface implementation for devices with at least v11 APIs.
74     */
75    static class EclairMotionEventVersionImpl implements MotionEventVersionImpl {
76        @Override
77        public int findPointerIndex(MotionEvent event, int pointerId) {
78            return MotionEventCompatEclair.findPointerIndex(event, pointerId);
79        }
80        @Override
81        public int getPointerId(MotionEvent event, int pointerIndex) {
82            return MotionEventCompatEclair.getPointerId(event, pointerIndex);
83        }
84        @Override
85        public float getX(MotionEvent event, int pointerIndex) {
86            return MotionEventCompatEclair.getX(event, pointerIndex);
87        }
88        @Override
89        public float getY(MotionEvent event, int pointerIndex) {
90            return MotionEventCompatEclair.getY(event, pointerIndex);
91        }
92    }
93
94    /**
95     * Select the correct implementation to use for the current platform.
96     */
97    static final MotionEventVersionImpl IMPL;
98    static {
99        if (android.os.Build.VERSION.SDK_INT >= 5) {
100            IMPL = new EclairMotionEventVersionImpl();
101        } else {
102            IMPL = new BaseMotionEventVersionImpl();
103        }
104    }
105
106    // -------------------------------------------------------------------
107
108    /**
109     * Synonym for {@link MotionEvent#ACTION_MASK}.
110     */
111    public static final int ACTION_MASK = 0xff;
112
113    /**
114     * Synonym for {@link MotionEvent#ACTION_POINTER_DOWN}.
115     */
116    public static final int ACTION_POINTER_DOWN = 5;
117
118    /**
119     * Synonym for {@link MotionEvent#ACTION_POINTER_UP}.
120     */
121    public static final int ACTION_POINTER_UP = 6;
122
123    /**
124     * Synonym for {@link MotionEvent#ACTION_HOVER_MOVE}.
125     */
126    public static final int ACTION_HOVER_MOVE = 7;
127
128    /**
129     * Synonym for {@link MotionEvent#ACTION_SCROLL}.
130     */
131    public static final int ACTION_SCROLL = 8;
132
133    /**
134     * Synonym for {@link MotionEvent#ACTION_POINTER_INDEX_MASK}.
135     */
136    public static final int ACTION_POINTER_INDEX_MASK  = 0xff00;
137
138    /**
139     * Synonym for {@link MotionEvent#ACTION_POINTER_INDEX_SHIFT}.
140     */
141    public static final int ACTION_POINTER_INDEX_SHIFT = 8;
142
143    /**
144     * Constant for {@link #getActionMasked}: The pointer is not down but has entered the
145     * boundaries of a window or view.
146     * <p>
147     * This action is always delivered to the window or view under the pointer.
148     * </p><p>
149     * This action is not a touch event so it is delivered to
150     * {@link android.view.View#onGenericMotionEvent(MotionEvent)} rather than
151     * {@link android.view.View#onTouchEvent(MotionEvent)}.
152     * </p>
153     */
154    public static final int ACTION_HOVER_ENTER = 9;
155
156    /**
157     * Constant for {@link #getActionMasked}: The pointer is not down but has exited the
158     * boundaries of a window or view.
159     * <p>
160     * This action is always delivered to the window or view that was previously under the pointer.
161     * </p><p>
162     * This action is not a touch event so it is delivered to
163     * {@link android.view.View#onGenericMotionEvent(MotionEvent)} rather than
164     * {@link android.view.View#onTouchEvent(MotionEvent)}.
165     * </p>
166     */
167    public static final int ACTION_HOVER_EXIT = 10;
168
169    /**
170     * Call {@link MotionEvent#getAction}, returning only the {@link #ACTION_MASK}
171     * portion.
172     */
173    public static int getActionMasked(MotionEvent event) {
174        return event.getAction() & ACTION_MASK;
175    }
176
177    /**
178     * Call {@link MotionEvent#getAction}, returning only the pointer index
179     * portion
180     */
181    public static int getActionIndex(MotionEvent event) {
182        return (event.getAction() & ACTION_POINTER_INDEX_MASK)
183                >> ACTION_POINTER_INDEX_SHIFT;
184    }
185
186    /**
187     * Call {@link MotionEvent#findPointerIndex(int)}.
188     * If running on a pre-{@link android.os.Build.VERSION_CODES#ECLAIR} device,
189     * does nothing and returns -1.
190     */
191    public static int findPointerIndex(MotionEvent event, int pointerId) {
192        return IMPL.findPointerIndex(event, pointerId);
193    }
194
195    /**
196     * Call {@link MotionEvent#getPointerId(int)}.
197     * If running on a pre-{@link android.os.Build.VERSION_CODES#ECLAIR} device,
198     * {@link IndexOutOfBoundsException} is thrown.
199     */
200    public static int getPointerId(MotionEvent event, int pointerIndex) {
201        return IMPL.getPointerId(event, pointerIndex);
202    }
203
204    /**
205     * Call {@link MotionEvent#getX(int)}.
206     * If running on a pre-{@link android.os.Build.VERSION_CODES#ECLAIR} device,
207     * {@link IndexOutOfBoundsException} is thrown.
208     */
209    public static float getX(MotionEvent event, int pointerIndex) {
210        return IMPL.getX(event, pointerIndex);
211    }
212
213    /**
214     * Call {@link MotionEvent#getY(int)}.
215     * If running on a pre-{@link android.os.Build.VERSION_CODES#ECLAIR} device,
216     * {@link IndexOutOfBoundsException} is thrown.
217     */
218    public static float getY(MotionEvent event, int pointerIndex) {
219        return IMPL.getY(event, pointerIndex);
220    }
221}
222