diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 0076c51326738..a773b2242eaab 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -202,7 +202,7 @@
#40000000
- #9444
+ #6444
#F8F9FA
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/CropView.java b/packages/SystemUI/src/com/android/systemui/screenshot/CropView.java
index 1ec175c01be7b..78ee896075703 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/CropView.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/CropView.java
@@ -16,8 +16,6 @@
package com.android.systemui.screenshot;
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
@@ -25,6 +23,7 @@ import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
+import android.graphics.RectF;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -32,6 +31,7 @@ import android.util.AttributeSet;
import android.util.IntArray;
import android.util.Log;
import android.util.MathUtils;
+import android.util.Range;
import android.view.MotionEvent;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
@@ -49,29 +49,30 @@ import com.android.systemui.R;
*/
public class CropView extends View {
private static final String TAG = "CropView";
+
public enum CropBoundary {
- NONE, TOP, BOTTOM
+ NONE, TOP, BOTTOM, LEFT, RIGHT
}
private final float mCropTouchMargin;
private final Paint mShadePaint;
private final Paint mHandlePaint;
- // Top and bottom crops are stored as floats [0, 1], representing the top and bottom of the
- // view, respectively.
- private float mTopCrop = 0f;
- private float mBottomCrop = 1f;
-
- // When the user is dragging a handle, these variables store the distance between the top/bottom
- // crop values and
- private float mTopDelta = 0f;
- private float mBottomDelta = 0f;
+ // Crop rect with each element represented as [0,1] along its proper axis.
+ private RectF mCrop = new RectF(0, 0, 1, 1);
private int mExtraTopPadding;
private int mExtraBottomPadding;
+ private int mImageWidth;
private CropBoundary mCurrentDraggingBoundary = CropBoundary.NONE;
+ // The starting value of mCurrentDraggingBoundary's crop, used to compute touch deltas.
+ private float mMovementStartValue;
private float mStartingY; // y coordinate of ACTION_DOWN
+ private float mStartingX;
+ // The allowable values for the current boundary being dragged
+ private Range mMotionRange;
+
private CropInteractionListener mCropInteractionListener;
public CropView(Context context, @Nullable AttributeSet attrs) {
@@ -86,6 +87,7 @@ public class CropView extends View {
mShadePaint.setColor(t.getColor(R.styleable.CropView_scrimColor, Color.TRANSPARENT));
mHandlePaint = new Paint();
mHandlePaint.setColor(t.getColor(R.styleable.CropView_handleColor, Color.BLACK));
+ mHandlePaint.setStrokeCap(Paint.Cap.ROUND);
mHandlePaint.setStrokeWidth(
t.getDimensionPixelSize(R.styleable.CropView_handleThickness, 20));
t.recycle();
@@ -100,8 +102,7 @@ public class CropView extends View {
Parcelable superState = super.onSaveInstanceState();
SavedState ss = new SavedState(superState);
- ss.mTopBoundary = getTopBoundary();
- ss.mBottomBoundary = getBottomBoundary();
+ ss.mCrop = mCrop;
return ss;
}
@@ -110,45 +111,67 @@ public class CropView extends View {
SavedState ss = (SavedState) state;
super.onRestoreInstanceState(ss.getSuperState());
- setBoundaryTo(CropBoundary.TOP, ss.mTopBoundary);
- setBoundaryTo(CropBoundary.BOTTOM, ss.mBottomBoundary);
+ mCrop = ss.mCrop;
}
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
- float top = mTopCrop + mTopDelta;
- float bottom = mBottomCrop + mBottomDelta;
- drawShade(canvas, 0, top);
- drawShade(canvas, bottom, 1f);
- drawHandle(canvas, top, /* draw the handle tab down */ false);
- drawHandle(canvas, bottom, /* draw the handle tab up */ true);
+ drawShade(canvas, 0, 0, 1, mCrop.top);
+ drawShade(canvas, 0, mCrop.bottom, 1, 1);
+ drawShade(canvas, 0, mCrop.top, mCrop.left, mCrop.bottom);
+ drawShade(canvas, mCrop.right, mCrop.top, 1, mCrop.bottom);
+ drawHorizontalHandle(canvas, mCrop.top, /* draw the handle tab up */ true);
+ drawHorizontalHandle(canvas, mCrop.bottom, /* draw the handle tab down */ false);
+ drawVerticalHandle(canvas, mCrop.left, /* left */ true);
+ drawVerticalHandle(canvas, mCrop.right, /* right */ false);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
- int topPx = fractionToPixels(mTopCrop);
- int bottomPx = fractionToPixels(mBottomCrop);
+ int topPx = fractionToVerticalPixels(mCrop.top);
+ int bottomPx = fractionToVerticalPixels(mCrop.bottom);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
- mCurrentDraggingBoundary = nearestBoundary(event, topPx, bottomPx);
+ mCurrentDraggingBoundary = nearestBoundary(event, topPx, bottomPx,
+ fractionToHorizontalPixels(mCrop.left),
+ fractionToHorizontalPixels(mCrop.right));
if (mCurrentDraggingBoundary != CropBoundary.NONE) {
mStartingY = event.getY();
+ mStartingX = event.getX();
+ mMovementStartValue = getBoundaryPosition(mCurrentDraggingBoundary);
updateListener(event);
+ switch (mCurrentDraggingBoundary) {
+ case TOP:
+ mMotionRange = new Range<>(0f,
+ mCrop.bottom - pixelDistanceToFraction(mCropTouchMargin,
+ CropBoundary.BOTTOM));
+ break;
+ case BOTTOM:
+ mMotionRange = new Range<>(
+ mCrop.top + pixelDistanceToFraction(mCropTouchMargin,
+ CropBoundary.TOP), 1f);
+ break;
+ case LEFT:
+ mMotionRange = new Range<>(0f,
+ mCrop.right - pixelDistanceToFraction(mCropTouchMargin,
+ CropBoundary.RIGHT));
+ break;
+ case RIGHT:
+ mMotionRange = new Range<>(
+ mCrop.left + pixelDistanceToFraction(mCropTouchMargin,
+ CropBoundary.LEFT), 1f);
+ break;
+ }
}
return true;
case MotionEvent.ACTION_MOVE:
if (mCurrentDraggingBoundary != CropBoundary.NONE) {
- float delta = event.getY() - mStartingY;
- if (mCurrentDraggingBoundary == CropBoundary.TOP) {
- mTopDelta = pixelDistanceToFraction((int) MathUtils.constrain(delta,
- -topPx + mExtraTopPadding,
- bottomPx - 2 * mCropTouchMargin - topPx));
- } else { // Bottom
- mBottomDelta = pixelDistanceToFraction((int) MathUtils.constrain(delta,
- topPx + 2 * mCropTouchMargin - bottomPx,
- getHeight() - bottomPx - mExtraBottomPadding));
- }
+ float deltaPx = isVertical(mCurrentDraggingBoundary) ? event.getY() - mStartingY
+ : event.getX() - mStartingX;
+ float delta = pixelDistanceToFraction((int) deltaPx, mCurrentDraggingBoundary);
+ setBoundaryPosition(mCurrentDraggingBoundary,
+ mMotionRange.clamp(mMovementStartValue + delta));
updateListener(event);
invalidate();
return true;
@@ -156,8 +179,6 @@ public class CropView extends View {
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
if (mCurrentDraggingBoundary != CropBoundary.NONE) {
- // Commit the delta to the stored crop values.
- commitDeltas(mCurrentDraggingBoundary);
updateListener(event);
}
}
@@ -167,22 +188,46 @@ public class CropView extends View {
/**
* Set the given boundary to the given value without animation.
*/
- public void setBoundaryTo(CropBoundary boundary, float value) {
+ public void setBoundaryPosition(CropBoundary boundary, float position) {
switch (boundary) {
case TOP:
- mTopCrop = value;
+ mCrop.top = position;
break;
case BOTTOM:
- mBottomCrop = value;
+ mCrop.bottom = position;
+ break;
+ case LEFT:
+ mCrop.left = position;
+ break;
+ case RIGHT:
+ mCrop.right = position;
break;
case NONE:
- Log.w(TAG, "No boundary selected for animation");
+ Log.w(TAG, "No boundary selected");
break;
}
invalidate();
}
+ private float getBoundaryPosition(CropBoundary boundary) {
+ switch (boundary) {
+ case TOP:
+ return mCrop.top;
+ case BOTTOM:
+ return mCrop.bottom;
+ case LEFT:
+ return mCrop.left;
+ case RIGHT:
+ return mCrop.right;
+ }
+ return 0;
+ }
+
+ private static boolean isVertical(CropBoundary boundary) {
+ return boundary == CropBoundary.TOP || boundary == CropBoundary.BOTTOM;
+ }
+
/**
* Animate the given boundary to the given value.
*/
@@ -191,28 +236,13 @@ public class CropView extends View {
Log.w(TAG, "No boundary selected for animation");
return;
}
- float totalDelta = (boundary == CropBoundary.TOP) ? (value - mTopCrop)
- : (value - mBottomCrop);
+ float start = getBoundaryPosition(boundary);
ValueAnimator animator = new ValueAnimator();
animator.addUpdateListener(animation -> {
- if (boundary == CropBoundary.TOP) {
- mTopDelta = animation.getAnimatedFraction() * totalDelta;
- } else {
- mBottomDelta = animation.getAnimatedFraction() * totalDelta;
- }
+ setBoundaryPosition(boundary,
+ MathUtils.lerp(start, value, animation.getAnimatedFraction()));
invalidate();
});
- animator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- commitDeltas(boundary);
- }
-
- @Override
- public void onAnimationCancel(Animator animation) {
- commitDeltas(boundary);
- }
- });
animator.setFloatValues(0f, 1f);
animator.setDuration(750);
animator.setInterpolator(new FastOutSlowInInterpolator());
@@ -230,65 +260,79 @@ public class CropView extends View {
}
/**
- * @return value [0,1] representing the position of the top crop boundary. Does not reflect
- * changes from any in-progress touch input.
+ * Set the pixel width of the image on the screen (on-screen dimension, not actual bitmap
+ * dimension)
*/
- public float getTopBoundary() {
- return mTopCrop;
+ public void setImageWidth(int width) {
+ mImageWidth = width;
+ invalidate();
}
/**
- * @return value [0,1] representing the position of the bottom crop boundary. Does not reflect
- * changes from any in-progress touch input.
+ * @return RectF with values [0,1] representing the position of the boundaries along image axes.
*/
- public float getBottomBoundary() {
- return mBottomCrop;
+ public Rect getCropBoundaries(int imageWidth, int imageHeight) {
+ return new Rect((int) (mCrop.left * imageWidth), (int) (mCrop.top * imageHeight),
+ (int) (mCrop.right * imageWidth), (int) (mCrop.bottom * imageHeight));
}
public void setCropInteractionListener(CropInteractionListener listener) {
mCropInteractionListener = listener;
}
- private void commitDeltas(CropBoundary boundary) {
- if (boundary == CropBoundary.TOP) {
- mTopCrop += mTopDelta;
- mTopDelta = 0;
- } else if (boundary == CropBoundary.BOTTOM) {
- mBottomCrop += mBottomDelta;
- mBottomDelta = 0;
- }
- }
-
private void updateListener(MotionEvent event) {
- if (mCropInteractionListener != null) {
- float boundaryPosition = (mCurrentDraggingBoundary == CropBoundary.TOP)
- ? mTopCrop + mTopDelta : mBottomCrop + mBottomDelta;
+ if (mCropInteractionListener != null && (isVertical(mCurrentDraggingBoundary))) {
+ float boundaryPosition = getBoundaryPosition(mCurrentDraggingBoundary);
mCropInteractionListener.onCropMotionEvent(event, mCurrentDraggingBoundary,
- boundaryPosition, fractionToPixels(boundaryPosition));
+ boundaryPosition, fractionToVerticalPixels(boundaryPosition),
+ (mCrop.left + mCrop.right) / 2);
}
}
- private void drawShade(Canvas canvas, float fracStart, float fracEnd) {
- canvas.drawRect(0, fractionToPixels(fracStart), getWidth(),
- fractionToPixels(fracEnd), mShadePaint);
+ /**
+ * Draw a shade to the given canvas with the given [0,1] fractional image bounds.
+ */
+ private void drawShade(Canvas canvas, float left, float top, float right, float bottom) {
+ canvas.drawRect(fractionToHorizontalPixels(left), fractionToVerticalPixels(top),
+ fractionToHorizontalPixels(right),
+ fractionToVerticalPixels(bottom), mShadePaint);
}
- private void drawHandle(Canvas canvas, float frac, boolean handleTabUp) {
- int y = fractionToPixels(frac);
- canvas.drawLine(0, y, getWidth(), y, mHandlePaint);
- float radius = 15 * getResources().getDisplayMetrics().density;
- float x = getWidth() * .9f;
+ private void drawHorizontalHandle(Canvas canvas, float frac, boolean handleTabUp) {
+ int y = fractionToVerticalPixels(frac);
+ canvas.drawLine(fractionToHorizontalPixels(mCrop.left), y,
+ fractionToHorizontalPixels(mCrop.right), y, mHandlePaint);
+ float radius = 8 * getResources().getDisplayMetrics().density;
+ int x = (fractionToHorizontalPixels(mCrop.left) + fractionToHorizontalPixels(mCrop.right))
+ / 2;
canvas.drawArc(x - radius, y - radius, x + radius, y + radius, handleTabUp ? 180 : 0, 180,
true, mHandlePaint);
}
+ private void drawVerticalHandle(Canvas canvas, float frac, boolean handleTabLeft) {
+ int x = fractionToHorizontalPixels(frac);
+ canvas.drawLine(x, fractionToVerticalPixels(mCrop.top), x,
+ fractionToVerticalPixels(mCrop.bottom), mHandlePaint);
+ float radius = 8 * getResources().getDisplayMetrics().density;
+ int y = (fractionToVerticalPixels(getBoundaryPosition(CropBoundary.TOP))
+ + fractionToVerticalPixels(
+ getBoundaryPosition(CropBoundary.BOTTOM))) / 2;
+ canvas.drawArc(x - radius, y - radius, x + radius, y + radius, handleTabLeft ? 90 : 270,
+ 180,
+ true, mHandlePaint);
+ }
+
/**
* Convert the given fraction position to pixel position within the View.
*/
- private int fractionToPixels(float frac) {
+ private int fractionToVerticalPixels(float frac) {
return (int) (mExtraTopPadding + frac * getImageHeight());
}
+ private int fractionToHorizontalPixels(float frac) {
+ return (int) ((getWidth() - mImageWidth) / 2 + frac * mImageWidth);
+ }
+
private int getImageHeight() {
return getHeight() - mExtraTopPadding - mExtraBottomPadding;
}
@@ -296,17 +340,30 @@ public class CropView extends View {
/**
* Convert the given pixel distance to fraction of the image.
*/
- private float pixelDistanceToFraction(int px) {
- return px / (float) getImageHeight();
+ private float pixelDistanceToFraction(float px, CropBoundary boundary) {
+ if (isVertical(boundary)) {
+ return px / getImageHeight();
+ } else {
+ return px / mImageWidth;
+ }
}
- private CropBoundary nearestBoundary(MotionEvent event, int topPx, int bottomPx) {
+ private CropBoundary nearestBoundary(MotionEvent event, int topPx, int bottomPx, int leftPx,
+ int rightPx) {
if (Math.abs(event.getY() - topPx) < mCropTouchMargin) {
return CropBoundary.TOP;
}
if (Math.abs(event.getY() - bottomPx) < mCropTouchMargin) {
return CropBoundary.BOTTOM;
}
+ if (event.getY() > topPx || event.getY() < bottomPx) {
+ if (Math.abs(event.getX() - leftPx) < mCropTouchMargin) {
+ return CropBoundary.LEFT;
+ }
+ if (Math.abs(event.getX() - rightPx) < mCropTouchMargin) {
+ return CropBoundary.RIGHT;
+ }
+ }
return CropBoundary.NONE;
}
@@ -321,10 +378,10 @@ public class CropView extends View {
@Override
protected int getVirtualViewAt(float x, float y) {
- if (Math.abs(y - fractionToPixels(mTopCrop)) < mCropTouchMargin) {
+ if (Math.abs(y - fractionToVerticalPixels(mCrop.top)) < mCropTouchMargin) {
return TOP_HANDLE_ID;
}
- if (Math.abs(y - fractionToPixels(mBottomCrop)) < mCropTouchMargin) {
+ if (Math.abs(y - fractionToVerticalPixels(mCrop.bottom)) < mCropTouchMargin) {
return BOTTOM_HANDLE_ID;
}
return ExploreByTouchHelper.INVALID_ID;
@@ -338,7 +395,7 @@ public class CropView extends View {
@Override
protected void onPopulateEventForVirtualView(int virtualViewId, AccessibilityEvent event) {
- switch(virtualViewId) {
+ switch (virtualViewId) {
case TOP_HANDLE_ID:
event.setContentDescription(
getResources().getString(R.string.screenshot_top_boundary));
@@ -353,16 +410,16 @@ public class CropView extends View {
@Override
protected void onPopulateNodeForVirtualView(int virtualViewId,
AccessibilityNodeInfo node) {
- switch(virtualViewId) {
+ switch (virtualViewId) {
case TOP_HANDLE_ID:
node.setContentDescription(
getResources().getString(R.string.screenshot_top_boundary));
- setNodePositions(mTopCrop, node);
+ setNodePositions(mCrop.top, node);
break;
case BOTTOM_HANDLE_ID:
node.setContentDescription(
getResources().getString(R.string.screenshot_bottom_boundary));
- setNodePositions(mBottomCrop, node);
+ setNodePositions(mCrop.bottom, node);
break;
}
@@ -380,7 +437,7 @@ public class CropView extends View {
}
private void setNodePositions(float fraction, AccessibilityNodeInfo node) {
- int pixels = fractionToPixels(fraction);
+ int pixels = fractionToVerticalPixels(fraction);
Rect rect = new Rect(0, (int) (pixels - mCropTouchMargin),
getWidth(), (int) (pixels + mCropTouchMargin));
node.setBoundsInParent(rect);
@@ -400,12 +457,11 @@ public class CropView extends View {
* boundaries.
*/
void onCropMotionEvent(MotionEvent event, CropBoundary boundary, float boundaryPosition,
- int boundaryPositionPx);
+ int boundaryPositionPx, float horizontalCenter);
}
static class SavedState extends BaseSavedState {
- float mTopBoundary;
- float mBottomBoundary;
+ RectF mCrop;
/**
* Constructor called from {@link CropView#onSaveInstanceState()}
@@ -419,15 +475,13 @@ public class CropView extends View {
*/
private SavedState(Parcel in) {
super(in);
- mTopBoundary = in.readFloat();
- mBottomBoundary = in.readFloat();
+ mCrop = in.readParcelable(ClassLoader.getSystemClassLoader());
}
@Override
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
- out.writeFloat(mTopBoundary);
- out.writeFloat(mBottomBoundary);
+ out.writeParcelable(mCrop, 0);
}
public static final Parcelable.Creator CREATOR
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java b/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java
index 6a004c2c01dc0..11c7c9a9934cd 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java
@@ -128,7 +128,7 @@ public class LongScreenshotActivity extends Activity {
mPreview.addOnLayoutChangeListener(
(v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) ->
- updateCropLocation());
+ updateImageDimensions());
Intent intent = getIntent();
mScrollCaptureResponse = intent.getParcelableExtra(EXTRA_CAPTURE_RESPONSE);
@@ -206,7 +206,7 @@ public class LongScreenshotActivity extends Activity {
Log.d(TAG, "onCaptureCompleted(longScreenshot=" + longScreenshot + ")");
mLongScreenshot = longScreenshot;
mPreview.setImageDrawable(mLongScreenshot.getDrawable());
- updateCropLocation();
+ updateImageDimensions();
mMagnifierView.setDrawable(mLongScreenshot.getDrawable(),
mLongScreenshot.getWidth(), mLongScreenshot.getHeight());
// Original boundaries go from the image tile set's y=0 to y=pageSize, so
@@ -363,10 +363,8 @@ public class LongScreenshotActivity extends Activity {
return;
}
- Rect bounds = new Rect(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
- int height = bounds.height();
- bounds.top = (int) (height * mCropView.getTopBoundary());
- bounds.bottom = (int) (height * mCropView.getBottomBoundary());
+ Rect bounds = mCropView.getCropBoundaries(drawable.getIntrinsicWidth(),
+ drawable.getIntrinsicHeight());
if (bounds.isEmpty()) {
Log.w(TAG, "Crop bounds empty, skipping export.");
@@ -404,7 +402,7 @@ public class LongScreenshotActivity extends Activity {
}
}
- private void updateCropLocation() {
+ private void updateImageDimensions() {
Drawable drawable = mPreview.getDrawable();
if (drawable == null) {
return;
@@ -419,9 +417,12 @@ public class LongScreenshotActivity extends Activity {
float imageHeight = mPreview.getHeight() * viewRatio / imageRatio;
int extraPadding = (int) (mPreview.getHeight() - imageHeight) / 2;
mCropView.setExtraPadding(extraPadding, extraPadding);
+ mCropView.setImageWidth(mPreview.getWidth());
} else {
// Image is full height
mCropView.setExtraPadding(0, 0);
+ mCropView.setImageWidth((int) (mPreview.getHeight() * imageRatio));
}
+
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/MagnifierView.java b/packages/SystemUI/src/com/android/systemui/screenshot/MagnifierView.java
index 90f304262ea19..08cd91ccada54 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/MagnifierView.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/MagnifierView.java
@@ -58,6 +58,7 @@ public class MagnifierView extends View implements CropView.CropInteractionListe
private float mCheckerboardBoxSize = 40;
private float mLastCropPosition;
+ private float mLastCenter = 0.5f;
private CropView.CropBoundary mCropBoundary;
private ViewPropertyAnimator mTranslationAnimator;
@@ -131,7 +132,7 @@ public class MagnifierView extends View implements CropView.CropInteractionListe
canvas.save();
// Translate such that the center of this view represents the center of the crop
// boundary.
- canvas.translate(-mDrawable.getBounds().width() / 2 + getWidth() / 2,
+ canvas.translate(-mDrawable.getBounds().width() * mLastCenter + getWidth() / 2,
-mDrawable.getBounds().height() * mLastCropPosition + getHeight() / 2);
mDrawable.draw(canvas);
canvas.restore();
@@ -148,8 +149,9 @@ public class MagnifierView extends View implements CropView.CropInteractionListe
@Override
public void onCropMotionEvent(MotionEvent event, CropView.CropBoundary boundary,
- float cropPosition, int cropPositionPx) {
+ float cropPosition, int cropPositionPx, float horizontalCenter) {
mCropBoundary = boundary;
+ mLastCenter = horizontalCenter;
boolean touchOnRight = event.getX() > getParentWidth() / 2;
float translateXTarget = touchOnRight ? 0 : getParentWidth() - getWidth();
switch (event.getAction()) {