150行代码实现滑动退出

超级简单代码实现滑动退出

本文参考自 http://www.jianshu.com/p/59be4551c418

OK,接下来惯例,通过阅读本文你能学习到:

ViewDragHelper的使用(如果你想学习自定义View,那么ViewDragHelper你绝对不能错过)
好像也没有什么了….

这个效果,难度不大,会ViewDragHelper的同学应该10分钟就能写出来了吧~
如果不会也没关系~以下是代码,请查看。

  • 自定义Layout : SwipeBackFrameLayout

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    public class SwipeBackFrameLayout extends FrameLayout {
    private ViewDragHelper mDragHelper;
    private int mDividerWidth = 100;
    private int mLastdx;
    public SwipeBackFrameLayout(Context context) {
    super(context);
    initView();
    }
    public SwipeBackFrameLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
    initView();
    }
    public SwipeBackFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    initView();
    }
    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    super.onLayout(changed, left, top, right, bottom);
    mDividerWidth = mDividerView.getWidth();
    }
    //Notice view 刚初始化的时候就会被调用一次
    @Override
    public void computeScroll() {
    super.computeScroll();
    if (mDragHelper.continueSettling(true)) {
    invalidate();
    }
    }
    private void initView() {
    // 1f代表灵敏度
    mDragHelper = ViewDragHelper.create(this, 1f, new ViewDragHelper.Callback() {
    @Override
    public void onViewDragStateChanged(int state) {
    super.onViewDragStateChanged(state);
    //滑动停止,并且到达了滑动的判断条件 则回调关闭
    if (mDragHelper.getViewDragState() == ViewDragHelper.STATE_IDLE && mcCallBack != null && mDividerWidth == mContentView.getLeft() && mLastdx > 0) {
    mcCallBack.onShouldFinish();
    }
    }
    @Override
    public void onEdgeTouched(int edgeFlags, int pointerId) {
    super.onEdgeTouched(edgeFlags, pointerId);
    // 触摸到边界的时候, 我们capture注mContentView
    mDragHelper.captureChildView(mContentView, pointerId);
    }
    @Override
    public int getViewHorizontalDragRange(View child) {
    return 1;
    }
    @Override
    public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
    super.onViewPositionChanged(changedView, left, top, dx, dy);
    Log.d("ZTJ", "onViewPositionChanged() called with left = [" + left + "], top = [" + top + "], dx = [" + dx + "], dy = [" + dy + "]");
    //0.0 - 1.0
    //Notice 这边可以给个接口回调出去,就可以做各种炫酷的效果了
    float alpha = (float) (left * 1.0 / mDividerWidth);
    mDividerView.setAlpha(alpha);
    }
    @Override
    public int clampViewPositionHorizontal(View child, int left, int dx) {
    // 计算left 我们的目标范围是0-dividerwidth的宽度
    mLastdx = dx;
    int newLeft = Math.min(mDividerWidth, Math.max(left, 0));
    return newLeft;
    }
    @Override
    public void onViewReleased(View releasedChild, float xvel, float yvel) {
    //>0代表用户想关闭
    if (mLastdx > 0) {
    // 还不到关闭条件,我们让view滑动过去,再关闭
    if (mDividerWidth != releasedChild.getLeft()) {
    mDragHelper.settleCapturedViewAt(mDividerWidth, releasedChild.getTop());
    invalidate();
    } else {
    if (mcCallBack != null) {
    mcCallBack.onShouldFinish();
    }
    }
    } else {
    //用户不想关闭 ,则滑动到最左边
    if (mDividerWidth != 0) {
    mDragHelper.settleCapturedViewAt(0, releasedChild.getTop());
    invalidate();
    }
    }
    }
    @Override
    public boolean tryCaptureView(View child, int pointerId) {
    return false;
    }
    });
    // 滑动范围
    mDragHelper.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT);
    }
    // 右侧要出现的View
    private View mDividerView;
    // 内容
    private View mContentView;
    @Override
    protected void onFinishInflate() {
    super.onFinishInflate();
    mDividerView = getChildAt(0);
    mDividerView.setAlpha(0f);
    mContentView = getChildAt(1);
    }
    // 设置finish 回调
    public void setCallBack(CallBack mCallBack) {
    this.mcCallBack = mCallBack;
    }
    private CallBack mcCallBack;
    public interface CallBack {
    void onShouldFinish();
    }
    // 让ViewDragHelper来处理Touch事件
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
    return mDragHelper.shouldInterceptTouchEvent(ev);
    }
    @Override
    public boolean onTouchEvent(MotionEvent event) {
    mDragHelper.processTouchEvent(event);
    return true;
    }
    }
  • layout.xml : activity_main.xml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <io.github.jungletian.gradle_export_jar.SwipeBackFrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/swipe_back"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
    android:layout_width="40dp"
    android:layout_height="match_parent"
    android:background="#ffff00"
    android:gravity="center"
    android:text="@string/hello_world" />
    <View
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ff00ff" />
    </io.github.jungletian.grad
    le_export_jar.SwipeBackFrameLayout>
  • 动画 : no_anim.xml 与 out_to_right.xml

    1
    2
    3
    4
    5
    <alpha
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="300"
    android:fromAlpha="1.0"
    android:toAlpha="1.0"></alpha>


1
2
3
4
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
android:fromXDelta="0%"
android:toXDelta="100%"></translate>

  • Activity :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    public class MainActivity extends AppCompatActivity {
    SwipeBackFrameLayout mSwipeBack;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mSwipeBack = (SwipeBackFrameLayout) findViewById(R.id.swipe_back);
    mSwipeBack.setCallBack(new SwipeBackFrameLayout.CallBack() {
    @Override
    public void onShouldFinish() {
    finish();
    overridePendingTransition(R.anim.no_anim, R.anim.out_to_right);
    }
    });
    }
    }