FileDocCategorySizeDatePackage
SwipeDismissLayout.javaAPI DocAndroid 5.1 API12284Thu Mar 12 22:22:10 GMT 2015com.android.internal.widget

SwipeDismissLayout

public class SwipeDismissLayout extends android.widget.FrameLayout
Special layout that finishes its activity when swiped away.

Fields Summary
private static final String
TAG
private static final float
DISMISS_MIN_DRAG_WIDTH_RATIO
private int
mSlop
private int
mMinFlingVelocity
private int
mMaxFlingVelocity
private long
mAnimationTime
private android.animation.TimeInterpolator
mCancelInterpolator
private android.animation.TimeInterpolator
mDismissInterpolator
private int
mActiveTouchId
private float
mDownX
private float
mDownY
private boolean
mSwiping
private boolean
mDismissed
private boolean
mDiscardIntercept
private android.view.VelocityTracker
mVelocityTracker
private float
mTranslationX
private OnDismissedListener
mDismissedListener
private OnSwipeProgressChangedListener
mProgressListener
private ViewTreeObserver.OnEnterAnimationCompleteListener
mOnEnterAnimationCompleteListener
private float
mLastX
Constructors Summary
public SwipeDismissLayout(android.content.Context context)


       
        super(context);
        init(context);
    
public SwipeDismissLayout(android.content.Context context, android.util.AttributeSet attrs)

        super(context, attrs);
        init(context);
    
public SwipeDismissLayout(android.content.Context context, android.util.AttributeSet attrs, int defStyle)

        super(context, attrs, defStyle);
        init(context);
    
Methods Summary
protected booleancanScroll(android.view.View v, boolean checkV, float dx, float x, float y)
Tests scrollability within child views of v in the direction of dx.

param
v View to test for horizontal scrollability
param
checkV Whether the view v passed should itself be checked for scrollability (true), or just its children (false).
param
dx Delta scrolled in pixels. Only the sign of this is used.
param
x X coordinate of the active touch point
param
y Y coordinate of the active touch point
return
true if child views of v can be scrolled by delta of dx.

        if (v instanceof ViewGroup) {
            final ViewGroup group = (ViewGroup) v;
            final int scrollX = v.getScrollX();
            final int scrollY = v.getScrollY();
            final int count = group.getChildCount();
            for (int i = count - 1; i >= 0; i--) {
                final View child = group.getChildAt(i);
                if (x + scrollX >= child.getLeft() && x + scrollX < child.getRight() &&
                        y + scrollY >= child.getTop() && y + scrollY < child.getBottom() &&
                        canScroll(child, true, dx, x + scrollX - child.getLeft(),
                                y + scrollY - child.getTop())) {
                    return true;
                }
            }
        }

        return checkV && v.canScrollHorizontally((int) -dx);
    
protected voidcancel()

        if (getContext() instanceof Activity) {
            ((Activity) getContext()).convertFromTranslucent();
        }
        if (mProgressListener != null) {
            mProgressListener.onSwipeCancelled(this);
        }
    
private voiddismiss()

        if (mDismissedListener != null) {
            mDismissedListener.onDismissed(this);
        }
    
private voidinit(android.content.Context context)

        ViewConfiguration vc = ViewConfiguration.get(getContext());
        mSlop = vc.getScaledTouchSlop();
        mMinFlingVelocity = vc.getScaledMinimumFlingVelocity();
        mMaxFlingVelocity = vc.getScaledMaximumFlingVelocity();
        mAnimationTime = getContext().getResources().getInteger(
                android.R.integer.config_shortAnimTime);
        mCancelInterpolator = new DecelerateInterpolator(1.5f);
        mDismissInterpolator = new AccelerateInterpolator(1.5f);
    
protected voidonAttachedToWindow()

        super.onAttachedToWindow();
        if (getContext() instanceof Activity) {
            getViewTreeObserver().addOnEnterAnimationCompleteListener(
                    mOnEnterAnimationCompleteListener);
        }
    
protected voidonDetachedFromWindow()

        super.onDetachedFromWindow();
        if (getContext() instanceof Activity) {
            getViewTreeObserver().removeOnEnterAnimationCompleteListener(
                    mOnEnterAnimationCompleteListener);
        }
    
public booleanonInterceptTouchEvent(android.view.MotionEvent ev)

        // offset because the view is translated during swipe
        ev.offsetLocation(mTranslationX, 0);

        switch (ev.getActionMasked()) {
            case MotionEvent.ACTION_DOWN:
                resetMembers();
                mDownX = ev.getRawX();
                mDownY = ev.getRawY();
                mActiveTouchId = ev.getPointerId(0);
                mVelocityTracker = VelocityTracker.obtain();
                mVelocityTracker.addMovement(ev);
                break;

            case MotionEvent.ACTION_POINTER_DOWN:
                int actionIndex = ev.getActionIndex();
                mActiveTouchId = ev.getPointerId(actionIndex);
                break;
            case MotionEvent.ACTION_POINTER_UP:
                actionIndex = ev.getActionIndex();
                int pointerId = ev.getPointerId(actionIndex);
                if (pointerId == mActiveTouchId) {
                    // This was our active pointer going up. Choose a new active pointer.
                    int newActionIndex = actionIndex == 0 ? 1 : 0;
                    mActiveTouchId = ev.getPointerId(newActionIndex);
                }
                break;

            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                resetMembers();
                break;

            case MotionEvent.ACTION_MOVE:
                if (mVelocityTracker == null || mDiscardIntercept) {
                    break;
                }

                int pointerIndex = ev.findPointerIndex(mActiveTouchId);
                if (pointerIndex == -1) {
                    Log.e(TAG, "Invalid pointer index: ignoring.");
                    mDiscardIntercept = true;
                    break;
                }
                float dx = ev.getRawX() - mDownX;
                float x = ev.getX(pointerIndex);
                float y = ev.getY(pointerIndex);
                if (dx != 0 && canScroll(this, false, dx, x, y)) {
                    mDiscardIntercept = true;
                    break;
                }
                updateSwiping(ev);
                break;
        }

        return !mDiscardIntercept && mSwiping;
    
public booleanonTouchEvent(android.view.MotionEvent ev)

        if (mVelocityTracker == null) {
            return super.onTouchEvent(ev);
        }
        switch (ev.getActionMasked()) {
            case MotionEvent.ACTION_UP:
                updateDismiss(ev);
                if (mDismissed) {
                    dismiss();
                } else if (mSwiping) {
                    cancel();
                }
                resetMembers();
                break;

            case MotionEvent.ACTION_CANCEL:
                cancel();
                resetMembers();
                break;

            case MotionEvent.ACTION_MOVE:
                mVelocityTracker.addMovement(ev);
                mLastX = ev.getRawX();
                updateSwiping(ev);
                if (mSwiping) {
                    if (getContext() instanceof Activity) {
                        ((Activity) getContext()).convertToTranslucent(null, null);
                    }
                    setProgress(ev.getRawX() - mDownX);
                    break;
                }
        }
        return true;
    
private voidresetMembers()
Resets internal members when canceling.

        if (mVelocityTracker != null) {
            mVelocityTracker.recycle();
        }
        mVelocityTracker = null;
        mTranslationX = 0;
        mDownX = 0;
        mDownY = 0;
        mSwiping = false;
        mDismissed = false;
        mDiscardIntercept = false;
    
public voidsetOnDismissedListener(com.android.internal.widget.SwipeDismissLayout$OnDismissedListener listener)

        mDismissedListener = listener;
    
public voidsetOnSwipeProgressChangedListener(com.android.internal.widget.SwipeDismissLayout$OnSwipeProgressChangedListener listener)

        mProgressListener = listener;
    
private voidsetProgress(float deltaX)

        mTranslationX = deltaX;
        if (mProgressListener != null && deltaX >= 0)  {
            mProgressListener.onSwipeProgressChanged(this, deltaX / getWidth(), deltaX);
        }
    
private voidupdateDismiss(android.view.MotionEvent ev)

        float deltaX = ev.getRawX() - mDownX;
        if (!mDismissed) {
            mVelocityTracker.addMovement(ev);
            mVelocityTracker.computeCurrentVelocity(1000);

            if (deltaX > (getWidth() * DISMISS_MIN_DRAG_WIDTH_RATIO) &&
                    ev.getRawX() >= mLastX) {
                mDismissed = true;
            }
        }
        // Check if the user tried to undo this.
        if (mDismissed && mSwiping) {
            // Check if the user's finger is actually back
            if (deltaX < (getWidth() * DISMISS_MIN_DRAG_WIDTH_RATIO)) {
                mDismissed = false;
            }
        }
    
private voidupdateSwiping(android.view.MotionEvent ev)

        if (!mSwiping) {
            float deltaX = ev.getRawX() - mDownX;
            float deltaY = ev.getRawY() - mDownY;
            if ((deltaX * deltaX) + (deltaY * deltaY) > mSlop * mSlop) {
                mSwiping = deltaX > mSlop * 2 && Math.abs(deltaY) < mSlop * 2;
            } else {
                mSwiping = false;
            }
        }