Fields Summary |
---|
static final String | TAG |
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 float | SWIPE_ESCAPE_VELOCITY |
private int | DEFAULT_ESCAPE_ANIMATION_DURATION |
private int | MAX_ESCAPE_ANIMATION_DURATION |
private static final int | SNAP_ANIM_LEN |
public static float | ALPHA_FADE_START |
static final float | ALPHA_FADE_END |
private float | mMinAlpha |
private float | mPagingTouchSlop |
Callback | mCallback |
private int | mSwipeDirection |
private android.view.VelocityTracker | mVelocityTracker |
private float | mInitialTouchPos |
private boolean | mDragging |
private android.view.View | mCurrView |
private boolean | mCanCurrViewBeDimissed |
private float | mDensityScale |
public boolean | mAllowSwipeTowardsStart |
public boolean | mAllowSwipeTowardsEnd |
private boolean | mRtl |
Methods Summary |
---|
public void | cancelOngoingDrag()
if (mDragging) {
if (mCurrView != null) {
mCallback.onDragCancelled(mCurrView);
setTranslation(mCurrView, 0);
mCallback.onSnapBackCompleted(mCurrView);
mCurrView = null;
}
mDragging = false;
}
|
private android.animation.ObjectAnimator | createTranslationAnimation(android.view.View v, float newPos)
ObjectAnimator anim = ObjectAnimator.ofFloat(v,
mSwipeDirection == X ? View.TRANSLATION_X : View.TRANSLATION_Y, newPos);
return anim;
|
private void | dismissChild(android.view.View view, float velocity)
final boolean canAnimViewBeDismissed = mCallback.canChildBeDismissed(view);
float newPos;
if (velocity < 0
|| (velocity == 0 && getTranslation(view) < 0)
// if we use the Menu to dismiss an item in landscape, animate up
|| (velocity == 0 && getTranslation(view) == 0 && mSwipeDirection == Y)) {
newPos = -getSize(view);
} else {
newPos = getSize(view);
}
int duration = MAX_ESCAPE_ANIMATION_DURATION;
if (velocity != 0) {
duration = Math.min(duration,
(int) (Math.abs(newPos - getTranslation(view)) *
1000f / Math.abs(velocity)));
} else {
duration = DEFAULT_ESCAPE_ANIMATION_DURATION;
}
ValueAnimator anim = createTranslationAnimation(view, newPos);
anim.setInterpolator(sLinearInterpolator);
anim.setDuration(duration);
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
mCallback.onChildDismissed(view);
if (FADE_OUT_DURING_SWIPE && canAnimViewBeDismissed) {
view.setAlpha(1.f);
}
}
});
anim.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
if (FADE_OUT_DURING_SWIPE && canAnimViewBeDismissed) {
view.setAlpha(getAlphaForOffset(view));
}
}
});
anim.start();
|
private void | endSwipe(android.view.VelocityTracker velocityTracker)
velocityTracker.computeCurrentVelocity(1000 /* px/sec */);
float velocity = getVelocity(velocityTracker);
float perpendicularVelocity = getPerpendicularVelocity(velocityTracker);
float escapeVelocity = SWIPE_ESCAPE_VELOCITY * mDensityScale;
float translation = getTranslation(mCurrView);
// Decide whether to dismiss the current view
boolean childSwipedFarEnough = DISMISS_IF_SWIPED_FAR_ENOUGH &&
Math.abs(translation) > 0.6 * getSize(mCurrView);
boolean childSwipedFastEnough = (Math.abs(velocity) > escapeVelocity) &&
(Math.abs(velocity) > Math.abs(perpendicularVelocity)) &&
(velocity > 0) == (translation > 0);
boolean dismissChild = mCallback.canChildBeDismissed(mCurrView)
&& isValidSwipeDirection(translation)
&& (childSwipedFastEnough || childSwipedFarEnough);
if (dismissChild) {
// flingadingy
dismissChild(mCurrView, childSwipedFastEnough ? velocity : 0f);
} else {
// snappity
mCallback.onDragCancelled(mCurrView);
snapChild(mCurrView, velocity);
}
|
float | getAlphaForOffset(android.view.View view)
float viewSize = getSize(view);
final float fadeSize = ALPHA_FADE_END * viewSize;
float result = 1.0f;
float pos = getTranslation(view);
if (pos >= viewSize * ALPHA_FADE_START) {
result = 1.0f - (pos - viewSize * ALPHA_FADE_START) / fadeSize;
} else if (pos < viewSize * (1.0f - ALPHA_FADE_START)) {
result = 1.0f + (viewSize * ALPHA_FADE_START + pos) / fadeSize;
}
result = Math.min(result, 1.0f);
result = Math.max(result, 0f);
return Math.max(mMinAlpha, result);
|
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)
final DisplayMetrics dm = v.getContext().getResources().getDisplayMetrics();
return mSwipeDirection == X ? dm.widthPixels : dm.heightPixels;
|
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 boolean | isLayoutRtl(android.view.View view)Determines whether the given view has RTL layout.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
return View.LAYOUT_DIRECTION_RTL == view.getLayoutDirection();
} else {
return false;
}
|
private boolean | isValidSwipeDirection(float amount)
if (mSwipeDirection == X) {
if (mRtl) {
return (amount <= 0) ? mAllowSwipeTowardsEnd : mAllowSwipeTowardsStart;
} else {
return (amount <= 0) ? mAllowSwipeTowardsStart : mAllowSwipeTowardsEnd;
}
}
// Vertical swipes are always valid.
return true;
|
public boolean | onInterceptTouchEvent(android.view.MotionEvent ev)
final int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
mDragging = false;
mCurrView = mCallback.getChildAtPosition(ev);
mVelocityTracker.clear();
if (mCurrView != null) {
mRtl = isLayoutRtl(mCurrView);
mCanCurrViewBeDimissed = mCallback.canChildBeDismissed(mCurrView);
mVelocityTracker.addMovement(ev);
mInitialTouchPos = getPos(ev);
} else {
mCanCurrViewBeDimissed = false;
}
break;
case MotionEvent.ACTION_MOVE:
if (mCurrView != null) {
mVelocityTracker.addMovement(ev);
float pos = getPos(ev);
float delta = pos - mInitialTouchPos;
if (Math.abs(delta) > mPagingTouchSlop) {
mCallback.onBeginDrag(mCurrView);
mDragging = true;
mInitialTouchPos = pos - getTranslation(mCurrView);
}
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
mDragging = false;
mCurrView = null;
break;
}
return mDragging;
|
public boolean | onTouchEvent(android.view.MotionEvent ev)
if (!mDragging) {
if (!onInterceptTouchEvent(ev)) {
return mCanCurrViewBeDimissed;
}
}
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;
setSwipeAmount(delta);
mCallback.onSwipeChanged(mCurrView, delta);
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
if (mCurrView != null) {
endSwipe(mVelocityTracker);
}
break;
}
return true;
|
public void | resetTranslation(android.view.View v)
setTranslation(v, 0);
|
public void | setDensityScale(float densityScale)
mDensityScale = densityScale;
|
public void | setMinAlpha(float minAlpha)
mMinAlpha = minAlpha;
|
public void | setPagingTouchSlop(float pagingTouchSlop)
mPagingTouchSlop = pagingTouchSlop;
|
private void | setSwipeAmount(float amount)
// don't let items that can't be dismissed be dragged more than
// maxScrollDistance
if (CONSTRAIN_SWIPE
&& (!isValidSwipeDirection(amount) || !mCallback.canChildBeDismissed(mCurrView))) {
float size = getSize(mCurrView);
float maxScrollDistance = 0.15f * size;
if (Math.abs(amount) >= size) {
amount = amount > 0 ? maxScrollDistance : -maxScrollDistance;
} else {
amount = maxScrollDistance * (float) Math.sin((amount/size)*(Math.PI/2));
}
}
setTranslation(mCurrView, amount);
if (FADE_OUT_DURING_SWIPE && mCanCurrViewBeDimissed) {
float alpha = getAlphaForOffset(mCurrView);
mCurrView.setAlpha(alpha);
}
|
private void | setTranslation(android.view.View v, float translate)
if (mSwipeDirection == X) {
v.setTranslationX(translate);
} else {
v.setTranslationY(translate);
}
|
private void | snapChild(android.view.View view, float velocity)
final boolean canAnimViewBeDismissed = mCallback.canChildBeDismissed(view);
ValueAnimator anim = createTranslationAnimation(view, 0);
int duration = SNAP_ANIM_LEN;
anim.setDuration(duration);
anim.setInterpolator(RecentsConfiguration.getInstance().linearOutSlowInInterpolator);
anim.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
if (FADE_OUT_DURING_SWIPE && canAnimViewBeDismissed) {
view.setAlpha(getAlphaForOffset(view));
}
mCallback.onSwipeChanged(mCurrView, view.getTranslationX());
}
});
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if (FADE_OUT_DURING_SWIPE && canAnimViewBeDismissed) {
view.setAlpha(1.0f);
}
mCallback.onSnapBackCompleted(view);
}
});
anim.start();
|