ViewDragHelper 实现侧滑(二)

1 引言  

android support v4中比较强大的类ViewDragHelper。自定义View(三) switch开关按钮 ViewDragHelper的使用初级 该文章粗略简述了ViewDragHelper的使用。本文进一步升级 使用ViewDragHelper类实现侧滑效果。注这里实现效果类似侧拉删除效果。(如果想实现侧拉删除效果需要自定义回调函数和处理逻辑   参照本文也可以实现自己的slidebar)

2 布局

   均较为简单 可根据自己的需求更改:
(1)left_view.xml布局如下:为学号和姓名

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ccc"
    >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:gravity="center"
        android:paddingLeft="20dp"
        android:text="姓名"
        android:textColor="#f03744"
        android:textSize="18sp" />
    <TextView
        android:paddingLeft="20dp"
        android:gravity="center"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:text="学号"
        android:textColor="#f03744"
        android:textSize="18sp" />
</LinearLayout>
(2)right_view.xml 为编辑按钮

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:background="#4690BD"
    >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:gravity="center"
        android:paddingLeft="20dp"
        android:text="删除"
        android:textColor="#f03744"
        android:textSize="18sp" />
    <TextView
        android:paddingLeft="20dp"
        android:gravity="center"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:text="编辑"
        android:textColor="#f03744"
        android:textSize="18sp" />
</LinearLayout>
  (3) 主要布局 activity_main

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    >
    <com.example.myswipedemo.MySwipeView
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:layout_gravity="center_horizontal"
        android:orientation="horizontal"
        >
        <include layout="@layout/left_view"
            android:id="@+id/lview"
            />
        <include layout="@layout/right_view"
            android:id="@+id/rview"/>

    </com.example.myswipedemo.MySwipeView>

</LinearLayout>
com.example.myswipedemo.MySwipeView为本文自定义的ViewGroup 为简便本文继承RelativeLayout

3 自定义的ViewGroup

public class MySwipeView extends RelativeLayout {
    private ViewDragHelper mDragger;
    private int mRange;
    View mLeftView;  //正常显示的View
    View mRightView;//编辑模式下显示的View
    private int mRightWidth; //右边View的宽度

    public MySwipeView(Context context) {
        this(context, null);
    }

    public MySwipeView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    public MySwipeView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return mDragger.shouldInterceptTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        mDragger.processTouchEvent(event);
        return true;
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        mLeftView = getChildAt(0);
        mRightView =  getChildAt(1);
        int left = getMeasuredWidth();//左边此时完全显示 宽度是整个View宽度
        //左边View放于左边View的右边 超出屏幕 故不显示
        mRightView.layout(left, 0, left + mRightView.getMeasuredWidth(), mRightView.getMeasuredHeight());
        mRange = left - mRightView.getMeasuredWidth();
        mRightWidth = mRightView.getWidth();
    }





    @Override
    public void computeScroll() {  //ViewCompat.postInvalidateOnAnimation
//不断回调此函数
        if (mDragger.continueSettling(true)) {
            ViewCompat.postInvalidateOnAnimation(this);
        }
    }



    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        mDragger = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() {//初始化ViewDragHelper
            @Override
            public boolean tryCaptureView(View child, int pointerId) {
                return true;
            }

            @Override
            public int clampViewPositionHorizontal(View child, int left, int dx) {
                if (child == mLeftView) {  //左侧View  的left 值 最大为0 最小为 -mRightWidth
                    left = Math.min(0,Math.max(-mRightWidth, left));
                }
                if (child == mRightView) {//同上
                    left = Math.min(mLeftView.getWidth()+mRightWidth,Math.max(mLeftView.getWidth()-mRightWidth,left));
                }
                return left;
            }

            @Override
            public void onViewReleased(View releasedChild, float xvel, float yvel) {
                if (xvel > 0) {//显示左边view
                    mDragger.smoothSlideViewTo(mLeftView,0, 0);
                } else if((xvel == 0) && (mLeftView.getLeft() > (-mRightWidth / 3))) {//显示左边view
                    mDragger.smoothSlideViewTo(mLeftView,0, 0);
                }else if((xvel == 0) && (mLeftView.getLeft() <= (-mRightWidth / 3))){
                    mDragger.smoothSlideViewTo(mLeftView,-mRightWidth, 0);
                }else if(xvel <0){
                    mDragger.smoothSlideViewTo(mLeftView,-mRightWidth, 0);
                }
                ViewCompat.postInvalidateOnAnimation(MySwipeView.this);;
            }

            @Override
            public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
                if (changedView == mLeftView) {
                    mRightView.offsetLeftAndRight(dx);
                } else if (changedView == mRightView) {
                    mLeftView.offsetLeftAndRight(dx);
                }
                ViewCompat.postInvalidateOnAnimation(MySwipeView.this);;//一定要刷新,不然会没效果
            }

            @Override
            public int getViewHorizontalDragRange(View child) {
                return mRange;
            }
        });
    }
}


(1) ViewDragHelper的初始化本文不再赘述。ViewGroup的自定义分别经历如下步骤:
a onMeasure 在onMeasure中计算childView的测量值以及模式,以及设置自己的宽和高:
b onLayout对其所有childView进行定位
c dispatchDraw 本文用不上。
(2)使用getChildAt()获取xml中的子View
(3)使用getMeasuredWidth()获取测量后的宽
(4)mRightWidth左边未显示(超出屏幕)的view的宽度
(5) public int clampViewPositionHorizontal(View child, int left, int dx)
为水平拉动后View的left值(为变化后的值)与上一节类似不再赘述。
(6)如下函数为本文重点:View的位置改变的时候
public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy)
if (changedView == mLeftView) {
                    mRightView.offsetLeftAndRight(dx);
                } 
                ViewCompat.postInvalidateOnAnimation(MySwipeView.this);;//一定要刷新,不然会没效果
该句实现 拉动左边View 将移动距离dx 同时交给右边View
(7) public void onViewReleased(View releasedChild, float xvel, float yvel ) 实现松开View 弹回或显示右边View
     里面的  mDragger.smoothSlideViewTo(mLeftView,0, 0); 第一个参数是滑动的View 后面两个参数是View最后的left 和top
    回调computeScroll()来实现平滑移动。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值