1
+     * Interface definition for callback to be invoked when attached ImageView scale changes
1072
+     *
1073
+     * @author Marek Sebera
1074
+     */
1075
+    public interface OnScaleChangeListener {
1076
+        /**
1077
+         * Callback for when the scale changes
1078
+         *
1079
+         * @param scaleFactor the scale factor (less than 1 for zoom out, greater than 1 for zoom in)
1080
+         * @param focusX      focal point X position
1081
+         * @param focusY      focal point Y position
1082
+         */
1083
+        void onScaleChange(float scaleFactor, float focusX, float focusY);
1084
+    }
1085
+
1086
+    /**
1087
+     * Interface definition for a callback to be invoked when the Photo is tapped with a single
1088
+     * tap.
1089
+     *
1090
+     * @author Chris Banes
1091
+     */
1092
+    public interface OnPhotoTapListener {
1093
+
1094
+        /**
1095
+         * A callback to receive where the user taps on a photo. You will only receive a callback if
1096
+         * the user taps on the actual photo, tapping on 'whitespace' will be ignored.
1097
+         *
1098
+         * @param view - View the user tapped.
1099
+         * @param x    - where the user tapped from the of the Drawable, as percentage of the
1100
+         *             Drawable width.
1101
+         * @param y    - where the user tapped from the top of the Drawable, as percentage of the
1102
+         *             Drawable height.
1103
+         */
1104
+        void onPhotoTap(View view, float x, float y);
1105
+
1106
+        /**
1107
+         * A simple callback where out of photo happened;
1108
+         * */
1109
+        void onOutsidePhotoTap();
1110
+    }
1111
+
1112
+    /**
1113
+     * Interface definition for a callback to be invoked when the ImageView is tapped with a single
1114
+     * tap.
1115
+     *
1116
+     * @author Chris Banes
1117
+     */
1118
+    public interface OnViewTapListener {
1119
+
1120
+        /**
1121
+         * A callback to receive where the user taps on a ImageView. You will receive a callback if
1122
+         * the user taps anywhere on the view, tapping on 'whitespace' will not be ignored.
1123
+         *
1124
+         * @param view - View the user tapped.
1125
+         * @param x    - where the user tapped from the left of the View.
1126
+         * @param y    - where the user tapped from the top of the View.
1127
+         */
1128
+        void onViewTap(View view, float x, float y);
1129
+    }
1130
+
1131
+    /**
1132
+     * Interface definition for a callback to be invoked when the ImageView is roateted with two finger.
1133
+     *
1134
+     * @author ChenSL
1135
+     */
1136
+    public interface OnRotateListener {
1137
+        /**
1138
+         * A callBack to receive when the user rotate a ImageView.You will receive a callback
1139
+         * if the user rotate the ImageView
1140
+         *
1141
+         * @param degree rotate mOldDegree
1142
+         */
1143
+        void onRotate(int degree);
1144
+    }
1145
+
1146
+    /**
1147
+     * Interface definition for a callback to be invoked when the ImageView is fling with a single
1148
+     * touch
1149
+     *
1150
+     * @author tonyjs
1151
+     */
1152
+    public interface OnSingleFlingListener {
1153
+
1154
+        /**
1155
+         * A callback to receive where the user flings on a ImageView. You will receive a callback if
1156
+         * the user flings anywhere on the view.
1157
+         *
1158
+         * @param e1        - MotionEvent the user first touch.
1159
+         * @param e2        - MotionEvent the user last touch.
1160
+         * @param velocityX - distance of user's horizontal fling.
1161
+         * @param velocityY - distance of user's vertical fling.
1162
+         */
1163
+        boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY);
1164
+    }
1165
+
1166
+    private class AnimatedZoomRunnable implements Runnable {
1167
+
1168
+        private final float mFocalX, mFocalY;
1169
+        private final long mStartTime;
1170
+        private final float mZoomStart, mZoomEnd;
1171
+
1172
+        public AnimatedZoomRunnable(final float currentZoom, final float targetZoom,
1173
+                                    final float focalX, final float focalY) {
1174
+            mFocalX = focalX;
1175
+            mFocalY = focalY;
1176
+            mStartTime = System.currentTimeMillis();
1177
+            mZoomStart = currentZoom;
1178
+            mZoomEnd = targetZoom;
1179
+        }
1180
+
1181
+        @Override
1182
+        public void run() {
1183
+            ImageView imageView = getImageView();
1184
+            if (imageView == null) {
1185
+                return;
1186
+            }
1187
+
1188
+            float t = interpolate();
1189
+            float scale = mZoomStart + t * (mZoomEnd - mZoomStart);
1190
+            float deltaScale = scale / getScale();
1191
+
1192
+            onScale(deltaScale, mFocalX, mFocalY);
1193
+
1194
+            // We haven't hit our target scale yet, so post ourselves again
1195
+            if (t < 1f) {
1196
+                Compat.postOnAnimation(imageView, this);
1197
+            }
1198
+        }
1199
+
1200
+        private float interpolate() {
1201
+            float t = 1f * (System.currentTimeMillis() - mStartTime) / ZOOM_DURATION;
1202
+            t = Math.min(1f, t);
1203
+            t = mInterpolator.getInterpolation(t);
1204
+            return t;
1205
+        }
1206
+    }
1207
+
1208
+    private class FlingRunnable implements Runnable {
1209
+
1210
+        private final ScrollerProxy mScroller;
1211
+        private int mCurrentX, mCurrentY;
1212
+
1213
+        public FlingRunnable(Context context) {
1214
+            mScroller = ScrollerProxy.getScroller(context);
1215
+        }
1216
+
1217
+        public void cancelFling() {
1218
+            if (DEBUG) {
1219
+                LogManager.getLogger().d(LOG_TAG, "Cancel Fling");
1220
+            }
1221
+            mScroller.forceFinished(true);
1222
+        }
1223
+
1224
+        public void fling(int viewWidth, int viewHeight, int velocityX,
1225
+                          int velocityY) {
1226
+            final RectF rect = getDisplayRect();
1227
+            if (null == rect) {
1228
+                return;
1229
+            }
1230
+
1231
+            final int startX = Math.round(-rect.left);
1232
+            final int minX, maxX, minY, maxY;
1233
+
1234
+            if (viewWidth < rect.width()) {
1235
+                minX = 0;
1236
+                maxX = Math.round(rect.width() - viewWidth);
1237
+            } else {
1238
+                minX = maxX = startX;
1239
+            }
1240
+
1241
+            final int startY = Math.round(-rect.top);
1242
+            if (viewHeight < rect.height()) {
1243
+                minY = 0;
1244
+                maxY = Math.round(rect.height() - viewHeight);
1245
+            } else {
1246
+                minY = maxY = startY;
1247
+            }
1248
+
1249
+            mCurrentX = startX;
1250
+            mCurrentY = startY;
1251
+
1252
+            if (DEBUG) {
1253
+                LogManager.getLogger().d(
1254
+                        LOG_TAG,
1255
+                        "fling. StartX:" + startX + " StartY:" + startY
1256
+                                + " MaxX:" + maxX + " MaxY:" + maxY);
1257
+            }
1258
+
1259
+            // If we actually can move, fling the scroller
1260
+            if (startX != maxX || startY != maxY) {
1261
+                mScroller.fling(startX, startY, velocityX, velocityY, minX,
1262
+                        maxX, minY, maxY, 0, 0);
1263
+            }
1264
+        }
1265
+
1266
+        @Override
1267
+        public void run() {
1268
+            if (mScroller.isFinished()) {
1269
+                return; // remaining post that should not be handled
1270
+            }
1271
+
1272
+            ImageView imageView = getImageView();
1273
+            if (null != imageView && mScroller.computeScrollOffset()) {
1274
+
1275
+                final int newX = mScroller.getCurrX();
1276
+                final int newY = mScroller.getCurrY();
1277
+
1278
+                if (DEBUG) {
1279
+                    LogManager.getLogger().d(
1280
+                            LOG_TAG,
1281
+                            "fling run(). CurrentX:" + mCurrentX + " CurrentY:"
1282
+                                    + mCurrentY + " NewX:" + newX + " NewY:"
1283
+                                    + newY);
1284
+                }
1285
+
1286
+                mSuppMatrix.postTranslate(mCurrentX - newX, mCurrentY - newY);
1287
+                setImageViewMatrix(getDrawMatrix());
1288
+
1289
+                mCurrentX = newX;
1290
+                mCurrentY = newY;
1291
+
1292
+                // Post On animation
1293
+                Compat.postOnAnimation(imageView, this);
1294
+            }
1295
+        }
1296
+    }
1297
+
1298
+    /**
1299
+     * a RightAngleRunnable that finger lift rotate to 0,90,180,270 degree
1300
+     */
1301
+    private class RightAngleRunnable implements Runnable {
1302
+        private static final int RECOVER_SPEED = 4;
1303
+        private int mOldDegree;
1304
+        private int mNeedToRotate;
1305
+        private int mRoPivotX;
1306
+        private int mRoPivotY;
1307
+
1308
+        RightAngleRunnable(int degree, int pivotX, int pivotY) {
1309
+            this.mOldDegree = degree;
1310
+            this.mNeedToRotate = calDegree(degree) - mOldDegree;
1311
+            this.mRoPivotX = pivotX;
1312
+            this.mRoPivotY = pivotY;
1313
+        }
1314
+
1315
+        /**
1316
+         * get right degree,when one finger lifts
1317
+         *
1318
+         * @param oldDegree current degree
1319
+         * @return 0, 90, 180, 270 according to oldDegree
1320
+         */
1321
+        private int calDegree(int oldDegree) {
1322
+            int result;
1323
+            float n = (float) oldDegree / 45;
1324
+            if (n >= 0 && n < 1) {
1325
+                result = 0;
1326
+            } else if (n >= 1 && n <= 2.5) {
1327
+                result = 90;
1328
+            } else if (n > 2.5 && n < 5.5) {
1329
+                result = 180;
1330
+            } else if (n >= 5.5 && n <= 7) {
1331
+                result = 270;
1332
+            } else {
1333
+                result = 360;
1334
+            }
1335
+            return result;
1336
+        }
1337
+
1338
+        @Override
1339
+        public void run() {
1340
+            if (mNeedToRotate == 0) {
1341
+                mIsToRighting = false;
1342
+                return;
1343
+            }
1344
+            ImageView imageView = getImageView();
1345
+            if (imageView == null) {
1346
+                mIsToRighting = false;
1347
+                return;
1348
+            }
1349
+            mIsToRighting = true;
1350
+            if (mNeedToRotate > 0) {
1351
+                //Clockwise rotation
1352
+                if (mNeedToRotate >= RECOVER_SPEED) {
1353
+                    mSuppMatrix.postRotate(RECOVER_SPEED, mRoPivotX, mRoPivotY);
1354
+                    mNeedToRotate -= RECOVER_SPEED;
1355
+                } else {
1356
+                    mSuppMatrix.postRotate(mNeedToRotate, mRoPivotX, mRoPivotY);
1357
+                    mNeedToRotate = 0;
1358
+                }
1359
+            } else if (mNeedToRotate < 0) {
1360
+                //Counterclockwise rotation
1361
+                if (mNeedToRotate <= -RECOVER_SPEED) {
1362
+                    mSuppMatrix.postRotate(-RECOVER_SPEED, mRoPivotX, mRoPivotY);
1363
+                    mNeedToRotate += RECOVER_SPEED;
1364
+                } else {
1365
+                    mSuppMatrix.postRotate(mNeedToRotate, mRoPivotX, mRoPivotY);
1366
+                    mNeedToRotate = 0;
1367
+                }
1368
+            }
1369
+            checkAndDisplayMatrix();
1370
+            Compat.postOnAnimation(imageView, this);
1371
+        }
1372
+    }
1373
+}

+ 149 - 0
views/src/main/java/com/android/views/rotatephotoview/gestures/CupcakeGestureDetector.java

@@ -0,0 +1,149 @@
1
+/*******************************************************************************
2
+ * Copyright 2011, 2012 Chris Banes.
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
+package com.android.views.rotatephotoview.gestures;
17
+
18
+import android.content.Context;
19
+import android.view.MotionEvent;
20
+import android.view.VelocityTracker;
21
+import android.view.ViewConfiguration;
22
+
23
+import com.android.views.rotatephotoview.log.LogManager;
24
+
25
+public class CupcakeGestureDetector implements GestureDetector {
26
+
27
+    protected OnGestureListener mListener;
28
+    private static final String LOG_TAG = "CupcakeGestureDetector";
29
+    float mLastTouchX;
30
+    float mLastTouchY;
31
+    final float mTouchSlop;
32
+    final float mMinimumVelocity;
33
+
34
+    @Override
35
+    public void setOnGestureListener(OnGestureListener listener) {
36
+        this.mListener = listener;
37
+    }
38
+
39
+    public CupcakeGestureDetector(Context context) {
40
+        final ViewConfiguration configuration = ViewConfiguration
41
+                .get(context);
42
+        mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();
43
+        mTouchSlop = configuration.getScaledTouchSlop();
44
+    }
45
+
46
+    private VelocityTracker mVelocityTracker;
47
+    private boolean mIsDragging;
48
+
49
+    float getActiveX(MotionEvent ev) {
50
+        return ev.getX();
51
+    }
52
+
53
+    float getActiveY(MotionEvent ev) {
54
+        return ev.getY();
55
+    }
56
+
57
+    @Override
58
+    public boolean isScaling() {
59
+        return false;
60
+    }
61
+
62
+    @Override
63
+    public boolean isDragging() {
64
+        return mIsDragging;
65
+    }
66
+
67
+    @Override
68
+    public boolean onTouchEvent(MotionEvent ev) {
69
+        switch (ev.getAction()) {
70
+            case MotionEvent.ACTION_DOWN: {
71
+                mVelocityTracker = VelocityTracker.obtain();
72
+                if (null != mVelocityTracker) {
73
+                    mVelocityTracker.addMovement(ev);
74
+                } else {
75
+                    LogManager.getLogger().i(LOG_TAG, "Velocity tracker is null");
76
+                }
77
+
78
+                mLastTouchX = getActiveX(ev);
79
+                mLastTouchY = getActiveY(ev);
80
+                mIsDragging = false;
81
+                break;
82
+            }
83
+
84
+            case MotionEvent.ACTION_MOVE: {
85
+                final float x = getActiveX(ev);
86
+                final float y = getActiveY(ev);
87
+                final float dx = x - mLastTouchX, dy = y - mLastTouchY;
88
+
89
+                if (!mIsDragging) {
90
+                    // Use Pythagoras to see if drag length is larger than
91
+                    // touch slop
92
+                    mIsDragging = Math.sqrt((dx * dx) + (dy * dy)) >= mTouchSlop;
93
+                }
94
+
95
+                if (mIsDragging) {
96
+                    mListener.onDrag(dx, dy);
97
+                    mLastTouchX = x;
98
+                    mLastTouchY = y;
99
+
100
+                    if (null != mVelocityTracker) {
101
+                        mVelocityTracker.addMovement(ev);
102
+                    }
103
+                }
104
+                break;
105
+            }
106
+
107
+            case MotionEvent.ACTION_CANCEL: {
108
+                // Recycle Velocity Tracker
109
+                if (null != mVelocityTracker) {
110
+                    mVelocityTracker.recycle();
111
+                    mVelocityTracker = null;
112
+                }
113
+                break;
114
+            }
115
+
116
+            case MotionEvent.ACTION_UP: {
117
+                if (mIsDragging) {
118
+                    if (null != mVelocityTracker) {
119
+                        mLastTouchX = getActiveX(ev);
120
+                        mLastTouchY = getActiveY(ev);
121
+
122
+                        // Compute velocity within the last 1000ms
123
+                        mVelocityTracker.addMovement(ev);
124
+                        mVelocityTracker.computeCurrentVelocity(1000);
125
+
126
+                        final float vX = mVelocityTracker.getXVelocity(), vY = mVelocityTracker
127
+                                .getYVelocity();
128
+
129
+                        // If the velocity is greater than minVelocity, call
130
+                        // listener
131
+                        if (Math.max(Math.abs(vX), Math.abs(vY)) >= mMinimumVelocity) {
132
+                            mListener.onFling(mLastTouchX, mLastTouchY, -vX,
133
+                                    -vY);
134
+                        }
135
+                    }
136
+                }
137
+
138
+                // Recycle Velocity Tracker
139
+                if (null != mVelocityTracker) {
140
+                    mVelocityTracker.recycle();
141
+                    mVelocityTracker = null;
142
+                }
143
+                break;
144
+            }
145
+        }
146
+
147
+        return true;
148
+    }
149
+}

+ 92 - 0
views/src/main/java/com/android/views/rotatephotoview/gestures/EclairGestureDetector.java

@@ -0,0 +1,92 @@
1
+/**
2
+ * ****************************************************************************
3
+ * Copyright 2011, 2012 Chris Banes.
4
+ * <p>
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ * <p>
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ * <p>
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ *******************************************************************************/
17
+package com.android.views.rotatephotoview.gestures;
18
+
19
+import android.annotation.TargetApi;
20
+import android.content.Context;
21
+import android.view.MotionEvent;
22
+
23
+import com.android.views.rotatephotoview.Compat;
24
+
25
+@TargetApi(5)
26
+public class EclairGestureDetector extends CupcakeGestureDetector {
27
+
28
+    private static final int INVALID_POINTER_ID = -1;
29
+    private int mActivePointerId = INVALID_POINTER_ID;
30
+    private int mActivePointerIndex = 0;
31
+
32
+    public EclairGestureDetector(Context context) {
33
+        super(context);
34
+    }
35
+
36
+    @Override
37
+    float getActiveX(MotionEvent ev) {
38
+        try {
39
+            return ev.getX(mActivePointerIndex);
40
+        } catch (Exception e) {
41
+            return ev.getX();
42
+        }
43
+    }
44
+
45
+    @Override
46
+    float getActiveY(MotionEvent ev) {
47
+        try {
48
+            return ev.getY(mActivePointerIndex);
49
+        } catch (Exception e) {
50
+            return ev.getY();
51
+        }
52
+    }
53
+
54
+    @Override
55
+    public boolean onTouchEvent(MotionEvent ev) {
56
+        final int action = ev.getAction();
57
+        switch (action & MotionEvent.ACTION_MASK) {
58
+            case MotionEvent.ACTION_DOWN:
59
+                mActivePointerId = ev.getPointerId(0);
60
+                break;
61
+            case MotionEvent.ACTION_CANCEL:
62
+            case MotionEvent.ACTION_UP:
63
+                mActivePointerId = INVALID_POINTER_ID;
64
+                break;
65
+            case MotionEvent.ACTION_POINTER_UP:
66
+                // Ignore deprecation, ACTION_POINTER_ID_MASK and
67
+                // ACTION_POINTER_ID_SHIFT has same value and are deprecated
68
+                // You can have either deprecation or lint target api warning
69
+                final int pointerIndex = Compat.getPointerIndex(ev.getAction());
70
+                final int pointerId = ev.getPointerId(pointerIndex);
71
+                if (pointerId == mActivePointerId) {
72
+                    // This was our active pointer going up. Choose a new
73
+                    // active pointer and adjust accordingly.
74
+                    final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
75
+                    mActivePointerId = ev.getPointerId(newPointerIndex);
76
+                    mLastTouchX = ev.getX(newPointerIndex);
77
+                    mLastTouchY = ev.getY(newPointerIndex);
78
+                }
79
+                break;
80
+        }
81
+
82
+        mActivePointerIndex = ev
83
+                .findPointerIndex(mActivePointerId != INVALID_POINTER_ID ? mActivePointerId
84
+                        : 0);
85
+        try {
86
+            return super.onTouchEvent(ev);
87
+        } catch (IllegalArgumentException e) {
88
+            // Fix for support lib bug, happening when onDestroy is
89
+            return true;
90
+        }
91
+    }
92
+}

+ 73 - 0
views/src/main/java/com/android/views/rotatephotoview/gestures/FroyoGestureDetector.java

@@ -0,0 +1,73 @@
1
+/*******************************************************************************
2
+ * Copyright 2011, 2012 Chris Banes.
3
+ * <p/>
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
+ * <p/>
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ * <p/>
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
+package com.android.views.rotatephotoview.gestures;
17
+
18
+import android.annotation.TargetApi;
19
+import android.content.Context;
20
+import android.view.MotionEvent;
21
+import android.view.ScaleGestureDetector;
22
+
23
+@TargetApi(8)
24
+public class FroyoGestureDetector extends EclairGestureDetector {
25
+
26
+    protected final ScaleGestureDetector mDetector;
27
+
28
+    public FroyoGestureDetector(Context context) {
29
+        super(context);
30
+        ScaleGestureDetector.OnScaleGestureListener mScaleListener = new ScaleGestureDetector.OnScaleGestureListener() {
31
+
32
+            @Override
33
+            public boolean onScale(ScaleGestureDetector detector) {
34
+                float scaleFactor = detector.getScaleFactor();
35
+
36
+                if (Float.isNaN(scaleFactor) || Float.isInfinite(scaleFactor))
37
+                    return false;
38
+
39
+                mListener.onScale(scaleFactor,
40
+                        detector.getFocusX(), detector.getFocusY());
41
+                return true;
42
+            }
43
+
44
+            @Override
45
+            public boolean onScaleBegin(ScaleGestureDetector detector) {
46
+                return true;
47
+            }
48
+
49
+            @Override
50
+            public void onScaleEnd(ScaleGestureDetector detector) {
51
+                // NO-OP
52
+            }
53
+        };
54
+        mDetector = new ScaleGestureDetector(context, mScaleListener);
55
+    }
56
+
57
+    @Override
58
+    public boolean isScaling() {
59
+        return mDetector.isInProgress();
60
+    }
61
+
62
+    @Override
63
+    public boolean onTouchEvent(MotionEvent ev) {
64
+        try {
65
+            mDetector.onTouchEvent(ev);
66
+            return super.onTouchEvent(ev);
67
+        } catch (IllegalArgumentException e) {
68
+            // Fix for support lib bug, happening when onDestroy is
69
+            return true;
70
+        }
71
+    }
72
+
73
+}

+ 30 - 0
views/src/main/java/com/android/views/rotatephotoview/gestures/GestureDetector.java

@@ -0,0 +1,30 @@
1
+/*******************************************************************************
2
+ * Copyright 2011, 2012 Chris Banes.
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
+package com.android.views.rotatephotoview.gestures;
17
+
18
+import android.view.MotionEvent;
19
+
20
+public interface GestureDetector {
21
+
22
+    boolean onTouchEvent(MotionEvent ev);
23
+
24
+    boolean isScaling();
25
+
26
+    boolean isDragging();
27
+
28
+    void setOnGestureListener(OnGestureListener listener);
29
+
30
+}

+ 24 - 0
views/src/main/java/com/android/views/rotatephotoview/gestures/IRotateDetector.java

@@ -0,0 +1,24 @@
1
+package com.android.views.rotatephotoview.gestures;
2
+
3
+import android.view.MotionEvent;
4
+
5
+/**
6
+ * Interface to detect rotation
7
+ * Created by ChenSL on 2015/9/16.
8
+ */
9
+public interface IRotateDetector {
10
+    /**
11
+     * handle rotation in onTouchEvent
12
+     *
13
+     * @param event The motion event.
14
+     * @return True if the event was handled, false otherwise.
15
+     */
16
+    boolean onTouchEvent(MotionEvent event);
17
+
18
+    /**
19
+     * is the Gesture Rotate
20
+     *
21
+     * @return true:rotating;false,otherwise
22
+     */
23
+    boolean isRotating();
24
+}

+ 20 - 0
views/src/main/java/com/android/views/rotatephotoview/gestures/IRotateListener.java

@@ -0,0 +1,20 @@
1
+package com.android.views.rotatephotoview.gestures;
2
+
3
+/**
4
+ * Interface for a callback for rotation
5
+ * Created by ChenSL on 2015/9/16.
6
+ */
7
+public interface IRotateListener {
8
+    /**
9
+     * callback for rotation
10
+     *
11
+     * @param degree degree of rotation
12
+     */
13
+    void rotate(int degree, int pivotX, int pivotY);
14
+
15
+    /**
16
+     * MotionEvent.ACTION_POINTER_UP happens when two finger minus to only one
17
+     * change the ImageView to 0,90,180,270
18
+     */
19
+    void upRotate(int pivotX, int pivotY);
20
+}

+ 27 - 0
views/src/main/java/com/android/views/rotatephotoview/gestures/OnGestureListener.java

@@ -0,0 +1,27 @@
1
+/*******************************************************************************
2
+ * Copyright 2011, 2012 Chris Banes.
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
+package com.android.views.rotatephotoview.gestures;
17
+
18
+public interface OnGestureListener {
19
+
20
+    void onDrag(float dx, float dy);
21
+
22
+    void onFling(float startX, float startY, float velocityX,
23
+                 float velocityY);
24
+
25
+    void onScale(float scaleFactor, float focusX, float focusY);
26
+
27
+}

+ 113 - 0
views/src/main/java/com/android/views/rotatephotoview/gestures/RotateGestureDetector.java

@@ -0,0 +1,113 @@
1
+package com.android.views.rotatephotoview.gestures;
2
+
3
+import android.view.MotionEvent;
4
+
5
+/**
6
+ * Handle ImageView rotate event with two fingers
7
+ * Created by ChenSL on 2015/9/16.
8
+ */
9
+public class RotateGestureDetector implements IRotateDetector {
10
+    private int mLastAngle = 0;
11
+    private IRotateListener mListener;
12
+    private boolean mIsRotate;
13
+
14
+    /**
15
+     * set rotation listener for callback
16
+     *
17
+     * @param listener a  rotation listener
18
+     */
19
+    public void setRotateListener(IRotateListener listener) {
20
+        this.mListener = listener;
21
+    }
22
+
23
+    @Override
24
+    public boolean onTouchEvent(MotionEvent event) {
25
+        return doRotate(event);
26
+    }
27
+
28
+    @Override
29
+    public boolean isRotating() {
30
+        return mIsRotate;
31
+    }
32
+
33
+    /**
34
+     * handle rotation
35
+     *
36
+     * @param ev Motion event
37
+     * @return always true.
38
+     */
39
+    private boolean doRotate(MotionEvent ev) {
40
+        if (ev.getPointerCount() != 2) {
41
+            return false;
42
+        }
43
+        //Calculate the angle between the two fingers
44
+        int pivotX = (int) (ev.getX(0) + ev.getX(1)) / 2;
45
+        int pivotY = (int) (ev.getY(0) + ev.getY(1)) / 2;
46
+        float deltaX = ev.getX(0) - ev.getX(1);
47
+        float deltaY = ev.getY(0) - ev.getY(1);
48
+        double radians = Math.atan(deltaY / deltaX);
49
+        //Convert to degrees
50
+        int degrees = (int) (radians * 180 / Math.PI);
51
+        /*
52
+         * Must use getActionMasked() for switching to pick up pointer events.
53
+         * These events have the pointer index encoded in them so the return
54
+         * from getAction() won't match the exact action constant.
55
+         */
56
+        switch (ev.getActionMasked()) {
57
+            case MotionEvent.ACTION_DOWN:
58
+                mLastAngle = degrees;
59
+                mIsRotate = false;
60
+                break;
61
+            case MotionEvent.ACTION_UP:
62
+                mIsRotate = false;
63
+                break;
64
+            case MotionEvent.ACTION_POINTER_DOWN:
65
+                mLastAngle = degrees;
66
+                mIsRotate = false;
67
+                break;
68
+            case MotionEvent.ACTION_CANCEL:
69
+            case MotionEvent.ACTION_POINTER_UP:
70
+                mIsRotate = false;
71
+                upRotate(pivotX, pivotY);
72
+                mLastAngle = degrees;
73
+                break;
74
+            case MotionEvent.ACTION_MOVE:
75
+                mIsRotate = true;
76
+                int degreesValue = degrees - mLastAngle;
77
+                if (degreesValue > 45) {
78
+                    //Going CCW across the boundary
79
+                    rotate(-5, pivotX, pivotY);
80
+                } else if (degreesValue < -45) {
81
+                    //Going CW across the boundary
82
+                    rotate(5, pivotX, pivotY);
83
+                } else {
84
+                    //Normal rotation, rotate the difference
85
+                    rotate(degreesValue, pivotX, pivotY);
86
+                }
87
+                //Save the current angle
88
+                mLastAngle = degrees;
89
+                break;
90
+        }
91
+        return true;
92
+    }
93
+
94
+    /**
95
+     * to invoke the callback
96
+     *
97
+     * @param degree degree to rotate
98
+     */
99
+    private void rotate(int degree, int pivotX, int pivotY) {
100
+        if (mListener != null) {
101
+            mListener.rotate(degree, pivotX, pivotY);
102
+        }
103
+    }
104
+
105
+    /**
106
+     * to invoke the finger up action
107
+     */
108
+    private void upRotate(int pivotX, int pivotY) {
109
+        if (mListener != null) {
110
+            mListener.upRotate(pivotX, pivotY);
111
+        }
112
+    }
113
+}

+ 42 - 0
views/src/main/java/com/android/views/rotatephotoview/gestures/VersionedGestureDetector.java

@@ -0,0 +1,42 @@
1
+package com.android.views.rotatephotoview.gestures;
2
+
3
+/*******************************************************************************
4
+ * Copyright 2011, 2012 Chris Banes.
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ *******************************************************************************/
18
+
19
+import android.content.Context;
20
+import android.os.Build;
21
+
22
+public final class VersionedGestureDetector {
23
+
24
+    public static GestureDetector newInstance(Context context,
25
+                                              OnGestureListener listener) {
26
+        final int sdkVersion = Build.VERSION.SDK_INT;
27
+        GestureDetector detector;
28
+
29
+        if (sdkVersion < Build.VERSION_CODES.ECLAIR) {
30
+            detector = new CupcakeGestureDetector(context);
31
+        } else if (sdkVersion < Build.VERSION_CODES.FROYO) {
32
+            detector = new EclairGestureDetector(context);
33
+        } else {
34
+            detector = new FroyoGestureDetector(context);
35
+        }
36
+
37
+        detector.setOnGestureListener(listener);
38
+
39
+        return detector;
40
+    }
41
+
42
+}

+ 35 - 0
views/src/main/java/com/android/views/rotatephotoview/log/LogManager.java

@@ -0,0 +1,35 @@
1
+/*******************************************************************************
2
+ * Copyright 2011, 2012 Chris Banes.
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
+package com.android.views.rotatephotoview.log;
17
+
18
+import android.util.Log;
19
+
20
+/**
21
+ * class that holds the {@link Logger} for this library, defaults to {@link LoggerDefault} to send logs to android {@link Log}
22
+ */
23
+public final class LogManager {
24
+
25
+    private static Logger logger = new LoggerDefault();
26
+
27
+    public static void setLogger(Logger newLogger) {
28
+        logger = newLogger;
29
+    }
30
+
31
+    public static Logger getLogger() {
32
+        return logger;
33
+    }
34
+
35
+}

+ 116 - 0
views/src/main/java/com/android/views/rotatephotoview/log/Logger.java

@@ -0,0 +1,116 @@
1
+/*******************************************************************************
2
+ * Copyright 2011, 2012 Chris Banes.
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
+package com.android.views.rotatephotoview.log;
17
+
18
+/**
19
+ * interface for a logger class to replace the static calls to {@link android.util.Log}
20
+ */
21
+public interface Logger {
22
+    /**
23
+     * Send a {@link android.util.Log#VERBOSE} log message.
24
+     *
25
+     * @param tag Used to identify the source of a log message.  It usually identifies
26
+     *            the class or activity where the log call occurs.
27
+     * @param msg The message you would like logged.
28
+     */
29
+    int v(String tag, String msg);
30
+
31
+    /**
32
+     * Send a {@link android.util.Log#VERBOSE} log message and log the exception.
33
+     *
34
+     * @param tag Used to identify the source of a log message.  It usually identifies
35
+     *            the class or activity where the log call occurs.
36
+     * @param msg The message you would like logged.
37
+     * @param tr  An exception to log
38
+     */
39
+    int v(String tag, String msg, Throwable tr);
40
+
41
+    /**
42
+     * Send a {@link android.util.Log#DEBUG} log message.
43
+     *
44
+     * @param tag Used to identify the source of a log message.  It usually identifies
45
+     *            the class or activity where the log call occurs.
46
+     * @param msg The message you would like logged.
47
+     */
48
+    int d(String tag, String msg);
49
+
50
+    /**
51
+     * Send a {@link android.util.Log#DEBUG} log message and log the exception.
52
+     *
53
+     * @param tag Used to identify the source of a log message.  It usually identifies
54
+     *            the class or activity where the log call occurs.
55
+     * @param msg The message you would like logged.
56
+     * @param tr  An exception to log
57
+     */
58
+    int d(String tag, String msg, Throwable tr);
59
+
60
+    /**
61
+     * Send an {@link android.util.Log#INFO} log message.
62
+     *
63
+     * @param tag Used to identify the source of a log message.  It usually identifies
64
+     *            the class or activity where the log call occurs.
65
+     * @param msg The message you would like logged.
66
+     */
67
+    int i(String tag, String msg);
68
+
69
+    /**
70
+     * Send a {@link android.util.Log#INFO} log message and log the exception.
71
+     *
72
+     * @param tag Used to identify the source of a log message.  It usually identifies
73
+     *            the class or activity where the log call occurs.
74
+     * @param msg The message you would like logged.
75
+     * @param tr  An exception to log
76
+     */
77
+    int i(String tag, String msg, Throwable tr);
78
+
79
+    /**
80
+     * Send a {@link android.util.Log#WARN} log message.
81
+     *
82
+     * @param tag Used to identify the source of a log message.  It usually identifies
83
+     *            the class or activity where the log call occurs.
84
+     * @param msg The message you would like logged.
85
+     */
86
+    int w(String tag, String msg);
87
+
88
+    /**
89
+     * Send a {@link android.util.Log#WARN} log message and log the exception.
90
+     *
91
+     * @param tag Used to identify the source of a log message.  It usually identifies
92
+     *            the class or activity where the log call occurs.
93
+     * @param msg The message you would like logged.
94
+     * @param tr  An exception to log
95
+     */
96
+    int w(String tag, String msg, Throwable tr);
97
+
98
+    /**
99
+     * Send an {@link android.util.Log#ERROR} log message.
100
+     *
101
+     * @param tag Used to identify the source of a log message.  It usually identifies
102
+     *            the class or activity where the log call occurs.
103
+     * @param msg The message you would like logged.
104
+     */
105
+    int e(String tag, String msg);
106
+
107
+    /**
108
+     * Send a {@link android.util.Log#ERROR} log message and log the exception.
109
+     *
110
+     * @param tag Used to identify the source of a log message.  It usually identifies
111
+     *            the class or activity where the log call occurs.
112
+     * @param msg The message you would like logged.
113
+     * @param tr  An exception to log
114
+     */
115
+    int e(String tag, String msg, Throwable tr);
116
+}

+ 76 - 0
views/src/main/java/com/android/views/rotatephotoview/log/LoggerDefault.java

@@ -0,0 +1,76 @@
1
+/*******************************************************************************
2
+ * Copyright 2011, 2012 Chris Banes.
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
+package com.android.views.rotatephotoview.log;
17
+
18
+import android.util.Log;
19
+
20
+/**
21
+ * Helper class to redirect {@link LogManager#logger} to {@link Log}
22
+ */
23
+public class LoggerDefault implements Logger {
24
+
25
+    @Override
26
+    public int v(String tag, String msg) {
27
+        return Log.v(tag, msg);
28
+    }
29
+
30
+    @Override
31
+    public int v(String tag, String msg, Throwable tr) {
32
+        return Log.v(tag, msg, tr);
33
+    }
34
+
35
+    @Override
36
+    public int d(String tag, String msg) {
37
+        return Log.d(tag, msg);
38
+    }
39
+
40
+    @Override
41
+    public int d(String tag, String msg, Throwable tr) {
42
+        return Log.d(tag, msg, tr);
43
+    }
44
+
45
+    @Override
46
+    public int i(String tag, String msg) {
47
+        return Log.i(tag, msg);
48
+    }
49
+
50
+    @Override
51
+    public int i(String tag, String msg, Throwable tr) {
52
+        return Log.i(tag, msg, tr);
53
+    }
54
+
55
+    @Override
56
+    public int w(String tag, String msg) {
57
+        return Log.w(tag, msg);
58
+    }
59
+
60
+    @Override
61
+    public int w(String tag, String msg, Throwable tr) {
62
+        return Log.w(tag, msg, tr);
63
+    }
64
+
65
+    @Override
66
+    public int e(String tag, String msg) {
67
+        return Log.e(tag, msg);
68
+    }
69
+
70
+    @Override
71
+    public int e(String tag, String msg, Throwable tr) {
72
+        return Log.e(tag, msg, tr);
73
+    }
74
+
75
+
76
+}

+ 61 - 0
views/src/main/java/com/android/views/rotatephotoview/scrollerproxy/GingerScroller.java

@@ -0,0 +1,61 @@
1
+/*******************************************************************************
2
+ * Copyright 2011, 2012 Chris Banes.
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
+package com.android.views.rotatephotoview.scrollerproxy;
17
+
18
+import android.annotation.TargetApi;
19
+import android.content.Context;
20
+import android.widget.OverScroller;
21
+
22
+@TargetApi(9)
23
+public class GingerScroller extends ScrollerProxy {
24
+
25
+    protected final OverScroller mScroller;
26
+
27
+    public GingerScroller(Context context) {
28
+        mScroller = new OverScroller(context);
29
+    }
30
+
31
+    @Override
32
+    public boolean computeScrollOffset() {
33
+        return mScroller.computeScrollOffset();
34
+    }
35
+
36
+    @Override
37
+    public void fling(int startX, int startY, int velocityX, int velocityY, int minX, int maxX, int minY, int maxY,
38
+                      int overX, int overY) {
39
+        mScroller.fling(startX, startY, velocityX, velocityY, minX, maxX, minY, maxY, overX, overY);
40
+    }
41
+
42
+    @Override
43
+    public void forceFinished(boolean finished) {
44
+        mScroller.forceFinished(finished);
45
+    }
46
+
47
+    @Override
48
+    public boolean isFinished() {
49
+        return mScroller.isFinished();
50
+    }
51
+
52
+    @Override
53
+    public int getCurrX() {
54
+        return mScroller.getCurrX();
55
+    }
56
+
57
+    @Override
58
+    public int getCurrY() {
59
+        return mScroller.getCurrY();
60
+    }
61
+}

+ 33 - 0
views/src/main/java/com/android/views/rotatephotoview/scrollerproxy/IcsScroller.java

@@ -0,0 +1,33 @@
1
+/*******************************************************************************
2
+ * Copyright 2011, 2012 Chris Banes.
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
+package com.android.views.rotatephotoview.scrollerproxy;
17
+
18
+import android.annotation.TargetApi;
19
+import android.content.Context;
20
+
21
+@TargetApi(14)
22
+public class IcsScroller extends GingerScroller {
23
+
24
+    public IcsScroller(Context context) {
25
+        super(context);
26
+    }
27
+
28
+    @Override
29
+    public boolean computeScrollOffset() {
30
+        return mScroller.computeScrollOffset();
31
+    }
32
+
33
+}

+ 58 - 0
views/src/main/java/com/android/views/rotatephotoview/scrollerproxy/PreGingerScroller.java

@@ -0,0 +1,58 @@
1
+/*******************************************************************************
2
+ * Copyright 2011, 2012 Chris Banes.
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
+package com.android.views.rotatephotoview.scrollerproxy;
17
+
18
+import android.content.Context;
19
+import android.widget.Scroller;
20
+
21
+public class PreGingerScroller extends ScrollerProxy {
22
+
23
+    private final Scroller mScroller;
24
+
25
+    public PreGingerScroller(Context context) {
26
+        mScroller = new Scroller(context);
27
+    }
28
+
29
+    @Override
30
+    public boolean computeScrollOffset() {
31
+        return mScroller.computeScrollOffset();
32
+    }
33
+
34
+    @Override
35
+    public void fling(int startX, int startY, int velocityX, int velocityY, int minX, int maxX, int minY, int maxY,
36
+                      int overX, int overY) {
37
+        mScroller.fling(startX, startY, velocityX, velocityY, minX, maxX, minY, maxY);
38
+    }
39
+
40
+    @Override
41
+    public void forceFinished(boolean finished) {
42
+        mScroller.forceFinished(finished);
43
+    }
44
+
45
+    public boolean isFinished() {
46
+        return mScroller.isFinished();
47
+    }
48
+
49
+    @Override
50
+    public int getCurrX() {
51
+        return mScroller.getCurrX();
52
+    }
53
+
54
+    @Override
55
+    public int getCurrY() {
56
+        return mScroller.getCurrY();
57
+    }
58
+}

+ 48 - 0
views/src/main/java/com/android/views/rotatephotoview/scrollerproxy/ScrollerProxy.java

@@ -0,0 +1,48 @@
1
+/*******************************************************************************
2
+ * Copyright 2011, 2012 Chris Banes.
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
+package com.android.views.rotatephotoview.scrollerproxy;
17
+
18
+import android.content.Context;
19
+import android.os.Build.VERSION;
20
+import android.os.Build.VERSION_CODES;
21
+
22
+public abstract class ScrollerProxy {
23
+
24
+    public static ScrollerProxy getScroller(Context context) {
25
+        if (VERSION.SDK_INT < VERSION_CODES.GINGERBREAD) {
26
+            return new PreGingerScroller(context);
27
+        } else if (VERSION.SDK_INT < VERSION_CODES.ICE_CREAM_SANDWICH) {
28
+            return new GingerScroller(context);
29
+        } else {
30
+            return new IcsScroller(context);
31
+        }
32
+    }
33
+
34
+    public abstract boolean computeScrollOffset();
35
+
36
+    public abstract void fling(int startX, int startY, int velocityX, int velocityY, int minX, int maxX, int minY,
37
+                               int maxY, int overX, int overY);
38
+
39
+    public abstract void forceFinished(boolean finished);
40
+
41
+    public abstract boolean isFinished();
42
+
43
+    public abstract int getCurrX();
44
+
45
+    public abstract int getCurrY();
46
+
47
+
48
+}

adminSystem - Gogs: Go Git Service

Nessuna descrizione

LICENSE 1.0KB

    The MIT License (MIT) Copyright (c) 2014 PostCSS Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.