RecycleView使用体验(二)

仿QQ会话列表,左滑item的时候,展示出删除等菜单。

把每个Item看成一个LinearLayout,它包含两个子控件,一个是Item要显示的内容,还有一个当然就是我们的右侧菜单了

<?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:orientation="horizontal">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="20dp">
        <TextView
            android:id="@+id/tv_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
    </RelativeLayout>

    <LinearLayout
        android:layout_width="80dp"
        android:layout_height="match_parent">
        <TextView
            android:id="@+id/tv_delete"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:background="@android:color/holo_red_light"
            android:gravity="center"
            android:text="删除"
            android:textColor="@android:color/white"/>
    </LinearLayout>

</LinearLayout>

接着将整个菜单的显示与隐藏把封闭在ItemSlideHelper里面,关键的代码如下

@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
    Log.d(TAG, "onInterceptTouchEvent: " + e.getAction());

    int action =  MotionEventCompat.getActionMasked(e);
    int x = (int) e.getX();
    int y = (int) e.getY();

    //如果RecyclerView滚动状态不是空闲targetView不是空
    if(rv.getScrollState() != RecyclerView.SCROLL_STATE_IDLE){
        if(mTargetView != null){
            //隐藏已经打开
            smoothHorizontalExpandOrCollapse(DEFAULT_DURATION / 2);
            mTargetView = null;
        }

        return false;
    }

    //如果正在运行动画 ,直接拦截什么都不做
    if(mExpandAndCollapseAnim != null && mExpandAndCollapseAnim.isRunning()){
        return true;
    }

    boolean needIntercept =  false;
    switch (action) {
        case MotionEvent.ACTION_DOWN:
            mActivePointerId = MotionEventCompat.getPointerId(e, 0);
            mLastX = (int) e.getX();
            mLastY = (int) e.getY();

            /*
            * 如果之前有一个已经打开的项目,当此次点击事件没有发生在右侧的菜单中则返回TRUE
            * 如果点击的是右侧菜单那么返回FALSE这样做的原因是因为菜单需要响应Onclick
            * */
            if(mTargetView != null){
                return !inView(x, y);
            }

            //查找需要显示菜单的view;
            mTargetView = mCallback.findTargetView(x, y);

            break;
        case MotionEvent.ACTION_MOVE:
            int deltaX = (x - mLastX);
            int deltaY = (y - mLastY);

            if(Math.abs(deltaY) > Math.abs(deltaX))
                return false;

            //如果移动距离达到要求,则拦截
            needIntercept = mIsDragging = mTargetView != null && Math.abs(deltaX) >= mTouchSlop;

            if(isExpanded()){
                needIntercept = true;
                //折叠菜单
                smoothHorizontalExpandOrCollapse(DEFAULT_DURATION / 2);
                mTargetView = null;
            }
            break;

        case MotionEvent.ACTION_CANCEL:
        case MotionEvent.ACTION_UP:
            /*
            * 走这是因为没有发生过拦截事件
            * */
            if(isExpanded()){

                if (inView(x, y)) {
                  // 如果走这那行这个ACTION_UP的事件会发生在右侧的菜单中
                    Log.d(TAG, "click item");
                }else{
                    //拦截事件,防止targetView执行onClick事件
                    needIntercept = true;
                }

                //折叠菜单
                smoothHorizontalExpandOrCollapse(DEFAULT_DURATION / 2);
            }

            mTargetView = null;
            break;
    }
    return  needIntercept ;
}
@Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
    Log.d(TAG, "onTouchEvent: " + e.getAction());

    if(mExpandAndCollapseAnim != null && mExpandAndCollapseAnim.isRunning() || mTargetView == null)
        return;

    //如果要响应fling事件设置将mIsDragging设为false
    if (mGestureDetector.onTouchEvent(e)) {
        mIsDragging = false;
        return;
    }
    int x = (int) e.getX();
    int y = (int) e.getY();
    int action =  MotionEventCompat.getActionMasked(e);
    switch (action) {
        case MotionEvent.ACTION_DOWN:
            //RecyclerView 不会转发这个Down事件

            break;
        case MotionEvent.ACTION_MOVE:
            int deltaX = (int) (mLastX - e.getX());
            if(mIsDragging) {
                horizontalDrag(deltaX);
            }
            mLastX = x;
            break;

        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_CANCEL:

             if(mIsDragging){
                if(!smoothHorizontalExpandOrCollapse(0) && isCollapsed())
                    mTargetView = null;

                mIsDragging = false;
             }
            break;
    }
}

ItemSlideHelper里面有个接口,最后让Adapter实现这个接口即可

public interface Callback {

    int getHorizontalRange(RecyclerView.ViewHolder holder);

    RecyclerView.ViewHolder getChildViewHolder(View childView);

    View findTargetView(float x, float y);

}

本文转自http://www.tuicool.com/articles/2ENBb2Q

源码

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章