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

源碼

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