1. 程式人生 > >Android RecyclerView自帶原生點選和長按事件

Android RecyclerView自帶原生點選和長按事件

RecyclerView 系統自帶點選和長按事件(可複用)

  • 寫在前面

我們用過RecyclerView的朋友都知道,它是不能直接設定其點選事件的,系統並沒有給我們提供api,不像TextView,Button等控制元件,可以直接setOnClickListener(),所以退而求其次,利用曲線救國的策略,通過回撥,我們一般都是在adapter裡面,單獨設定每一個控制元件的點選事件,然後回調出來,但是,這並不能複用,每次都得重新設計,所以,今天我們說一下,系統自帶的可複用的RecyclerView的點選事件設定。​​​​​​

  • 關鍵類 

RecyclerView.OnItemTouchListener  (介面)

我們需要新建類,實現RecyclerView.OnItemTouchListener 這個介面,重寫onInterceptTouchEvent(RecyclerView rv, MotionEvent e)方法,當我們通過事件傳遞,捕捉到手勢事件之後,將它交給手勢處理的方法,就能夠實現單擊及長按的事件監聽。

    @Override
    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
        View childView = rv.findChildViewUnder(e.getX(), e.getY());
        if (childView == null) {
            return false;
        }
        selectView = childView;
        selectPosition = rv.getChildAdapterPosition(childView);
        /**
         * 交給手勢控制類來處理
         */
        return mGestureDetector.onTouchEvent(e);
    }

    @Override
    public void onTouchEvent(RecyclerView rv, MotionEvent e) {

    }

    @Override
    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

    }

 childView就是被點選的itemView,selectPosition就是被點選的position。

  • 設定監聽 

設定回撥監聽,將GestureDetector方法(手勢操作方法)的處理結果回調回去,就能夠在我們的activity中得到對應的點選事件。

1. 定義監聽介面

設定builder是為了方便只重寫點選事件,或者只重寫長按事件。  又定義一個normal介面是為了區別於其他的點選事件,這裡並沒有定義其他的點選事件。如果擴充套件,定義內部介面會比較好。

    public interface OnItemClickListener {

        interface Normal {

            void onItemClick(View view, int position);

            void onItemLongClick(View view, int position);

            class Builder implements Normal {

                @Override
                public void onItemClick(View view, int position) {

                }

                @Override
                public void onItemLongClick(View view, int position) {

                }
            }
        }


    }

 2. 新增監聽構造方法

這是一個構造方法,將此方法作為一個例項,傳入被呼叫的方法即可,呼叫方法見3.

    public RecyclerItemClickListener(Context context, final OnItemClickListener.Normal mListener) {

        mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
            /**
             * 點選
             */
            @Override
            public boolean onSingleTapUp(MotionEvent e) {
                if (selectView != null && mListener != null){
                    mListener.onItemClick(selectView, selectPosition);
                    return true;
                }
                return super.onSingleTapUp(e);
            }

            /**
             * 長按
             */
            @Override
            public void onLongPress(MotionEvent e) {
                if (selectView != null && mListener != null){
                    mListener.onItemLongClick(selectView, selectPosition);
                }
            }

        });
    }

 3. 呼叫點選事件方法


    // recyclerView  呼叫自己的addOnItemTouchListener方法,引數傳入我們定義的類RecyclerItemClickListener的例項
    recycleView.addOnItemTouchListener(new RecyclerItemClickListener(context, onItemClickListener));


    //  這是回撥方法,在下面的回撥裡面新增自己的處理邏輯,這裡有三種寫法
    //  1.只回調單擊事件
    private RecyclerItemClickListener.OnItemClickListener.Normal onItemClickListener = new RecyclerItemClickListener.OnItemClickListener.Normal.Builder() {
        @Override
        public void onItemClick(View view, int position) {

            // 在這裡寫自己的單擊事件邏輯
        }
    };

    
    // 2.只回調長按事件
    private RecyclerItemClickListener.OnItemClickListener.Normal onItemClickListener = new RecyclerItemClickListener.OnItemClickListener.Normal.Builder() {
        @Override
        public void onItemLongClick(View view, int position) {

            // 在這裡寫自己的長按事件邏輯
        }
    };

    // 3.同時回撥點選和長按事件
    private RecyclerItemClickListener.OnItemClickListener.Normal onItemClickListener = new RecyclerItemClickListener.OnItemClickListener.Normal() {
        @Override
        public void onItemClick(View view, int position) {

            // 在這裡寫自己的單擊事件邏輯
        }

        @Override
        public void onItemLongClick(View view, int position) {

            // 在這裡寫自己的長按事件邏輯
        }
    };

  • 結束語

好了,可點選,可長按,可複用的RecyclerView的點選事件就介紹到這裡了,歡迎大家指正批評。

附上完整程式碼



import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;

public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener {

    private GestureDetector mGestureDetector;

    /**
     * 被選擇的view
     */
    private View selectView;
    /**
     * 被選擇view的position
     */
    private int selectPosition;

    @Override
    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
        View childView = rv.findChildViewUnder(e.getX(), e.getY());
        if (childView == null) {
            return false;
        }
        selectView = childView;
        selectPosition = rv.getChildAdapterPosition(childView);
        /**
         * 交給手勢控制類來處理
         */
        return mGestureDetector.onTouchEvent(e);
    }

    @Override
    public void onTouchEvent(RecyclerView rv, MotionEvent e) {

    }

    @Override
    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

    }

   
    public RecyclerItemClickListener(Context context, final OnItemClickListener.Normal mListener) {

        mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
            /**
             * 點選
             */
            @Override
            public boolean onSingleTapUp(MotionEvent e) {
                if (selectView != null && mListener != null){
                    mListener.onItemClick(selectView, selectPosition);
                    return true;
                }
                return super.onSingleTapUp(e);
            }

            /**
             * 長按
             */
            @Override
            public void onLongPress(MotionEvent e) {
                if (selectView != null && mListener != null){
                    mListener.onItemLongClick(selectView, selectPosition);
                }
            }

        });
    }

    public interface OnItemClickListener {

        interface Normal {

            void onItemClick(View view, int position);

            void onItemLongClick(View view, int position);

            class Builder implements Normal {

                @Override
                public void onItemClick(View view, int position) {

                }

                @Override
                public void onItemLongClick(View view, int position) {

                }
            }
        }


    }
}