Fields Summary |
---|
static final String | TAG |
private static final boolean | DEBUG |
private static final boolean | DEBUG_INVALIDATE |
private static final boolean | SLOW_ANIMATIONS |
private static final boolean | CONSTRAIN_SWIPE |
private static final boolean | FADE_OUT_DURING_SWIPE |
private static final boolean | DISMISS_IF_SWIPED_FAR_ENOUGH |
public static final int | X |
public static final int | Y |
private static android.view.animation.LinearInterpolator | sLinearInterpolator |
private final android.view.animation.Interpolator | mFastOutLinearInInterpolator |
private float | SWIPE_ESCAPE_VELOCITY |
private int | DEFAULT_ESCAPE_ANIMATION_DURATION |
private int | MAX_ESCAPE_ANIMATION_DURATION |
private int | MAX_DISMISS_VELOCITY |
private static final int | SNAP_ANIM_LEN |
public static float | SWIPE_PROGRESS_FADE_START |
static final float | SWIPE_PROGRESS_FADE_END |
private float | mMinSwipeProgress |
private float | mMaxSwipeProgress |
private float | mPagingTouchSlop |
private Callback | mCallback |
private android.os.Handler | mHandler |
private int | mSwipeDirection |
private android.view.VelocityTracker | mVelocityTracker |
private float | mInitialTouchPos |
private boolean | mDragging |
private android.view.View | mCurrView |
private android.view.View | mCurrAnimView |
private boolean | mCanCurrViewBeDimissed |
private float | mDensityScale |
private boolean | mLongPressSent |
private LongPressListener | mLongPressListener |
private Runnable | mWatchLongPress |
private long | mLongPressTimeout |
private final int[] | mTmpPos |
private int | mFalsingThreshold |
private boolean | mTouchAboveFalsingThreshold |
Methods Summary |
---|
private android.animation.ObjectAnimator | createTranslationAnimation(android.view.View v, float newPos)
ObjectAnimator anim = ObjectAnimator.ofFloat(v,
mSwipeDirection == X ? "translationX" : "translationY", newPos);
return anim;
|
public void | dismissChild(android.view.View view, float velocity)
dismissChild(view, velocity, null, 0, false, 0);
|
public void | dismissChild(android.view.View view, float velocity, java.lang.Runnable endAction, long delay, boolean useAccelerateInterpolator, long fixedDuration)
final View animView = mCallback.getChildContentView(view);
final boolean canAnimViewBeDismissed = mCallback.canChildBeDismissed(view);
float newPos;
boolean isLayoutRtl = view.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
if (velocity < 0
|| (velocity == 0 && getTranslation(animView) < 0)
// if we use the Menu to dismiss an item in landscape, animate up
|| (velocity == 0 && getTranslation(animView) == 0 && mSwipeDirection == Y)
// if the language is rtl we prefer swiping to the left
|| (velocity == 0 && getTranslation(animView) == 0 && isLayoutRtl)) {
newPos = -getSize(animView);
} else {
newPos = getSize(animView);
}
long duration;
if (fixedDuration == 0) {
duration = MAX_ESCAPE_ANIMATION_DURATION;
if (velocity != 0) {
duration = Math.min(duration,
(int) (Math.abs(newPos - getTranslation(animView)) * 1000f / Math
.abs(velocity))
);
} else {
duration = DEFAULT_ESCAPE_ANIMATION_DURATION;
}
} else {
duration = fixedDuration;
}
animView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
ObjectAnimator anim = createTranslationAnimation(animView, newPos);
if (useAccelerateInterpolator) {
anim.setInterpolator(mFastOutLinearInInterpolator);
} else {
anim.setInterpolator(sLinearInterpolator);
}
anim.setDuration(duration);
if (delay > 0) {
anim.setStartDelay(delay);
}
anim.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator animation) {
mCallback.onChildDismissed(view);
if (endAction != null) {
endAction.run();
}
animView.setLayerType(View.LAYER_TYPE_NONE, null);
}
});
anim.addUpdateListener(new AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
updateSwipeProgressFromOffset(animView, canAnimViewBeDismissed);
}
});
anim.start();
|
private int | getFalsingThreshold()
float factor = mCallback.getFalsingThresholdFactor();
return (int) (mFalsingThreshold * factor);
|
private float | getPerpendicularVelocity(android.view.VelocityTracker vt)
return mSwipeDirection == X ? vt.getYVelocity() :
vt.getXVelocity();
|
private float | getPos(android.view.MotionEvent ev)
return mSwipeDirection == X ? ev.getX() : ev.getY();
|
private float | getSize(android.view.View v)
return mSwipeDirection == X ? v.getMeasuredWidth() :
v.getMeasuredHeight();
|
private float | getSwipeProgressForOffset(android.view.View view)
float viewSize = getSize(view);
final float fadeSize = SWIPE_PROGRESS_FADE_END * viewSize;
float result = 1.0f;
float pos = getTranslation(view);
if (pos >= viewSize * SWIPE_PROGRESS_FADE_START) {
result = 1.0f - (pos - viewSize * SWIPE_PROGRESS_FADE_START) / fadeSize;
} else if (pos < viewSize * (1.0f - SWIPE_PROGRESS_FADE_START)) {
result = 1.0f + (viewSize * SWIPE_PROGRESS_FADE_START + pos) / fadeSize;
}
return Math.min(Math.max(mMinSwipeProgress, result), mMaxSwipeProgress);
|
private float | getTranslation(android.view.View v)
return mSwipeDirection == X ? v.getTranslationX() : v.getTranslationY();
|
private float | getVelocity(android.view.VelocityTracker vt)
return mSwipeDirection == X ? vt.getXVelocity() :
vt.getYVelocity();
|
public static void | invalidateGlobalRegion(android.view.View view)
invalidateGlobalRegion(
view,
new RectF(view.getLeft(), view.getTop(), view.getRight(), view.getBottom()));
|
public static void | invalidateGlobalRegion(android.view.View view, android.graphics.RectF childBounds)
//childBounds.offset(view.getTranslationX(), view.getTranslationY());
if (DEBUG_INVALIDATE)
Log.v(TAG, "-------------");
while (view.getParent() != null && view.getParent() instanceof View) {
view = (View) view.getParent();
view.getMatrix().mapRect(childBounds);
view.invalidate((int) Math.floor(childBounds.left),
(int) Math.floor(childBounds.top),
(int) Math.ceil(childBounds.right),
(int) Math.ceil(childBounds.bottom));
if (DEBUG_INVALIDATE) {
Log.v(TAG, "INVALIDATE(" + (int) Math.floor(childBounds.left)
+ "," + (int) Math.floor(childBounds.top)
+ "," + (int) Math.ceil(childBounds.right)
+ "," + (int) Math.ceil(childBounds.bottom));
}
}
|
public boolean | onInterceptTouchEvent(android.view.MotionEvent ev)
final int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
mTouchAboveFalsingThreshold = false;
mDragging = false;
mLongPressSent = false;
mCurrView = mCallback.getChildAtPosition(ev);
mVelocityTracker.clear();
if (mCurrView != null) {
mCurrAnimView = mCallback.getChildContentView(mCurrView);
mCanCurrViewBeDimissed = mCallback.canChildBeDismissed(mCurrView);
mVelocityTracker.addMovement(ev);
mInitialTouchPos = getPos(ev);
if (mLongPressListener != null) {
if (mWatchLongPress == null) {
mWatchLongPress = new Runnable() {
@Override
public void run() {
if (mCurrView != null && !mLongPressSent) {
mLongPressSent = true;
mCurrView.sendAccessibilityEvent(
AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
mCurrView.getLocationOnScreen(mTmpPos);
final int x = (int) ev.getRawX() - mTmpPos[0];
final int y = (int) ev.getRawY() - mTmpPos[1];
mLongPressListener.onLongPress(mCurrView, x, y);
}
}
};
}
mHandler.postDelayed(mWatchLongPress, mLongPressTimeout);
}
}
break;
case MotionEvent.ACTION_MOVE:
if (mCurrView != null && !mLongPressSent) {
mVelocityTracker.addMovement(ev);
float pos = getPos(ev);
float delta = pos - mInitialTouchPos;
if (Math.abs(delta) > mPagingTouchSlop) {
mCallback.onBeginDrag(mCurrView);
mDragging = true;
mInitialTouchPos = getPos(ev) - getTranslation(mCurrAnimView);
removeLongPressCallback();
}
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
final boolean captured = (mDragging || mLongPressSent);
mDragging = false;
mCurrView = null;
mCurrAnimView = null;
mLongPressSent = false;
removeLongPressCallback();
if (captured) return true;
break;
}
return mDragging || mLongPressSent;
|
public boolean | onTouchEvent(android.view.MotionEvent ev)
if (mLongPressSent) {
return true;
}
if (!mDragging) {
if (mCallback.getChildAtPosition(ev) != null) {
// We are dragging directly over a card, make sure that we also catch the gesture
// even if nobody else wants the touch event.
onInterceptTouchEvent(ev);
return true;
} else {
// We are not doing anything, make sure the long press callback
// is not still ticking like a bomb waiting to go off.
removeLongPressCallback();
return false;
}
}
mVelocityTracker.addMovement(ev);
final int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_OUTSIDE:
case MotionEvent.ACTION_MOVE:
if (mCurrView != null) {
float delta = getPos(ev) - mInitialTouchPos;
float absDelta = Math.abs(delta);
if (absDelta >= getFalsingThreshold()) {
mTouchAboveFalsingThreshold = true;
}
// don't let items that can't be dismissed be dragged more than
// maxScrollDistance
if (CONSTRAIN_SWIPE && !mCallback.canChildBeDismissed(mCurrView)) {
float size = getSize(mCurrAnimView);
float maxScrollDistance = 0.15f * size;
if (absDelta >= size) {
delta = delta > 0 ? maxScrollDistance : -maxScrollDistance;
} else {
delta = maxScrollDistance * (float) Math.sin((delta/size)*(Math.PI/2));
}
}
setTranslation(mCurrAnimView, delta);
updateSwipeProgressFromOffset(mCurrAnimView, mCanCurrViewBeDimissed);
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
if (mCurrView != null) {
float maxVelocity = MAX_DISMISS_VELOCITY * mDensityScale;
mVelocityTracker.computeCurrentVelocity(1000 /* px/sec */, maxVelocity);
float escapeVelocity = SWIPE_ESCAPE_VELOCITY * mDensityScale;
float velocity = getVelocity(mVelocityTracker);
float perpendicularVelocity = getPerpendicularVelocity(mVelocityTracker);
// Decide whether to dismiss the current view
boolean childSwipedFarEnough = DISMISS_IF_SWIPED_FAR_ENOUGH &&
Math.abs(getTranslation(mCurrAnimView)) > 0.4 * getSize(mCurrAnimView);
boolean childSwipedFastEnough = (Math.abs(velocity) > escapeVelocity) &&
(Math.abs(velocity) > Math.abs(perpendicularVelocity)) &&
(velocity > 0) == (getTranslation(mCurrAnimView) > 0);
boolean falsingDetected = mCallback.isAntiFalsingNeeded()
&& !mTouchAboveFalsingThreshold;
boolean dismissChild = mCallback.canChildBeDismissed(mCurrView)
&& !falsingDetected && (childSwipedFastEnough || childSwipedFarEnough)
&& ev.getActionMasked() == MotionEvent.ACTION_UP;
if (dismissChild) {
// flingadingy
dismissChild(mCurrView, childSwipedFastEnough ? velocity : 0f);
} else {
// snappity
mCallback.onDragCancelled(mCurrView);
snapChild(mCurrView, velocity);
}
}
break;
}
return true;
|
public void | removeLongPressCallback()
if (mWatchLongPress != null) {
mHandler.removeCallbacks(mWatchLongPress);
mWatchLongPress = null;
}
|
public void | setDensityScale(float densityScale)
mDensityScale = densityScale;
|
public void | setLongPressListener(com.android.systemui.SwipeHelper$LongPressListener listener)
mLongPressListener = listener;
|
public void | setMaxSwipeProgress(float maxSwipeProgress)
mMaxSwipeProgress = maxSwipeProgress;
|
public void | setMinSwipeProgress(float minSwipeProgress)
mMinSwipeProgress = minSwipeProgress;
|
public void | setPagingTouchSlop(float pagingTouchSlop)
mPagingTouchSlop = pagingTouchSlop;
|
private void | setTranslation(android.view.View v, float translate)
if (mSwipeDirection == X) {
v.setTranslationX(translate);
} else {
v.setTranslationY(translate);
}
|
public void | snapChild(android.view.View view, float velocity)
final View animView = mCallback.getChildContentView(view);
final boolean canAnimViewBeDismissed = mCallback.canChildBeDismissed(animView);
ObjectAnimator anim = createTranslationAnimation(animView, 0);
int duration = SNAP_ANIM_LEN;
anim.setDuration(duration);
anim.addUpdateListener(new AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
updateSwipeProgressFromOffset(animView, canAnimViewBeDismissed);
}
});
anim.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator animator) {
updateSwipeProgressFromOffset(animView, canAnimViewBeDismissed);
mCallback.onChildSnappedBack(animView);
}
});
anim.start();
|
private void | updateSwipeProgressFromOffset(android.view.View animView, boolean dismissable)
float swipeProgress = getSwipeProgressForOffset(animView);
if (!mCallback.updateSwipeProgress(animView, dismissable, swipeProgress)) {
if (FADE_OUT_DURING_SWIPE && dismissable) {
float alpha = swipeProgress;
if (alpha != 0f && alpha != 1f) {
animView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
} else {
animView.setLayerType(View.LAYER_TYPE_NONE, null);
}
animView.setAlpha(getSwipeProgressForOffset(animView));
}
}
invalidateGlobalRegion(animView);
|