Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/213.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 带动画的SwipedSmissBehavior问题_Android_Android Layout_Android Coordinatorlayout - Fatal编程技术网

Android 带动画的SwipedSmissBehavior问题

Android 带动画的SwipedSmissBehavior问题,android,android-layout,android-coordinatorlayout,Android,Android Layout,Android Coordinatorlayout,我的问题是,为什么在拖动cardwiew时,我看不到任何动画。在许多示例中,动画都存在。也许有人知道为什么我从右向左滑动时会看到从左向右的动画 布局: <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-a

我的问题是,为什么在拖动
cardwiew
时,我看不到任何动画。在许多示例中,动画都存在。也许有人知道为什么我从右向左滑动时会看到从左向右的动画

布局:

<android.support.design.widget.CoordinatorLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    <android.support.v7.widget.CardView
            xmlns:card_view="http://schemas.android.com/apk/res-auto"
            android:id="@+id/swipe.card"
            android:layout_width="match_parent"
            android:layout_height="200dp"
            card_view:cardCornerRadius="4dp"
            card_view:contentPadding="8dp"
            android:layout_margin="16dp"
            app:layout_anchorGravity="bottom">

        <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Card"
                android:lineSpacingExtra="6dp"/>

        <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="SWIPE THIS CARD"
                android:layout_gravity="bottom|right"
                android:textAllCaps="true"
                android:fontFamily="sans-serif-medium"/>

    </android.support.v7.widget.CardView>

</android.support.design.widget.CoordinatorLayout>

尝试将此行添加到cardView:

cardView.setOnTouchListener { v, event ->
    if (v != null && v is CardView) {
        b.onInterceptTouchEvent(coordinatorLayout, v, event)
    } else {
        false
    }
}
但是,卡仅在滑动手势后显示滑动动画。如果你玩牌并左右刷卡,什么也不会发生


然后我检查Snackbar是如何实现的,但它们是一样的。新的snackbar只对快速滑动做出响应。我记得我们以前可以玩snackbar,但现在不行了。我想这是出于一些新材料设计的考虑。

我认为支持库有问题,所以我复制了代码并对其进行了一些修改。下面是一个工作示例:

将新行为应用于
snackbar

snackbar.addCallback(new Snackbar.Callback() {
            @Override
            public void onShown(Snackbar sb) {
                super.onShown(sb);
                ViewGroup.LayoutParams params = sb.getView().getLayoutParams();
                if (params instanceof CoordinatorLayout.LayoutParams) {
                    SwipeDismissBehavior2<View> behavior = new SwipeDismissBehavior2<>();
                    behavior.setSwipeDirection(SwipeDismissBehavior2.SWIPE_DIRECTION_ANY);
                    ((CoordinatorLayout.LayoutParams) params).setBehavior(behavior);
                }
            }
        });
snackbar.addCallback(新的snackbar.Callback(){
@凌驾
公开募捐(Snackbar sb){
super.onShown(某人);
ViewGroup.LayoutParams params=sb.getView().getLayoutParams();
if(参数CoordinatorLayout.LayoutParams的实例){
SwipedSmissBehavior2行为=新的SwipedSmissBehavior2();
behavior.setswitdirection(SwipedSmissBehavior2.SWIPE\u DIRECTION\u ANY);
((CoordinatorLayout.LayoutParams)params)setBehavior(行为);
}
}
});
新行为:

public class SwipeDismissBehavior2<V extends View> extends Behavior<V> {

    /**
     * A view is not currently being dragged or animating as a result of a fling/snap.
     */
    public static final int STATE_IDLE = ViewDragHelper.STATE_IDLE;
    /**
     * A view is currently being dragged. The position is currently changing as a result
     * of user input or simulated user input.
     */
    public static final int STATE_DRAGGING = ViewDragHelper.STATE_DRAGGING;
    /**
     * A view is currently settling into place as a result of a fling or
     * predefined non-interactive motion.
     */
    public static final int STATE_SETTLING = ViewDragHelper.STATE_SETTLING;
    /** @hide */
    @IntDef({SWIPE_DIRECTION_START_TO_END, SWIPE_DIRECTION_END_TO_START, SWIPE_DIRECTION_ANY})
    @Retention(RetentionPolicy.SOURCE)
    private @interface SwipeDirection {}
    /**
     * Swipe direction that only allows swiping in the direction of start-to-end. That is
     * left-to-right in LTR, or right-to-left in RTL.
     */
    public static final int SWIPE_DIRECTION_START_TO_END = 0;
    /**
     * Swipe direction that only allows swiping in the direction of end-to-start. That is
     * right-to-left in LTR or left-to-right in RTL.
     */
    public static final int SWIPE_DIRECTION_END_TO_START = 1;
    /**
     * Swipe direction which allows swiping in either direction.
     */
    public static final int SWIPE_DIRECTION_ANY = 2;
    private static final float DEFAULT_DRAG_DISMISS_THRESHOLD = 0.5f;
    private static final float DEFAULT_ALPHA_START_DISTANCE = 0f;
    private static final float DEFAULT_ALPHA_END_DISTANCE = DEFAULT_DRAG_DISMISS_THRESHOLD;
    private ViewDragHelper mViewDragHelper;
    private OnDismissListener mListener;
    private boolean mIgnoreEvents;
    private float mSensitivity = 0f;
    private boolean mSensitivitySet;
    private int mSwipeDirection = SWIPE_DIRECTION_ANY;
    private float mDragDismissThreshold = DEFAULT_DRAG_DISMISS_THRESHOLD;
    private float mAlphaStartSwipeDistance = DEFAULT_ALPHA_START_DISTANCE;
    private float mAlphaEndSwipeDistance = DEFAULT_ALPHA_END_DISTANCE;
    /**
     * Callback interface used to notify the application that the view has been dismissed.
     */
    public interface OnDismissListener {
        /**
         * Called when {@code view} has been dismissed via swiping.
         */
        public void onDismiss(View view);
        /**
         * Called when the drag state has changed.
         *
         * @param state the new state. One of
         * {@link #STATE_IDLE}, {@link #STATE_DRAGGING} or {@link #STATE_SETTLING}.
         */
        public void onDragStateChanged(int state);
    }
    /**
     * Set the listener to be used when a dismiss event occurs.
     *
     * @param listener the listener to use.
     */
    public void setListener(OnDismissListener listener) {
        mListener = listener;
    }
    /**
     * Sets the swipe direction for this behavior.
     *
     * @param direction one of the {@link #SWIPE_DIRECTION_START_TO_END},
     *                  {@link #SWIPE_DIRECTION_END_TO_START} or {@link #SWIPE_DIRECTION_ANY}
     */
    public void setSwipeDirection(@SwipeDirection int direction) {
        mSwipeDirection = direction;
    }
    /**
     * Set the threshold for telling if a view has been dragged enough to be dismissed.
     *
     * @param distance a ratio of a view's width, values are clamped to 0 >= x <= 1f;
     */
    public void setDragDismissDistance(float distance) {
        mDragDismissThreshold = clamp(0f, distance, 1f);
    }
    /**
     * The minimum swipe distance before the view's alpha is modified.
     *
     * @param fraction the distance as a fraction of the view's width.
     */
    public void setStartAlphaSwipeDistance(float fraction) {
        mAlphaStartSwipeDistance = clamp(0f, fraction, 1f);
    }
    /**
     * The maximum swipe distance for the view's alpha is modified.
     *
     * @param fraction the distance as a fraction of the view's width.
     */
    public void setEndAlphaSwipeDistance(float fraction) {
        mAlphaEndSwipeDistance = clamp(0f, fraction, 1f);
    }
    /**
     * Set the sensitivity used for detecting the start of a swipe. This only takes effect if
     * no touch handling has occured yet.
     *
     * @param sensitivity Multiplier for how sensitive we should be about detecting
     *                    the start of a drag. Larger values are more sensitive. 1.0f is normal.
     */
    public void setSensitivity(float sensitivity) {
        mSensitivity = sensitivity;
        mSensitivitySet = true;
    }
    @Override
    public boolean onInterceptTouchEvent(CoordinatorLayout parent, V child, MotionEvent event) {
        switch (MotionEventCompat.getActionMasked(event)) {
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                // Reset the ignore flag
                if (mIgnoreEvents) {
                    mIgnoreEvents = false;
                    return false;
                }
                break;
            default:
                mIgnoreEvents = !parent.isPointInChildBounds(child,
                        (int) event.getX(), (int) event.getY());
                break;
        }
        if (mIgnoreEvents) {
            return false;
        }
        ensureViewDragHelper(parent);
        return mViewDragHelper.shouldInterceptTouchEvent(event);
    }
    @Override
    public boolean onTouchEvent(CoordinatorLayout parent, V child, MotionEvent event) {
        if (mViewDragHelper != null) {
            mViewDragHelper.processTouchEvent(event);
            return true;
        }
        return false;
    }
    private final ViewDragHelper.Callback mDragCallback = new ViewDragHelper.Callback() {
        private int mOriginalCapturedViewLeft;
        @Override
        public boolean tryCaptureView(View child, int pointerId) {
            mOriginalCapturedViewLeft = child.getLeft();
            return true;
        }
        @Override
        public void onViewDragStateChanged(int state) {
            if (mListener != null) {
                mListener.onDragStateChanged(state);
            }
        }
        @Override
        public void onViewReleased(View child, float xvel, float yvel) {
            final int childWidth = child.getWidth();
            int targetLeft;
            boolean dismiss = false;
            if (shouldDismiss(child, xvel)) {
                targetLeft = child.getLeft() < mOriginalCapturedViewLeft
                        ? mOriginalCapturedViewLeft - childWidth
                        : mOriginalCapturedViewLeft + childWidth;
                dismiss = true;
            } else {
                // Else, reset back to the original left
                targetLeft = mOriginalCapturedViewLeft;
            }
            if (mViewDragHelper.settleCapturedViewAt(targetLeft, child.getTop())) {
                ViewCompat.postOnAnimation(child, new SettleRunnable(child, dismiss));
            } else if (dismiss) {
                child.setVisibility(View.GONE);
                if (mListener != null) {
                    mListener.onDismiss(child);
                }
            }
        }
        private boolean shouldDismiss(View child, float xvel) {
            if (xvel != 0f) {
                final boolean isRtl = ViewCompat.getLayoutDirection(child)
                        == ViewCompat.LAYOUT_DIRECTION_RTL;
                if (mSwipeDirection == SWIPE_DIRECTION_ANY) {
                    // We don't care about the direction so return true
                    return true;
                } else if (mSwipeDirection == SWIPE_DIRECTION_START_TO_END) {
                    // We only allow start-to-end swiping, so the fling needs to be in the
                    // correct direction
                    return isRtl ? xvel < 0f : xvel > 0f;
                } else if (mSwipeDirection == SWIPE_DIRECTION_END_TO_START) {
                    // We only allow end-to-start swiping, so the fling needs to be in the
                    // correct direction
                    return isRtl ? xvel > 0f : xvel < 0f;
                }
            } else {
                final int distance = child.getLeft() - mOriginalCapturedViewLeft;
                final int thresholdDistance = Math.round(child.getWidth() * mDragDismissThreshold);
                return Math.abs(distance) >= thresholdDistance;
            }
            return false;
        }
        @Override
        public int getViewHorizontalDragRange(View child) {
            return child.getWidth();
        }
        @Override
        public int clampViewPositionHorizontal(View child, int left, int dx) {
            final boolean isRtl = ViewCompat.getLayoutDirection(child)
                    == ViewCompat.LAYOUT_DIRECTION_RTL;
            int min, max;
            if (mSwipeDirection == SWIPE_DIRECTION_START_TO_END) {
                if (isRtl) {
                    min = mOriginalCapturedViewLeft - child.getWidth();
                    max = mOriginalCapturedViewLeft;
                } else {
                    min = mOriginalCapturedViewLeft;
                    max = mOriginalCapturedViewLeft + child.getWidth();
                }
            } else if (mSwipeDirection == SWIPE_DIRECTION_END_TO_START) {
                if (isRtl) {
                    min = mOriginalCapturedViewLeft;
                    max = mOriginalCapturedViewLeft + child.getWidth();
                } else {
                    min = mOriginalCapturedViewLeft - child.getWidth();
                    max = mOriginalCapturedViewLeft;
                }
            } else {
                min = mOriginalCapturedViewLeft - child.getWidth();
                max = mOriginalCapturedViewLeft + child.getWidth();
            }
            return clamp(min, left, max);
        }
        @Override
        public int clampViewPositionVertical(View child, int top, int dy) {
            return child.getTop();
        }
        @Override
        public void onViewPositionChanged(View child, int left, int top, int dx, int dy) {
            final float distance = fraction(0, child.getWidth(), Math.abs(left - mOriginalCapturedViewLeft));
            child.setAlpha(clamp(0f, 1f - distance, 1f));
        }
    };

    private void ensureViewDragHelper(ViewGroup parent) {
        if (mViewDragHelper == null) {
            mViewDragHelper = mSensitivitySet
                    ? ViewDragHelper.create(parent, mSensitivity, mDragCallback)
                    : ViewDragHelper.create(parent, mDragCallback);
        }
    }
    private class SettleRunnable implements Runnable {
        private final View mView;
        private final boolean mDismiss;
        SettleRunnable(View view, boolean dismiss) {
            mView = view;
            mDismiss = dismiss;
        }
        @Override
        public void run() {
            if (mViewDragHelper != null && mViewDragHelper.continueSettling(true)) {
                ViewCompat.postOnAnimation(mView, this);
            } else {
                if (mDismiss) {
                    mView.setVisibility(View.GONE);
                    if (mListener != null) {
                        mListener.onDismiss(mView);
                    }
                }
            }
        }
    }
    private static float clamp(float min, float value, float max) {
        return Math.min(Math.max(min, value), max);
    }
    private static int clamp(int min, int value, int max) {
        return Math.min(Math.max(min, value), max);
    }
    /**
     * Retrieve the current drag state of this behavior. This will return one of
     * {@link #STATE_IDLE}, {@link #STATE_DRAGGING} or {@link #STATE_SETTLING}.
     *
     * @return The current drag state
     */
    public int getDragState() {
        return mViewDragHelper != null ? mViewDragHelper.getViewDragState() : STATE_IDLE;
    }
    /**
     * The fraction that {@code value} is between {@code startValue} and {@code endValue}.
     */
    static float fraction(float startValue, float endValue, float value) {
        return (value - startValue) / (endValue - startValue);
    }
}
公共类SwipedSmissBehavior2扩展了行为{
/**
*视图当前未被拖动或设置动画,这是投掷/捕捉的结果。
*/
public static final int STATE_IDLE=ViewDragHelper.STATE_IDLE;
/**
*当前正在拖动视图。因此,位置当前正在更改
*用户输入或模拟用户输入。
*/
public static final int STATE_DRAGGING=ViewDragHelper.STATE_DRAGGING;
/**
*一个视图当前由于一次抛投或
*预定义的非交互运动。
*/
公共静态最终int状态\u设置=ViewDragHelper.STATE\u设置;
/**@隐藏*/
@IntDef({SWIPE_DIRECTION_START_TO_END,SWIPE_DIRECTION_END_TO_START,SWIPE_DIRECTION_ANY})
@保留(RetentionPolicy.SOURCE)
私有@interface SwipeDirection{}
/**
*只允许从开始到结束方向滑动的滑动方向。即
*在LTR中从左向右,或在RTL中从右向左。
*/
公共静态最终整数滑动方向开始到结束=0;
/**
*只允许从结束到开始方向滑动的滑动方向。即
*在LTR中从右向左或在RTL中从左向右。
*/
公共静态最终整数滑动方向结束到开始=1;
/**
*滑动方向,允许在任一方向滑动。
*/
公共静态最终整数滑动方向任意=2;
私有静态最终浮动默认值\拖动\解除\阈值=0.5f;
专用静态最终浮动默认值\u ALPHA\u START\u距离=0f;
专用静态最终浮动默认值\u ALPHA\u END\u DISTANCE=默认值\u DRAG\u Disease\u THRESHOLD;
私有ViewDragHelper mViewDragHelper;
私家侦探;
私有布尔mIgnoreEvents;
专用浮点mSensitivity=0f;
私有布尔mSensitivitySet;
private int mSwipeDirection=swip\u DIRECTION\u ANY;
private float mdragdismisssthreshold=默认\u拖动\u解除\u阈值;
私有浮动MalphasStartSwipedInstance=默认的α开始距离;
私有浮动MalphaendSwipedInstance=默认的\u ALPHA\u END\u距离;
/**
*回调接口,用于通知应用程序视图已被取消。
*/
公共接口OnDismissListener{
/**
*通过刷卡解除{@code view}时调用。
*/
公共空间(视图);
/**
*拖动状态更改时调用。
*
*@param state新状态。其中一个
*{@link#STATE_IDLE}、{@link#STATE_DRAGGING}或{@link#STATE_satting}。
*/
公共状态已更改(int状态);
}
/**
*设置在发生解除事件时要使用的侦听器。
*
*@param listener要使用的侦听器。
*/
公共void setListener(OnDismissListener侦听器){
mListener=监听器;
}
/**
*设置此行为的滑动方向。
*
*@param方向{@link#滑动方向(开始)到(结束)之一,
*{@link#滑动方向(u END)到(u START)或{@link#滑动方向(u ANY)
*/
公共方向(@SwipeDirection int direction){
mSwipeDirection=方向;
}
/**
*设置阈值,以告知视图是否已被拖动到足以关闭的程度。
*

*@param distance视图宽度的比率,值被钳制为0>=x,那么是否确认此问题是由支持库版本引起的?我也在28.0.0上,面临着同样的问题:<使用自定义SwipedSmissBehavior似乎…太过了是的,我认为是,或者可能是一个新的实现。@DennisAnderson材质组件和roid他们有错误,他们仍然没有解决这个刷卡问题。但是你已经解决了。谢谢你!
snackbar.addCallback(new Snackbar.Callback() {
            @Override
            public void onShown(Snackbar sb) {
                super.onShown(sb);
                ViewGroup.LayoutParams params = sb.getView().getLayoutParams();
                if (params instanceof CoordinatorLayout.LayoutParams) {
                    SwipeDismissBehavior2<View> behavior = new SwipeDismissBehavior2<>();
                    behavior.setSwipeDirection(SwipeDismissBehavior2.SWIPE_DIRECTION_ANY);
                    ((CoordinatorLayout.LayoutParams) params).setBehavior(behavior);
                }
            }
        });
public class SwipeDismissBehavior2<V extends View> extends Behavior<V> {

    /**
     * A view is not currently being dragged or animating as a result of a fling/snap.
     */
    public static final int STATE_IDLE = ViewDragHelper.STATE_IDLE;
    /**
     * A view is currently being dragged. The position is currently changing as a result
     * of user input or simulated user input.
     */
    public static final int STATE_DRAGGING = ViewDragHelper.STATE_DRAGGING;
    /**
     * A view is currently settling into place as a result of a fling or
     * predefined non-interactive motion.
     */
    public static final int STATE_SETTLING = ViewDragHelper.STATE_SETTLING;
    /** @hide */
    @IntDef({SWIPE_DIRECTION_START_TO_END, SWIPE_DIRECTION_END_TO_START, SWIPE_DIRECTION_ANY})
    @Retention(RetentionPolicy.SOURCE)
    private @interface SwipeDirection {}
    /**
     * Swipe direction that only allows swiping in the direction of start-to-end. That is
     * left-to-right in LTR, or right-to-left in RTL.
     */
    public static final int SWIPE_DIRECTION_START_TO_END = 0;
    /**
     * Swipe direction that only allows swiping in the direction of end-to-start. That is
     * right-to-left in LTR or left-to-right in RTL.
     */
    public static final int SWIPE_DIRECTION_END_TO_START = 1;
    /**
     * Swipe direction which allows swiping in either direction.
     */
    public static final int SWIPE_DIRECTION_ANY = 2;
    private static final float DEFAULT_DRAG_DISMISS_THRESHOLD = 0.5f;
    private static final float DEFAULT_ALPHA_START_DISTANCE = 0f;
    private static final float DEFAULT_ALPHA_END_DISTANCE = DEFAULT_DRAG_DISMISS_THRESHOLD;
    private ViewDragHelper mViewDragHelper;
    private OnDismissListener mListener;
    private boolean mIgnoreEvents;
    private float mSensitivity = 0f;
    private boolean mSensitivitySet;
    private int mSwipeDirection = SWIPE_DIRECTION_ANY;
    private float mDragDismissThreshold = DEFAULT_DRAG_DISMISS_THRESHOLD;
    private float mAlphaStartSwipeDistance = DEFAULT_ALPHA_START_DISTANCE;
    private float mAlphaEndSwipeDistance = DEFAULT_ALPHA_END_DISTANCE;
    /**
     * Callback interface used to notify the application that the view has been dismissed.
     */
    public interface OnDismissListener {
        /**
         * Called when {@code view} has been dismissed via swiping.
         */
        public void onDismiss(View view);
        /**
         * Called when the drag state has changed.
         *
         * @param state the new state. One of
         * {@link #STATE_IDLE}, {@link #STATE_DRAGGING} or {@link #STATE_SETTLING}.
         */
        public void onDragStateChanged(int state);
    }
    /**
     * Set the listener to be used when a dismiss event occurs.
     *
     * @param listener the listener to use.
     */
    public void setListener(OnDismissListener listener) {
        mListener = listener;
    }
    /**
     * Sets the swipe direction for this behavior.
     *
     * @param direction one of the {@link #SWIPE_DIRECTION_START_TO_END},
     *                  {@link #SWIPE_DIRECTION_END_TO_START} or {@link #SWIPE_DIRECTION_ANY}
     */
    public void setSwipeDirection(@SwipeDirection int direction) {
        mSwipeDirection = direction;
    }
    /**
     * Set the threshold for telling if a view has been dragged enough to be dismissed.
     *
     * @param distance a ratio of a view's width, values are clamped to 0 >= x <= 1f;
     */
    public void setDragDismissDistance(float distance) {
        mDragDismissThreshold = clamp(0f, distance, 1f);
    }
    /**
     * The minimum swipe distance before the view's alpha is modified.
     *
     * @param fraction the distance as a fraction of the view's width.
     */
    public void setStartAlphaSwipeDistance(float fraction) {
        mAlphaStartSwipeDistance = clamp(0f, fraction, 1f);
    }
    /**
     * The maximum swipe distance for the view's alpha is modified.
     *
     * @param fraction the distance as a fraction of the view's width.
     */
    public void setEndAlphaSwipeDistance(float fraction) {
        mAlphaEndSwipeDistance = clamp(0f, fraction, 1f);
    }
    /**
     * Set the sensitivity used for detecting the start of a swipe. This only takes effect if
     * no touch handling has occured yet.
     *
     * @param sensitivity Multiplier for how sensitive we should be about detecting
     *                    the start of a drag. Larger values are more sensitive. 1.0f is normal.
     */
    public void setSensitivity(float sensitivity) {
        mSensitivity = sensitivity;
        mSensitivitySet = true;
    }
    @Override
    public boolean onInterceptTouchEvent(CoordinatorLayout parent, V child, MotionEvent event) {
        switch (MotionEventCompat.getActionMasked(event)) {
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                // Reset the ignore flag
                if (mIgnoreEvents) {
                    mIgnoreEvents = false;
                    return false;
                }
                break;
            default:
                mIgnoreEvents = !parent.isPointInChildBounds(child,
                        (int) event.getX(), (int) event.getY());
                break;
        }
        if (mIgnoreEvents) {
            return false;
        }
        ensureViewDragHelper(parent);
        return mViewDragHelper.shouldInterceptTouchEvent(event);
    }
    @Override
    public boolean onTouchEvent(CoordinatorLayout parent, V child, MotionEvent event) {
        if (mViewDragHelper != null) {
            mViewDragHelper.processTouchEvent(event);
            return true;
        }
        return false;
    }
    private final ViewDragHelper.Callback mDragCallback = new ViewDragHelper.Callback() {
        private int mOriginalCapturedViewLeft;
        @Override
        public boolean tryCaptureView(View child, int pointerId) {
            mOriginalCapturedViewLeft = child.getLeft();
            return true;
        }
        @Override
        public void onViewDragStateChanged(int state) {
            if (mListener != null) {
                mListener.onDragStateChanged(state);
            }
        }
        @Override
        public void onViewReleased(View child, float xvel, float yvel) {
            final int childWidth = child.getWidth();
            int targetLeft;
            boolean dismiss = false;
            if (shouldDismiss(child, xvel)) {
                targetLeft = child.getLeft() < mOriginalCapturedViewLeft
                        ? mOriginalCapturedViewLeft - childWidth
                        : mOriginalCapturedViewLeft + childWidth;
                dismiss = true;
            } else {
                // Else, reset back to the original left
                targetLeft = mOriginalCapturedViewLeft;
            }
            if (mViewDragHelper.settleCapturedViewAt(targetLeft, child.getTop())) {
                ViewCompat.postOnAnimation(child, new SettleRunnable(child, dismiss));
            } else if (dismiss) {
                child.setVisibility(View.GONE);
                if (mListener != null) {
                    mListener.onDismiss(child);
                }
            }
        }
        private boolean shouldDismiss(View child, float xvel) {
            if (xvel != 0f) {
                final boolean isRtl = ViewCompat.getLayoutDirection(child)
                        == ViewCompat.LAYOUT_DIRECTION_RTL;
                if (mSwipeDirection == SWIPE_DIRECTION_ANY) {
                    // We don't care about the direction so return true
                    return true;
                } else if (mSwipeDirection == SWIPE_DIRECTION_START_TO_END) {
                    // We only allow start-to-end swiping, so the fling needs to be in the
                    // correct direction
                    return isRtl ? xvel < 0f : xvel > 0f;
                } else if (mSwipeDirection == SWIPE_DIRECTION_END_TO_START) {
                    // We only allow end-to-start swiping, so the fling needs to be in the
                    // correct direction
                    return isRtl ? xvel > 0f : xvel < 0f;
                }
            } else {
                final int distance = child.getLeft() - mOriginalCapturedViewLeft;
                final int thresholdDistance = Math.round(child.getWidth() * mDragDismissThreshold);
                return Math.abs(distance) >= thresholdDistance;
            }
            return false;
        }
        @Override
        public int getViewHorizontalDragRange(View child) {
            return child.getWidth();
        }
        @Override
        public int clampViewPositionHorizontal(View child, int left, int dx) {
            final boolean isRtl = ViewCompat.getLayoutDirection(child)
                    == ViewCompat.LAYOUT_DIRECTION_RTL;
            int min, max;
            if (mSwipeDirection == SWIPE_DIRECTION_START_TO_END) {
                if (isRtl) {
                    min = mOriginalCapturedViewLeft - child.getWidth();
                    max = mOriginalCapturedViewLeft;
                } else {
                    min = mOriginalCapturedViewLeft;
                    max = mOriginalCapturedViewLeft + child.getWidth();
                }
            } else if (mSwipeDirection == SWIPE_DIRECTION_END_TO_START) {
                if (isRtl) {
                    min = mOriginalCapturedViewLeft;
                    max = mOriginalCapturedViewLeft + child.getWidth();
                } else {
                    min = mOriginalCapturedViewLeft - child.getWidth();
                    max = mOriginalCapturedViewLeft;
                }
            } else {
                min = mOriginalCapturedViewLeft - child.getWidth();
                max = mOriginalCapturedViewLeft + child.getWidth();
            }
            return clamp(min, left, max);
        }
        @Override
        public int clampViewPositionVertical(View child, int top, int dy) {
            return child.getTop();
        }
        @Override
        public void onViewPositionChanged(View child, int left, int top, int dx, int dy) {
            final float distance = fraction(0, child.getWidth(), Math.abs(left - mOriginalCapturedViewLeft));
            child.setAlpha(clamp(0f, 1f - distance, 1f));
        }
    };

    private void ensureViewDragHelper(ViewGroup parent) {
        if (mViewDragHelper == null) {
            mViewDragHelper = mSensitivitySet
                    ? ViewDragHelper.create(parent, mSensitivity, mDragCallback)
                    : ViewDragHelper.create(parent, mDragCallback);
        }
    }
    private class SettleRunnable implements Runnable {
        private final View mView;
        private final boolean mDismiss;
        SettleRunnable(View view, boolean dismiss) {
            mView = view;
            mDismiss = dismiss;
        }
        @Override
        public void run() {
            if (mViewDragHelper != null && mViewDragHelper.continueSettling(true)) {
                ViewCompat.postOnAnimation(mView, this);
            } else {
                if (mDismiss) {
                    mView.setVisibility(View.GONE);
                    if (mListener != null) {
                        mListener.onDismiss(mView);
                    }
                }
            }
        }
    }
    private static float clamp(float min, float value, float max) {
        return Math.min(Math.max(min, value), max);
    }
    private static int clamp(int min, int value, int max) {
        return Math.min(Math.max(min, value), max);
    }
    /**
     * Retrieve the current drag state of this behavior. This will return one of
     * {@link #STATE_IDLE}, {@link #STATE_DRAGGING} or {@link #STATE_SETTLING}.
     *
     * @return The current drag state
     */
    public int getDragState() {
        return mViewDragHelper != null ? mViewDragHelper.getViewDragState() : STATE_IDLE;
    }
    /**
     * The fraction that {@code value} is between {@code startValue} and {@code endValue}.
     */
    static float fraction(float startValue, float endValue, float value) {
        return (value - startValue) / (endValue - startValue);
    }
}