+ * 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
|
+}
|
|
|
@@ -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
|
+}
|
|
|
@@ -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
|
+}
|
|
|
@@ -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
|
+}
|
|
|
@@ -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
|
+}
|
|
|
@@ -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
|
+}
|
|
|
@@ -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
|
+}
|
|
|
@@ -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
|
+}
|
|
|
@@ -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
|
+}
|
|
|
@@ -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
|
+}
|
|
|
@@ -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
|
+}
|
|
|
@@ -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
|
+}
|
|
|
@@ -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
|
+}
|
|
|
@@ -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
|
+}
|
|
|
@@ -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
|
+}
|
|
|
@@ -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
|
+}
|
|
|
@@ -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
|
+}
|