手记

Android三种方式实现RecyclerView的Item点击事件

今天来学习一下如何实现RecyclerView的Item的点击事件.实现Item的点击事件有三种方式:

1.   通过RecyclerView已有的方法addOnItemTouchListener()实现

2.   在创建ItemView时添加点击监听

3.   当ItemView attach RecyclerView时实现

1. 通过RecyclerViewaddOnItemTouchListener()实现

1.1 查看源码

查看RecyclerView源码可以看到,RecyclerView预留了一个Item的触摸事件方法:

[代码]java代码:

?

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

/**

 * 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.</p>

 *

 * @param listener Listener to add

 * @see SimpleOnItemTouchListener

 */

public void addOnItemTouchListener(OnItemTouchListener   listener) {

    mOnItemTouchListeners.add(listener);

}

 

通过注释我们可知,此方法是在滚动事件之前调用.需要传入一个OnItemTouchListener对象.OnItemTouchListener的代码如下:

[代码]java代码:

?

1

2

3

4

5

6

7

8

public static interface OnItemTouchListener {

  

    public boolean onInterceptTouchEvent(RecyclerView   rv, MotionEvent e);

  

    public void onTouchEvent(RecyclerView   rv, MotionEvent e);

  

    public void onRequestDisallowInterceptTouchEvent(boolean   disallowIntercept);

}

 

此接口还提供了一个实现类,且官方推荐使用该实现类SimpleOnItemTouchListener

 

在触摸接口中,当触摸时会回调一个MotionEvent对象,通过使用GestureDetectorCompat来解析用户的操作.

1.2 实现点击事件监听

写一个ItemClickListener类继承SimpleOnItemTouchListener,构造时传入RecyclerView对象和Item点击回调,并覆写父类的boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e)方法,具体代码如下:

[代码]java代码:

?

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

/**

 * 点击事件

 * Created by DevWiki on 2016/7/16.

 */

  

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的手势回调中我们覆写:

1.   boolean onSingleTapUp(MotionEvent e)单击抬起回调

2.   void onLongPress(MotionEvent e)长按回调

1.3 使用事件监听

在RecyclerView的对象中添加addOnItemTouchListener()方法,然后在回调中处理你需要的事件:



[代码]java代码:

?

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

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();

            }

        }));

 

2. 在创建ItemView时添加点击监听

这种方法和ListView一样,在Adapter里面创建View时添加点击事件.比如:

[代码]java代码:

?

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21

@Override

public void bindCustomViewHolder(SingleHolder holder,   final int position) {

    Person person =   getItem(position);

    holder.nameView.setText(person.getName());

    holder.ageView.setText(String.valueOf(person.getAge()));

  

    if (clickListener != null) {

        holder.nameView.setOnClickListener(new   View.OnClickListener() {

            @Override

            public   void onClick(View v) {

                clickListener.onNameClick(position);

            }

        });

        holder.ageView.setOnClickListener(new   View.OnClickListener() {

            @Override

            public   void onClick(View v) {

                clickListener.onAgeClick(position);

            }

        });

    }

}

 

然后在Adapter对象上添加监听回调:

[代码]java代码:

?

01

02

03

04

05

06

07

08

09

10

11

12

13

singleAdapter.setClickListener(new SingleAdapter.OnSingleItemClickListener()   {

    @Override

    public void onNameClick(int position)   {

        DevLog.i("adapter   click name:" + position);

        Toast.makeText(SingleActivity.this,   "adapter click name:" + position, Toast.LENGTH_SHORT).show();

    }

  

    @Override

    public void onAgeClick(int position)   {

        DevLog.i("adapter   click age:" + position);

        Toast.makeText(SingleActivity.this,   "adapter click name:" + position, Toast.LENGTH_SHORT).show();

    }

});

 

3. ItemView attach RecyclerView时实现

该实现方法是在阅读国外的一篇博客时发现的,原文链接如下:Getting your clicks on RecyclerView

实现的代码如下:

[代码]java代码:

?

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

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设置了OnChildAttachStateChangeListener事件监听,当子View attach RecyclerView时设置事件监听.

[代码]java代码:

?

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

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) {}

};

 

4. 三种方式对比

以上三种方式分别是:

1.   通过RecyclerView已有的方法addOnItemTouchListener()实现

2.   在创建ItemView时添加点击监听

3.   当ItemView attach RecyclerView时实现

从以上三种方式的实现过程可知:

1.   三种均可实现ItemView的点击事件和长按事件的监听.

2.   第一种方式可以很方便获取用户点击的坐标.

3.   第二种和第三种方式可以很方便对ItemView中的子View进行监听.

4.   第一种方式和第三种方式可以写在单独的类中,相对于第二种写在Adapter的方式可使代码更独立整洁

综上所述:

如果你只想监听ItemView的点击事件或长按事件,三种方式均可.

如果你想监听ItemView中每个子View的点击事件,采用第二种或者第三种比较方面.

原文链接:http://www.apkbus.com/blog-705730-61341.html

0人推荐
随时随地看视频
慕课网APP