summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Wren <cwren@android.com>2012-08-29 15:57:23 -0400
committerChris Wren <cwren@android.com>2012-08-30 07:59:53 -0400
commit23f9b01ba3f51a33a2ba92bca7d7a53f25b1b146 (patch)
treec5f5fbc1a21c8d54e7de161eaa6318364e5b80ae
parent20e2554251954f6757462ab13470c1ebdcfba62e (diff)
downloadandroid_packages_screensavers_PhotoTable-23f9b01ba3f51a33a2ba92bca7d7a53f25b1b146.tar.gz
android_packages_screensavers_PhotoTable-23f9b01ba3f51a33a2ba92bca7d7a53f25b1b146.tar.bz2
android_packages_screensavers_PhotoTable-23f9b01ba3f51a33a2ba92bca7d7a53f25b1b146.zip
PhotoTable Polish:
+ remove manual rotation + better icon + gradient background + remove tap to dismiss + (temporarily disabled) flick to replace Change-Id: I2177077e37ce07a131a67bfbd11f8a447775ab98
-rw-r--r--res/drawable/table.xml30
-rw-r--r--res/layout/photo.xml2
-rw-r--r--res/mipmap-hdpi/icon.pngbin4713 -> 11919 bytes
-rw-r--r--res/mipmap-mdpi/icon.pngbin2850 -> 7861 bytes
-rw-r--r--res/mipmap-xhdpi/icon.pngbin0 -> 17695 bytes
-rw-r--r--res/values-sw800dp/config.xml3
-rw-r--r--res/values/colors.xml3
-rw-r--r--res/values/config.xml18
-rw-r--r--res/values/dimen.xml1
-rw-r--r--src/com/android/dreams/phototable/PhotoTable.java453
10 files changed, 357 insertions, 153 deletions
diff --git a/res/drawable/table.xml b/res/drawable/table.xml
new file mode 100644
index 0000000..4663f51
--- /dev/null
+++ b/res/drawable/table.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<shape
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <gradient
+ android:angle="90"
+ android:startColor="@color/tabletop_light"
+ android:endColor="@color/tabletop_dark"
+ android:type="linear"
+ />
+ <padding
+ android:left="10dp"
+ android:top="10dp"
+ android:right="10dp"
+ android:bottom="10dp" />
+</shape>
diff --git a/res/layout/photo.xml b/res/layout/photo.xml
index 988dbe4..1850c21 100644
--- a/res/layout/photo.xml
+++ b/res/layout/photo.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
+<!-- Copyright (C) 2012 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/res/mipmap-hdpi/icon.png b/res/mipmap-hdpi/icon.png
index b57ffa4..869cf89 100644
--- a/res/mipmap-hdpi/icon.png
+++ b/res/mipmap-hdpi/icon.png
Binary files differ
diff --git a/res/mipmap-mdpi/icon.png b/res/mipmap-mdpi/icon.png
index 5cd2f30..682ab14 100644
--- a/res/mipmap-mdpi/icon.png
+++ b/res/mipmap-mdpi/icon.png
Binary files differ
diff --git a/res/mipmap-xhdpi/icon.png b/res/mipmap-xhdpi/icon.png
new file mode 100644
index 0000000..dc36096
--- /dev/null
+++ b/res/mipmap-xhdpi/icon.png
Binary files differ
diff --git a/res/values-sw800dp/config.xml b/res/values-sw800dp/config.xml
index 7771f21..eff4c2b 100644
--- a/res/values-sw800dp/config.xml
+++ b/res/values-sw800dp/config.xml
@@ -14,6 +14,9 @@
limitations under the License.
-->
<resources>
+ <!-- Number of photos to drop when the screensaver starts.-->
+ <integer name="initial_drop">5</integer>
+
<!-- Parts per million ratio between image size and screen size. -->
<integer name="image_ratio">500000</integer>
</resources>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 9d5864e..279c0c9 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -14,5 +14,6 @@
limitations under the License.
-->
<resources>
- <color name="tabletop">#ff444444</color>
+ <color name="tabletop_dark">#ff222222</color>
+ <color name="tabletop_light">#ff111111</color>
</resources>
diff --git a/res/values/config.xml b/res/values/config.xml
index f1c9fcc..c510c2e 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -27,7 +27,25 @@
<!-- Parts per million ratio between image size and screen size. -->
<integer name="image_ratio">1000000</integer>
+ <!-- Parts per million ratio between image size on the table and screen size. -->
+ <integer name="table_ratio">500000</integer>
+
+ <!-- The maximum allowed rotation of images thrown onto the table. -->
+ <integer name="max_image_rotation">30</integer>
+
<!-- Maximum number of image paths to load before shuffling. -->
<integer name="image_queue_size">1000</integer>
+
+ <!-- Enable manual rotation of images. -->
+ <bool name="enable_manual_image_rotation">false</bool>
+
+ <!-- Enable flinging away photos. -->
+ <bool name="enable_fling">false</bool>
+
+ <!-- Honor tap on table to exit. -->
+ <bool name="enable_tap_to_exit">false</bool>
+
+ <!-- Parts per million damping coefficient of the table. -->
+ <integer name="table_damping">500000</integer>
</resources>
diff --git a/res/values/dimen.xml b/res/values/dimen.xml
index 7e070df..eaf42ef 100644
--- a/res/values/dimen.xml
+++ b/res/values/dimen.xml
@@ -14,5 +14,6 @@
limitations under the License.
-->
<resources>
+ <!-- Amount photo is inset to account for the frame. -->
<dimen name="photo_inset">4px</dimen>
</resources>
diff --git a/src/com/android/dreams/phototable/PhotoTable.java b/src/com/android/dreams/phototable/PhotoTable.java
index 082b3b5..9066396 100644
--- a/src/com/android/dreams/phototable/PhotoTable.java
+++ b/src/com/android/dreams/phototable/PhotoTable.java
@@ -31,12 +31,13 @@ import android.os.AsyncTask;
import android.os.PowerManager;
import android.util.AttributeSet;
import android.util.Log;
+import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
+import android.view.ViewPropertyAnimator;
import android.view.animation.DecelerateInterpolator;
-import android.view.animation.LinearInterpolator;
import android.widget.FrameLayout;
import android.widget.FrameLayout.LayoutParams;
import android.widget.ImageView;
@@ -68,6 +69,284 @@ public class PhotoTable extends Dream {
private Table mTable;
+ static class PhotoTouchListener implements View.OnTouchListener,
+ GestureDetector.OnGestureListener {
+ private static final int INVALID_POINTER = -1;
+ private static final int MAX_POINTER_COUNT = 10;
+ private final int mTouchSlop;
+ private final int mTapTimeout;
+ private final Table mTable;
+ private final GestureDetector mDetector;
+ private final float mBeta;
+ private final float mTableRatio;
+ private final boolean mEnableFling;
+ private View mTarget;
+ private float mInitialTouchX;
+ private float mInitialTouchY;
+ private float mInitialTouchA;
+ private long mInitialTouchTime;
+ private float mInitialTargetX;
+ private float mInitialTargetY;
+ private float mInitialTargetA;
+ private int mA = INVALID_POINTER;
+ private int mB = INVALID_POINTER;
+ private float[] pts = new float[MAX_POINTER_COUNT];
+
+ public PhotoTouchListener(Context context, Table table) {
+ mTable = table;
+ mDetector = new GestureDetector(context, this);
+ final ViewConfiguration configuration = ViewConfiguration.get(context);
+ mTouchSlop = configuration.getScaledTouchSlop();
+ mTapTimeout = configuration.getTapTimeout();
+ final Resources resources = context.getResources();
+ mBeta = resources.getInteger(R.integer.table_damping) / 1000000f;
+ mTableRatio = resources.getInteger(R.integer.table_ratio) / 1000000f;
+ mEnableFling = resources.getBoolean(R.bool.enable_fling);
+ }
+
+ /** Get angle defined by first two touches, in degrees */
+ private float getAngle(View target, MotionEvent ev) {
+ float alpha = 0f;
+ int a = ev.findPointerIndex(mA);
+ int b = ev.findPointerIndex(mB);
+ if (a >=0 && b >=0) {
+ alpha = (float) (Math.atan2(pts[2*a + 1] - pts[2*b + 1],
+ pts[2*a] - pts[2*b]) *
+ 180f / Math.PI);
+ }
+ return alpha;
+ }
+
+ private void resetTouch(View target) {
+ mInitialTouchX = -1;
+ mInitialTouchY = -1;
+ mInitialTouchA = 0f;
+ mInitialTargetX = (float) target.getX();
+ mInitialTargetY = (float) target.getY();
+ mInitialTargetA = (float) target.getRotation();
+ }
+
+ @Override
+ public boolean onDown(MotionEvent e) {
+ return false;
+ }
+
+ @Override
+ public void onLongPress(MotionEvent e) {
+ }
+
+ @Override
+ public boolean onScroll(MotionEvent e1, MotionEvent e2, float deltaX, float deltaY) {
+ return false;
+ }
+
+ @Override
+ public void onShowPress(MotionEvent e) {
+ }
+
+ @Override
+ public boolean onSingleTapUp(MotionEvent e) {
+ return false;
+ }
+
+ @Override
+ public boolean onFling(MotionEvent e1, MotionEvent e2, float dX, float dY) {
+ if (!mEnableFling) {
+ return false;
+ }
+ pts[0] = dX;
+ pts[1] = dY;
+ mTarget.getMatrix().mapVectors(pts);
+ // velocity components in global coordinate frame
+ dX = - pts[0];
+ dY = - pts[1];
+
+ if (DEBUG) {
+ Log.i(TAG, "fling " + dX + ", " + dY);
+ }
+
+ final int idx = e2.getActionIndex();
+ pts[0] = e2.getX(idx);
+ pts[1] = e2.getY(idx);
+ mTarget.getMatrix().mapPoints(pts);
+ // starting position compionents in global corrdinate frame
+ final float x0 = pts[0];
+ final float y0 = pts[1];
+
+ // velocity
+ final float v = (float) Math.hypot(dX, dY);
+ // number of steps to come to a stop
+ final float n = (float) (- Math.log(v) / Math.log(mBeta));
+ // distance travelled before stopping
+ final float s = (float) (v * (1f - Math.pow(mBeta, n)) / (1f - mBeta));
+
+ // ending posiiton after stopping
+ final float x1 = x0 + s * dX / v;
+ final float y1 = y0 + s * dY / v;
+
+ if (DEBUG) {
+ Log.i(TAG, "fling v = " + v);
+ Log.i(TAG, "fling n = " + n);
+ Log.i(TAG, "fling s = " + n);
+ Log.i(TAG, "fling x0 = " + x0);
+ Log.i(TAG, "fling y0 = " + y0);
+ Log.i(TAG, "fling x1 = " + x1);
+ Log.i(TAG, "fling y1 = " + y1);
+ }
+
+ final float photoWidth = ((Integer) mTarget.getTag(R.id.photo_width)).floatValue();
+ final float photoHeight = ((Integer) mTarget.getTag(R.id.photo_height)).floatValue();
+ final float tableWidth = mTable.getWidth();
+ final float tableHeight = mTable.getHeight();
+
+ pts[0] = 0f;
+ pts[1] = 0f;
+ pts[2] = photoHeight;
+ pts[3] = photoWidth;
+ mTarget.getMatrix().mapPoints(pts);
+ pts[0] += x1;
+ pts[1] += y1;
+ pts[2] += x1;
+ pts[3] += y1;
+
+ boolean xOut = true;
+ boolean yOut = true;
+ for (int i = 0; i < 2; i++) {
+ if(pts[2 * i] >= 0f && pts[2 * i] < tableWidth) {
+ xOut = false;
+ if (DEBUG) {
+ Log.i(TAG, "fling x in: " + pts[2 * i]);
+ }
+ }
+ if(pts[2 * i + 1] >= 0f && pts[2 * i + 1] < tableHeight) {
+ yOut = false;
+ if (DEBUG) {
+ Log.i(TAG, "fling y in: " + pts[2 * i + 1]);
+ }
+ }
+ }
+ final View photo = mTarget;
+ ViewPropertyAnimator animator = photo.animate()
+ .withLayer()
+ .x(x1)
+ .y(y1)
+ .setDuration((int) (100f * n));
+
+ if (xOut || yOut) {
+ if (DEBUG) {
+ Log.i(TAG, "fling away");
+ }
+ animator.withEndAction(new Runnable() {
+ @Override
+ public void run() {
+ mTable.fadeAway(photo);
+ mTable.launch();
+ }
+ });
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean onTouch(View target, MotionEvent ev) {
+ mTarget = target;
+ if (mDetector.onTouchEvent(ev)) {
+ return true;
+ }
+ final int action = ev.getActionMasked();
+
+ // compute raw coordinates
+ for(int i = 0; i < 10 && i < ev.getPointerCount(); i++) {
+ pts[i*2] = ev.getX(i);
+ pts[i*2 + 1] = ev.getY(i);
+ }
+ target.getMatrix().mapPoints(pts);
+
+ switch (action) {
+ case MotionEvent.ACTION_DOWN:
+ mTable.moveToBackOfQueue(target);
+ mInitialTouchTime = ev.getEventTime();
+ mA = ev.getPointerId(ev.getActionIndex());
+ resetTouch(target);
+ break;
+
+ case MotionEvent.ACTION_POINTER_DOWN:
+ if (mB == INVALID_POINTER) {
+ mB = ev.getPointerId(ev.getActionIndex());
+ mInitialTouchA = getAngle(target, ev);
+ }
+ break;
+
+ case MotionEvent.ACTION_POINTER_UP:
+ if (mB == ev.getPointerId(ev.getActionIndex())) {
+ mB = INVALID_POINTER;
+ mInitialTargetA = (float) target.getRotation();
+ }
+ if (mA == ev.getPointerId(ev.getActionIndex())) {
+ mA = mB;
+ resetTouch(target);
+ mB = INVALID_POINTER;
+ }
+ break;
+
+ case MotionEvent.ACTION_MOVE: {
+ if (mA != INVALID_POINTER) {
+ int idx = ev.findPointerIndex(mA);
+ float x = pts[2 * idx];
+ float y = pts[2 * idx + 1];
+ if (mInitialTouchX == -1 && mInitialTouchY == -1) {
+ mInitialTouchX = x;
+ mInitialTouchY = y;
+ }
+ if (mTable.getSelected() != target) {
+ target.animate().cancel();
+
+ target.setX((int) (mInitialTargetX + x - mInitialTouchX));
+ target.setY((int) (mInitialTargetY + y - mInitialTouchY));
+ if (mTable.mManualImageRotation && mB != INVALID_POINTER) {
+ float a = getAngle(target, ev);
+ target.setRotation(
+ (int) (mInitialTargetA + a - mInitialTouchA));
+ }
+ }
+ }
+ }
+ break;
+
+ case MotionEvent.ACTION_UP: {
+ if (mA != INVALID_POINTER) {
+ int idx = ev.findPointerIndex(mA);
+ float x = pts[2 * idx];
+ float y = pts[2 * idx + 1];
+ if (mInitialTouchX == -1 && mInitialTouchY == -1) {
+ mInitialTouchX = x;
+ mInitialTouchY = y;
+ }
+ double distance = Math.hypot(x - mInitialTouchX,
+ y - mInitialTouchY);
+ if (mTable.getSelected() == target) {
+ mTable.dropOnTable(target);
+ mTable.clearSelection();
+ } else if ((ev.getEventTime() - mInitialTouchTime) < mTapTimeout &&
+ distance < mTouchSlop) {
+ // tap
+ target.animate().cancel();
+ mTable.setSelection(target);
+ }
+ mA = INVALID_POINTER;
+ mB = INVALID_POINTER;
+ }
+ }
+ break;
+
+ case MotionEvent.ACTION_CANCEL:
+ break;
+ }
+ return true;
+ }
+ }
+
public static class Table extends FrameLayout {
class Launcher implements Runnable {
private final Table mTable;
@@ -89,12 +368,14 @@ public class PhotoTable extends Dream {
private final Dream mDream;
private final int mDropPeriod;
private final float mImageRatio;
+ private final float mTableRatio;
+ private final float mImageRotationLimit;
+ private final boolean mManualImageRotation;
+ private final boolean mTapToExit;
private final int mTableCapacity;
private final int mInset;
private final LocalSource mLocalSource;
private final Resources mResources;
- private final int mTouchSlop;
- private final int mTapTimeout;
private boolean mStarted;
private boolean mIsLandscape;
private BitmapFactory.Options mOptions;
@@ -109,20 +390,21 @@ public class PhotoTable extends Dream {
super(dream, as);
mDream = dream;
mResources = getResources();
- setBackgroundColor(mResources.getColor(R.color.tabletop));
+ setBackground(mResources.getDrawable(R.drawable.table));
mInset = mResources.getDimensionPixelSize(R.dimen.photo_inset);
mDropPeriod = mResources.getInteger(R.integer.drop_period);
mImageRatio = mResources.getInteger(R.integer.image_ratio) / 1000000f;
+ mTableRatio = mResources.getInteger(R.integer.table_ratio) / 1000000f;
+ mImageRotationLimit = (float) mResources.getInteger(R.integer.max_image_rotation);
mTableCapacity = mResources.getInteger(R.integer.table_capacity);
+ mManualImageRotation = mResources.getBoolean(R.bool.enable_manual_image_rotation);
+ mTapToExit = mResources.getBoolean(R.bool.enable_tap_to_exit);
mOnTable = new LinkedList<View>();
mOptions = new BitmapFactory.Options();
mOptions.inTempStorage = new byte[32768];
mLocalSource = new LocalSource(getContext());
mLauncher = new Launcher(this);
mStarted = false;
- final ViewConfiguration configuration = ViewConfiguration.get(getContext());
- mTouchSlop = configuration.getScaledTouchSlop();
- mTapTimeout = configuration.getTapTimeout();
}
public boolean hasSelection() {
@@ -186,7 +468,9 @@ public class PhotoTable extends Dream {
dropOnTable(getSelected());
clearSelection();
} else {
- mDream.finish();
+ if (mTapToExit) {
+ mDream.finish();
+ }
}
return true;
}
@@ -352,13 +636,13 @@ public class PhotoTable extends Dream {
int width = ((Integer) photo.getTag(R.id.photo_width));
int height = ((Integer) photo.getTag(R.id.photo_height));
photo.setRotation(-100.0f);
- photo.setX(-width);
- photo.setY(-height);
+ photo.setX(-mLongSide);
+ photo.setY(-mLongSide);
dropOnTable(photo);
}
private void dropOnTable(final View photo) {
- float angle = randfrange(-60, 60f);
+ float angle = randfrange(-mImageRotationLimit, mImageRotationLimit);
PointF p = randInCenter((float) sRNG.nextGaussian(), (float) sRNG.nextGaussian(),
mWidth, mHeight);
float x = p.x;
@@ -371,8 +655,8 @@ public class PhotoTable extends Dream {
float width = (float) ((Integer) photo.getTag(R.id.photo_width)).intValue();
float height = (float) ((Integer) photo.getTag(R.id.photo_height)).intValue();
- x -= width / 2f;
- y -= height / 2f;
+ x -= mTableRatio * mLongSide / 2f;
+ y -= mTableRatio * mLongSide / 2f;
log("fixed offset is " + x + ", " + y);
float dx = x - x0;
@@ -386,12 +670,13 @@ public class PhotoTable extends Dream {
// toss onto table
photo.animate()
.withLayer()
- .scaleX(0.5f / mImageRatio)
- .scaleY(0.5f / mImageRatio)
+ .scaleX(mTableRatio / mImageRatio)
+ .scaleY(mTableRatio / mImageRatio)
.rotation(angle)
.x(x)
- .y(y)
+ .y(y)
.setDuration(duration)
+ .setInterpolator(new DecelerateInterpolator())
.withEndAction(new Runnable() {
@Override
public void run() {
@@ -401,141 +686,7 @@ public class PhotoTable extends Dream {
}
});
- photo.setOnTouchListener(new OnTouchListener() {
- private static final int INVALID_POINTER = -1;
- private static final int MAX_POINTER_COUNT = 10;
- private float mInitialTouchX;
- private float mInitialTouchY;
- private float mInitialTouchA;
- private long mInitialTouchTime;
- private float mInitialTargetX;
- private float mInitialTargetY;
- private float mInitialTargetA;
- private int mA = INVALID_POINTER;
- private int mB = INVALID_POINTER;
- private float[] pts = new float[MAX_POINTER_COUNT];
-
- /** Get angle defined by first two touches, in degrees */
- private float getAngle(View target, MotionEvent ev) {
- float alpha = 0f;
- int a = ev.findPointerIndex(mA);
- int b = ev.findPointerIndex(mB);
- if (a >=0 && b >=0) {
- alpha = (float) (Math.atan2(pts[2*a + 1] - pts[2*b + 1],
- pts[2*a] - pts[2*b]) *
- 180f / Math.PI);
- }
- return alpha;
- }
-
- private void resetTouch(View target) {
- mInitialTouchX = -1;
- mInitialTouchY = -1;
- mInitialTouchA = 0f;
- mInitialTargetX = (float) target.getX();
- mInitialTargetY = (float) target.getY();
- mInitialTargetA = (float) target.getRotation();
- }
-
- @Override
- public boolean onTouch(View target, MotionEvent ev) {
- final int action = ev.getActionMasked();
-
- // compute raw coordinates
- for(int i = 0; i < 10 && i < ev.getPointerCount(); i++) {
- pts[i*2] = ev.getX(i);
- pts[i*2 + 1] = ev.getY(i);
- }
- target.getMatrix().mapPoints(pts);
-
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- moveToBackOfQueue(target);
- mInitialTouchTime = ev.getEventTime();
- mA = ev.getPointerId(ev.getActionIndex());
- resetTouch(target);
- log("action down: " + mA + ", " + mB);
- break;
-
- case MotionEvent.ACTION_POINTER_DOWN:
- if (mB == INVALID_POINTER) {
- mB = ev.getPointerId(ev.getActionIndex());
- mInitialTouchA = getAngle(target, ev);
- }
- log("action pointer down: " + mA + ", " + mB);
- break;
-
- case MotionEvent.ACTION_POINTER_UP:
- if (mB == ev.getPointerId(ev.getActionIndex())) {
- mB = INVALID_POINTER;
- mInitialTargetA = (float) target.getRotation();
- }
- if (mA == ev.getPointerId(ev.getActionIndex())) {
- mA = mB;
- resetTouch(target);
- mB = INVALID_POINTER;
- }
- log("action pointer up: " + mA + ", " + mB);
- break;
-
- case MotionEvent.ACTION_MOVE: {
- if (mA != INVALID_POINTER) {
- log("action move: " + mA + ", " + mB);
- int idx = ev.findPointerIndex(mA);
- float x = pts[2 * idx];
- float y = pts[2 * idx + 1];
- if (mInitialTouchX == -1 && mInitialTouchY == -1) {
- mInitialTouchX = x;
- mInitialTouchY = y;
- }
- if (getSelected() != target) {
- target.animate().cancel();
-
- target.setX((int) (mInitialTargetX + x - mInitialTouchX));
- target.setY((int) (mInitialTargetY + y - mInitialTouchY));
- if (mB != INVALID_POINTER) {
- float a = getAngle(target, ev);
- target.setRotation(
- (int) (mInitialTargetA + a - mInitialTouchA));
- }
- }
- }
- }
- break;
-
- case MotionEvent.ACTION_UP: {
- if (mA != INVALID_POINTER) {
- int idx = ev.findPointerIndex(mA);
- float x = pts[2 * idx];
- float y = pts[2 * idx + 1];
- if (mInitialTouchX == -1 && mInitialTouchY == -1) {
- mInitialTouchX = x;
- mInitialTouchY = y;
- }
- double distance = Math.hypot(x - mInitialTouchX,
- y - mInitialTouchY);
- if (getSelected() == target) {
- dropOnTable(target);
- clearSelection();
- } else if ((ev.getEventTime() - mInitialTouchTime) < mTapTimeout &&
- distance < mTouchSlop) {
- // tap
- target.animate().cancel();
- setSelection(target);
- }
- mA = INVALID_POINTER;
- mB = INVALID_POINTER;
- log("action up: " + mA + ", " + mB);
- }
- }
- break;
-
- case MotionEvent.ACTION_CANCEL:
- break;
- }
- return true;
- }
- });
+ photo.setOnTouchListener(new PhotoTouchListener(getContext(), this));
}
/** wrap all orientations to the interval [-180, 180). */