Android開發(fā)中RecyclerView item點(diǎn)擊(二)

其實可以在一篇文章中寫完這6種方式娃圆,但是我自己的習(xí)慣——不喜歡閱讀太長的文章褪储,硬生生的被我截斷了疗韵,其實主要是這幾種沒有什么聯(lián)系,分開讀也無所謂李命。繼續(xù)剩下的3種:
4.定義一個自己的RecyclerView類
見代碼:

//初始化
private void init() {
        addOnChildAttachStateChangeListener(new OnChildAttachStateChangeListener() {
            @Override//當(dāng)子View被添加到Window
            public void onChildViewAttachedToWindow(View view) {
                //此處參數(shù)的view就是ItemView
                //這里可以這么實現(xiàn)
                view.setOnClickListener(new View.OnClickListener(){
                    public void onClick(View v){
                        //這里就可以回調(diào)自己定義的接口方法了
                    }
                });
            }

            @Override//當(dāng)子View從Window中移除/解綁
            public void onChildViewDetachedFromWindow(View view) {
                //此處參數(shù)的view就是ItemView
                //那么這里我們可以做些什么事了登淘?
                //兩種方案:
                //1.啥也不做;
                    // do nothing
                //2.把view的點(diǎn)擊事件取消
                view.setOnClickListener(null);
            }
        });
}

出自簡書:http://www.reibang.com/p/3070695619b9
其實和上一篇是一個人寫的项戴,我喜歡簡單粗暴,于是直接放了鏈接槽惫,還有這種方法我還沒試周叮,明天寫個demo試試。
5.RecyclerView 已有的方法 addOnItemTouchListener()+GestureDetectorCompat
(1)為RecyclerView添加addOnItemTouchListener
查看 RecyclerView 源碼可以看到, RecyclerView 預(yù)留了一個Item的觸摸事件方法:

/**
 * Add an {@link OnItemTouchListener} to intercept touch events before they are dispatched
 * to child views or this view's standard scrolling behavior.
 *
 * <p>Client code may use listeners to implement item manipulation behavior. Once a listener
 * returns true from
 * {@link OnItemTouchListener#onInterceptTouchEvent(RecyclerView, MotionEvent)} its
 * {@link OnItemTouchListener#onTouchEvent(RecyclerView, MotionEvent)} method will be called
 * for each incoming MotionEvent until the end of the gesture.
 *
 * @param listener Listener to add
 * @see SimpleOnItemTouchListener
 */
public void addOnItemTouchListener(OnItemTouchListener listener) {
    mOnItemTouchListeners.add(listener);
}

代碼如下:

recyclerView.addOnItemTouchListener(new OnItemTouchListener(recyclerView) {
            @Override
            public void onItemClick(RecyclerView.ViewHolder vh) {
            //item 操作
            }
        });

通過注釋我們可知,此方法是在滾動事件之前調(diào)用.需要傳入一個 OnItemTouchListener 對象. OnItemTouchListener 的代碼如下:

public static interface OnItemTouchListener { 

    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e);

    public void onTouchEvent(RecyclerView rv, MotionEvent e);

    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept);
}

第一個是攔截觸摸事件的界斜,第二個是處理觸摸事件的仿耽,第三個是處理觸摸沖突的。第三個這里我們用不到各薇,不用管项贺,至于前兩個我們只要向下面我們用到的GestureDetectorCompat傳遞MotionEvent為了獲取觸摸的坐標(biāo),最后再定義個abstract回調(diào)。
此接口還提供了一個實現(xiàn)類,且官方推薦使用該實現(xiàn)類 SimpleOnItemTouchListener

/**
 * An implementation of {@link RecyclerView.OnItemTouchListener} that has empty method bodies and
 * default return values.
 * You may prefer to extend this class if you don't need to override all methods. Another
 * benefit of using this class is future compatibility. As the interface may change, we'll
 * always provide a default implementation on this class so that your code won't break when
 * you update to a new version of the support library.
 */
public static class SimpleOnItemTouchListener implements RecyclerView.OnItemTouchListener {
    @Override
    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
        return false;
    }

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

    @Override
    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
    }
}

在觸摸接口中,當(dāng)觸摸時會回調(diào)一個 MotionEvent 對象,通過使用 GestureDetectorCompat 來解析用戶的操作峭判。
(2)寫一個 ItemClickListener
類繼承 SimpleOnItemTouchListener
,構(gòu)造時傳入 RecyclerView
對象和Item點(diǎn)擊回調(diào),并覆寫父類的 boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e)
方法,具體代碼如下:

/**
 * 點(diǎn)擊事件
 */
public class ItemClickListener extends RecyclerView.SimpleOnItemTouchListener {

    private OnItemClickListener clickListener;
    private GestureDetectorCompat gestureDetector;

    public interface OnItemClickListener {

        void onItemClick(View view, int position);

        void onItemLongClick(View view, int position);
    }

    public ItemClickListener(final RecyclerView recyclerView,
                             OnItemClickListener listener) {
        this.clickListener = listener;
        gestureDetector = new GestureDetectorCompat(recyclerView.getContext(),
                new GestureDetector.SimpleOnGestureListener() {
                    @Override
                    public boolean onSingleTapUp(MotionEvent e) {
                        View childView = recyclerView.findChildViewUnder(e.getX(), e.getY());
                        if (childView != null && clickListener != null && gestureDetector.onTouchEvent(e)) {
                            clickListener.onItemClick(childView, recyclerView.getChildAdapterPosition(childView));
                        }
                        return true;
                    }

                    @Override
                    public void onLongPress(MotionEvent e) {
                        View childView = recyclerView.findChildViewUnder(e.getX(), e.getY());
                        if (childView != null && clickListener != null) {
                            clickListener.onItemLongClick(childView,
                                    recyclerView.getChildAdapterPosition(childView));
                        }
                    }
                });
    }

    @Override
    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
        gestureDetector.onTouchEvent(e);
        return false;
    }
}

在 GestureDetectorCompat 的手勢回調(diào)中我們覆寫:

boolean onSingleTapUp(MotionEvent e)
void onLongPress(MotionEvent e)

(3)使用事件監(jiān)聽
在 RecyclerView 的對象中添加 addOnItemTouchListener() 方法,然后在回調(diào)中處理你需要的事件:

recyclerView.addOnItemTouchListener(new SingleItemClickListener(recyclerView,
        new SingleItemClickListener.OnItemClickListener() {

            @Override
            public void onItemClick(View view, int position) {
                DevLog.i("touch click name:" + position);
                Toast.makeText(SingleActivity.this, "touch click:" + position, Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onItemLongClick(View view, int position) {
                DevLog.i("touch long click:" + position);
                Toast.makeText(SingleActivity.this, "touch long click:" + position, Toast.LENGTH_SHORT).show();
            }
        }));

6.當(dāng) ItemView attach RecyclerView 時實現(xiàn)
代碼如下:

public class ItemClickSupport {
    private final RecyclerView mRecyclerView;
    private OnItemClickListener mOnItemClickListener;
    private OnItemLongClickListener mOnItemLongClickListener;

    private View.OnClickListener mOnClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (mOnItemClickListener != null) {
                RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(v);
                mOnItemClickListener.onItemClicked(mRecyclerView, holder.getAdapterPosition(), v);
            }
        }
    };

    private View.OnLongClickListener mOnLongClickListener = new View.OnLongClickListener() {
        @Override
        public boolean onLongClick(View v) {
            if (mOnItemLongClickListener != null) {
                RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(v);
                return mOnItemLongClickListener.onItemLongClicked(mRecyclerView, holder.getAdapterPosition(), v);
            }
            return false;
        }
    };

    private RecyclerView.OnChildAttachStateChangeListener mAttachListener
            = new RecyclerView.OnChildAttachStateChangeListener() {
        @Override
        public void onChildViewAttachedToWindow(View view) {
            if (mOnItemClickListener != null) {
                view.setOnClickListener(mOnClickListener);
            }
            if (mOnItemLongClickListener != null) {
                view.setOnLongClickListener(mOnLongClickListener);
            }
        }

        @Override
        public void onChildViewDetachedFromWindow(View view) {}
    };

    private ItemClickSupport(RecyclerView recyclerView) {
        mRecyclerView = recyclerView;
        mRecyclerView.setTag(R.id.item_click_support, this);
        mRecyclerView.addOnChildAttachStateChangeListener(mAttachListener);
    }

    public static ItemClickSupport addTo(RecyclerView view) {
        ItemClickSupport support = (ItemClickSupport) view.getTag(R.id.item_click_support);
        if (support == null) {
            support = new ItemClickSupport(view);
        }
        return support;
    }

    public static ItemClickSupport removeFrom(RecyclerView view) {
        ItemClickSupport support = (ItemClickSupport) view.getTag(R.id.item_click_support);
        if (support != null) {
            support.detach(view);
        }
        return support;
    }

    public ItemClickSupport setOnItemClickListener(OnItemClickListener listener) {
        mOnItemClickListener = listener;
        return this;
    }

    public ItemClickSupport setOnItemLongClickListener(OnItemLongClickListener listener) {
        mOnItemLongClickListener = listener;
        return this;
    }

    private void detach(RecyclerView view) {
        view.removeOnChildAttachStateChangeListener(mAttachListener);
        view.setTag(R.id.item_click_support, null);
    }

    public interface OnItemClickListener {
        void onItemClicked(RecyclerView recyclerView, int position, View v);
    }

    public interface OnItemLongClickListener {
        boolean onItemLongClicked(RecyclerView recyclerView, int position, View v);
    }
}

上面的代碼中給 RecyclerView 設(shè)置了 OnChildAttachStateChangeListener 事件監(jiān)聽,當(dāng)子 View attach RecyclerView 時設(shè)置事件監(jiān)聽开缎。為了使代碼獨(dú)立簡潔,可以寫在單獨(dú)的類中林螃,無論是監(jiān)聽 ItemView 還是ItemView 中每個子 View 的點(diǎn)擊事件奕删。

出自;http://www.littlerobots.nl/blog/Handle-Android-RecyclerView-Clicks/

最后疗认,歡迎大家吐槽完残,共同進(jìn)步,謝謝横漏。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末谨设,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子缎浇,更是在濱河造成了極大的恐慌扎拣,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件素跺,死亡現(xiàn)場離奇詭異鹏秋,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)亡笑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門侣夷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人仑乌,你說我怎么就攤上這事百拓∏俣В” “怎么了?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵衙传,是天一觀的道長决帖。 經(jīng)常有香客問我,道長蓖捶,這世上最難降的妖魔是什么地回? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮俊鱼,結(jié)果婚禮上刻像,老公的妹妹穿的比我還像新娘。我一直安慰自己并闲,他們只是感情好细睡,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著帝火,像睡著了一般溜徙。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上犀填,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天蠢壹,我揣著相機(jī)與錄音,去河邊找鬼九巡。 笑死知残,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的比庄。 我是一名探鬼主播求妹,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼佳窑!你這毒婦竟也來了制恍?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤神凑,失蹤者是張志新(化名)和其女友劉穎净神,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體溉委,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡鹃唯,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了瓣喊。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片坡慌。...
    茶點(diǎn)故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖藻三,靈堂內(nèi)的尸體忽然破棺而出洪橘,到底是詐尸還是另有隱情跪者,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布熄求,位于F島的核電站渣玲,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏弟晚。R本人自食惡果不足惜忘衍,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望卿城。 院中可真熱鬧枚钓,春花似錦、人聲如沸藻雪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽勉耀。三九已至,卻和暖如春蹋偏,著一層夾襖步出監(jiān)牢的瞬間便斥,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工威始, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留枢纠,地道東北人。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓黎棠,卻偏偏與公主長得像晋渺,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子脓斩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容