- RecyclerView Item Click Listener the Right Way
- Example Scenario
- Project Creation
- Data model
- Recyclerview Adapter and view holder
- Item Click the bad way
- Let us fix it
- Defining item click listener for RecyclerView in Android
- grantland / post.md
- This comment has been minimized.
- matthewmichihara commented Jul 3, 2014
- This comment has been minimized.
- alexnavratil commented Jul 3, 2014
- This comment has been minimized.
- jacobtabak commented Oct 4, 2014
- This comment has been minimized.
- AmauryEsparza commented Feb 16, 2015
- This comment has been minimized.
- lnikkila commented Mar 9, 2015
- This comment has been minimized.
- ghost commented Apr 29, 2015
- This comment has been minimized.
- ghost commented Jul 9, 2015
- This comment has been minimized.
- riyazMuhammad commented Jul 22, 2015
- This comment has been minimized.
- yosraa commented Jul 30, 2015
- This comment has been minimized.
- dinigo commented Aug 20, 2015
- This comment has been minimized.
- IgorGanapolsky commented Oct 2, 2015
- This comment has been minimized.
- dinesh-gadri commented Nov 19, 2015
- This comment has been minimized.
- dinesh-gadri commented Nov 19, 2015
- This comment has been minimized.
- mayooresan commented Jan 6, 2016
- This comment has been minimized.
- dima925 commented Mar 14, 2016
- This comment has been minimized.
- shubham08gupta commented May 1, 2016
- This comment has been minimized.
- MansoorJafari commented Jun 29, 2016
- This comment has been minimized.
- pradeepkumarreddyk commented Jul 12, 2016
- This comment has been minimized.
- EliudNjuguna commented Sep 17, 2016
- This comment has been minimized.
- devmike01 commented Oct 17, 2016
- This comment has been minimized.
- MinaGabriel commented Nov 18, 2016
- This comment has been minimized.
- SkymanOne commented Dec 6, 2016 •
- This comment has been minimized.
- JSila commented Feb 15, 2017
- This comment has been minimized.
- ayetolusamuel commented Apr 11, 2018
- This comment has been minimized.
- ax-vasquez commented Jul 20, 2018
- This comment has been minimized.
- deweysia commented Nov 11, 2018
- This comment has been minimized.
- nayzawoo commented Feb 11, 2019
- This comment has been minimized.
- imrankhanissm commented Feb 19, 2019
- This comment has been minimized.
- parthdesai1208 commented May 27, 2019
- This comment has been minimized.
- JaiMistry commented Feb 11, 2020
- This comment has been minimized.
- IrshadKasana commented Sep 8, 2020
- RecyclerView — click everywhere
- So, let’s begin.
- Create the Activity layout
- Generate the dummy data
- The Adapter
- The essential part
- We finish
RecyclerView Item Click Listener the Right Way
Some Android developers wonder why Google created a view like Recyclerview without a click listener(given the fact that the deprecated ListView has an item click listener).
Because there is no standard way of setting a click listener, new developers tend to confuse on the right way of doing it. In this article, I will show you how to do it in a proper way using an example scenario.
Example Scenario
- There is a Recyclerview adapter with a Recyclerview with a list of items(Users in this case).
- What we want is that when an item is clicked, we get the item’s model(User) information and may be pass it to a second activity.
Project Creation
From Android Studio, create an empty android project(Select the Kotlin support option) and name your activity, MainActivity.
- Delete the default ‘Hello World’ TextView in activity_main.xml .
- Add recyclerview and cardview dependencies in app level build.gradle file as shown below.
Add recyclerview in activity_main.xml where you removed the textview as shown below.
Ok we are good to go. The assumption is that you have worked with the recyclerview(in Java) before and know how to create a recyclerview adapter.. Next, we create the model class containing username and phone.
Data model
Sweet Kotlin. Just the above line of code gives us access to a setter and getter under the hood and other methods like toString. Check more at https://kotlinlang.org/docs/reference/data-classes.html .
Next, we create our view holder and adapter. Pay attention here because it is the most important part of what this article addresses.
Recyclerview Adapter and view holder
- Create a new Kotlin file called RecyclerAdapter.kt
- Next we create our item_user.xml layout as follows
The item_user has two textviews which holds the name and phone.
Next we create our view holder. As usual, our view holder has a constructor with an itemView as parameter and we get a reference to our views from item_user layout .
Then we create our adapter with the list of users as a parameter. An adapter contains the list of users
Item Click the bad way
Note that in onBindView, we can have access to the the current clicked item and thus open a new activity from here and pass our data..
This will work perfectly but it is a bad practice because
- It is not a good practice opening an Activity from a viewholder context
- Note that onBindViewHolder is called as your views are populated during scrolling. Thus you will have numerous calls to setOnClickListener.
Let us fix it
The way that you should do is that you create an ItemClickListener interface with one method ontemClicked with parameter User.
- We then pass modify the Adapter’s constructor to take the users list and an OnItemClickListener interface
- We also modify the the ViewHolder to have a bind function which takes a user and itemClick interface as follows.
This is all we have to do. We just have to implement the interface in our MainActivity .
Источник
Defining item click listener for RecyclerView in Android
Android RecyclerView doesn’t come with the Item Click Listener that you have with ListView. You will have to implement the item clicke listener yourself. Here is an example of how to implement the view holder item clicker listener in RecyclerView. In a nutshell, The Activity class will implement an interface for onClick event, this interface will be passed to the RecyclerView Adapter class, then the ViewHolder class in the RecyclerView will call onClick method defined in the interface, which will pass the view and position of the clicked item to the onClick implementation in the Activity class.
1. We will need a listener interface.
2. In your ViewHolder class in your RecyclerView adapter, implement View.OnClickListener, bind the listener to the view. In the onClick method, call the onClick method of the interface OnItemClickListener. This should be passed in from your RecycyclerView’s constructor. The actual implementation of the onclick event will be from an activity or fragment that contains this RecyclerView. The important line here is clickListener.onClick(view, getPosition()); where clickListener is a global variable in your RecyclerView class, again it should’ve passed in from your RecyclerView’s constructor.
3. The onClick implementation in the Activity class, the important line here is mAdapter.setClickListener(this); and the onClick method. The onClick method gets triggered from the ViewHolder’s onClick method in your RecyclerView class, which passes the view and position of the clicked item.
4. All together:
The interface class, ItemClickListener.java
The RecyclerView Adapter class, CityAdapter.java
The Activity class, CityActivity.java
The layout files are not provided for above sample are not provided since this post is not about layout.
Источник
grantland / post.md
RecyclerView item onClick
RecyclerView does not have an OnItemClickListener like it’s predecessor, ListView . However, detecting item clicks is pretty simple.
Set an OnClickListener in your ViewHolder creation:
Add touch feedback to your item layout:
This comment has been minimized.
Copy link Quote reply
matthewmichihara commented Jul 3, 2014
how do you find out about all these ?android:attr values? I never know what exists
This comment has been minimized.
Copy link Quote reply
alexnavratil commented Jul 3, 2014
This comment has been minimized.
Copy link Quote reply
jacobtabak commented Oct 4, 2014
You should not couple your ViewHolders and ItemClickListeners. Please see a better solution here.
This comment has been minimized.
Copy link Quote reply
AmauryEsparza commented Feb 16, 2015
@jacobtabak that exactly is what i think, but how you get the position element was clicked on the RecyclerView? I’m just find answers like above.
This comment has been minimized.
Copy link Quote reply
lnikkila commented Mar 9, 2015
This comment has been minimized.
Copy link Quote reply
ghost commented Apr 29, 2015
@jacobtabak how to get click listener on individual views in the row item. The click is intercepted by on touch right??
This comment has been minimized.
Copy link Quote reply
ghost commented Jul 9, 2015
This comment has been minimized.
Copy link Quote reply
riyazMuhammad commented Jul 22, 2015
This comment has been minimized.
Copy link Quote reply
yosraa commented Jul 30, 2015
how to get startactivity in onclick()
This comment has been minimized.
Copy link Quote reply
dinigo commented Aug 20, 2015
This works on my head, but doesn’t run as expected. The onClick() is never triggered, and I can’t find why
This comment has been minimized.
Copy link Quote reply
IgorGanapolsky commented Oct 2, 2015
@jacobtabak Read the comment in the solution you linked to:
This will not provide any clue about which button or view (within the item) was clicked.
This comment has been minimized.
Copy link Quote reply
dinesh-gadri commented Nov 19, 2015
how to delete row in recycler view.
plzz help me
This comment has been minimized.
Copy link Quote reply
dinesh-gadri commented Nov 19, 2015
how to delete row in recycle view when click on delete than that row is delete..plzzz help me
This comment has been minimized.
Copy link Quote reply
mayooresan commented Jan 6, 2016
@demil133 after adding android:clickable=»true» to the parent element for the item’s layout in xml, it started to work. Hope it’ll help someone out there.
This comment has been minimized.
Copy link Quote reply
dima925 commented Mar 14, 2016
Good sample. it’s well for my app.
This comment has been minimized.
Copy link Quote reply
shubham08gupta commented May 1, 2016
This comment has been minimized.
Copy link Quote reply
MansoorJafari commented Jun 29, 2016
Hi
I have a recycler view with event onTap Listener and in item row I have a TextView that have click listener event
in my code OnTap only work. mean after click textview event onTap run and textview event dont work.
please help for solve this problem.
This comment has been minimized.
Copy link Quote reply
pradeepkumarreddyk commented Jul 12, 2016
where did you add touch feedback to item layout
This comment has been minimized.
Copy link Quote reply
EliudNjuguna commented Sep 17, 2016
How do you implement onClickListener on GridLayout using the RecyclerView
This comment has been minimized.
Copy link Quote reply
devmike01 commented Oct 17, 2016
This code doesn’t work, but this does work
This comment has been minimized.
Copy link Quote reply
MinaGabriel commented Nov 18, 2016
the base class doesn’t have any on click method.
This comment has been minimized.
Copy link Quote reply
SkymanOne commented Dec 6, 2016 •
but can use int item instead of String item and it’s easier work with items
This comment has been minimized.
Copy link Quote reply
JSila commented Feb 15, 2017
getPosition is deprecated, use getAdapterPosition instead.
This comment has been minimized.
Copy link Quote reply
ayetolusamuel commented Apr 11, 2018
thanks, this save me from item clicklistener mess.
Though this is what i use.
int itemPosition = getLayoutPosition();
Products products = productsArrayList.get(itemPosition);
Thanks for the clue
This comment has been minimized.
Copy link Quote reply
ax-vasquez commented Jul 20, 2018
Thanks! This is by far the cleanest solution I have seen for this. Helped a lot!
This comment has been minimized.
Copy link Quote reply
deweysia commented Nov 11, 2018
Short and concise. Thanks!
This comment has been minimized.
Copy link Quote reply
nayzawoo commented Feb 11, 2019
I use this method
This comment has been minimized.
Copy link Quote reply
imrankhanissm commented Feb 19, 2019
This comment has been minimized.
Copy link Quote reply
parthdesai1208 commented May 27, 2019
thanks for the code, you saved my lot of time.
This comment has been minimized.
Copy link Quote reply
JaiMistry commented Feb 11, 2020
how to get startactivity in onclick()
This comment has been minimized.
Copy link Quote reply
IrshadKasana commented Sep 8, 2020
how to implement onItemClickListener on individual items/icons of viewHolder in a recyclerView and perform actions on them inside fragment/activity, but not inside the adapter
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Источник
RecyclerView — click everywhere
It has been widely agreed that RecyclerView object is a great addition to the Android SDK. Besides its benefits we take advantage of, there are certain issues which the developers need to solve when using that object. One of the most common is the problem of setting RecyclerView items click listener.
What I have seen in my Android experience is that there are many ways and different approaches to set RecyclerView items click listener. For example, I have met listeners to get passed through the RecyclerView Adapter and then into the ViewHolder and at the end all the way back to the Activity again. I have seen also an implementation using EventBus and so on, but none of them really make me feel comfortable.
However, it seems almost none of the existing approaches works completely well as number of unwanted consequences occur, some of which even leading to Memory Leaks. Considering my practice so far, I personally would prefer a way to tackle the problem, as described in the following article .
Despite the text has been well written, providing enough knowledge to set simple item listener, it still does not cover the case when the product may require more advanced work. For example, if the product has the requirements for setup click listeners in specific parts of the items (specific sub Views). In such cases, we shall appreciate that the things are getting a little bit more complicated and require development work in greater depth.
The focus of the current article is to provide a feasible solution of the problem described above. I would draw your attention to my own generic solution which would be ready to apply on any project and in any scenario given. The reason the source code hereinafter has been written in Kotlin is because of my belief that it is the best language for Android native development so far.
To avoid any additional complications, I will try to keep the examples as simple as possible. Also, I shall not embark on any of the useful Android libraries to achieve the goal (so no RxJava, no Dagger, no Retrofit etc.). Moreover, I aim to avoid using any specific Android application design pattern as well (so no MVP, no MVVM, no clean architecture etc.).
What I shall try is to keep my code as simple as possible, except the generic part, where the “magic” should happen. And finally, I will try to stay focused only around the click events on specific views in the RecyclerView items.
Here is the public GitHub repository, where you can find the complete source code written in Kotlin.
What are the steps we need to complete?
- We have to create new Android Studio project with one empty Activity. The name of the project is up to you;
- In the xml layout of the Activity, we are going to put one RecyclerView, which needs to take the full device screen. The RecyclerView will be used to display (render) some list items on the screen.
- In the Activity, we have to create an ArrayList with 20 items inside and mock some data (no API requests). Later this data will be passed to the Adapter attached to the RecyclerView.
- Before we start with RecyclerView item click listener, we have to create out RecyclerView Adapter and the corresponding ViewHolder, where the data will be rendered in every single RecyclerView row.
- The final part shall be to create the RecyclerView items click listener with the option to listen for specific view clicks. And here comes the essential part of the article, which would require more detailed explanation.
At the end we should have a generic RecyclerView items click listener with the ability to listen for specific sub View clicks. If you feel yourself comfortable in Android and you know all of the step above you can just jump to the Essential part.
So, let’s begin.
The first step is to create new Android project in Android Studio with one empty Activity. I wouldn’t go into details on how to do it, considering there are tons of tutorials about that on the web. In any case, if someone feels like getting a support, I would recommend to have a look at here
Create the Activity layout
This step is pretty simple and I will just post the source code for the Activity layout (activity_main.xml):
Generate the dummy data
This is really simple and we just need one method inside the Activity, which is going to return a List with 20 ( MAX_ITEMS) custom mock data objects inside.
The Adapter
Before we dive into the custom RecyclerView items click listener, we have to create our RecyclerView adapter, where the items data shall be set. For this tutorial, we gonna use simple RecyclerView adapter with only one view type. Inside the item view type we have to display four things: the product title, the product description and two action buttons — one to backup the product on some cloud service (green button) and the second to block the product (red button). This is how the single row item should look like:
and this is the xml code for single view item (item_custom_data.xml), which we gonna use in the ViewHolder later on to render the dummy data:
It does not need any particular explanation as everything is quite straightforward here. What we need to note however is that we have two action buttons, which we would use later for some custom actions about every specific list item. Once we have the xml layout and the idea how the list item should look on the screen, it’s time to create our RecyclerView Adapter (CustomAdapter.kt):
And here is how our ViewHolder (CustomViewHolder.kt) looks like. It is pretty simple and it just displays the dummy data:
The essential part
When ready with all the preparations mentioned above, we’ve reached to the point where we have to go into our Activity and set some custom RecyclerView items listener, which is going to be able to catch a click events not only for the list item, but also for the custom actions (connected with sub views) inside that item ( backup the item and block the item).
This is how the activity setup method looks like:
To understand how this CustomRecyclerViewItemTouchListener object works, let’s start with the generic (basic) part.
Our CustomRecyclerViewItemTouchListener.kt will be extended from BaseRecyclerViewItemTouchListener.kt, where all of the generic logic will stay. Here is how the BaseRecyclerViewItemTouchListener.kt looks like:
As you can see, BaseRecyclerViewItemTouchListener constructor expects three items:
- recycleView: RecyclerView — the recycler view which items we would like to listen for click events,
- specialViewIDs: IntArray — an IntArray of all special view ids, that we want to have clickable inside the single item view,
- mClickListener: BaseRecyclerViewItemTouchListener.ClickListener — a custom listener object (needs to implement this Interface) where the implementation of all click events will be.
There are two important methods in BaseRecyclerViewItemTouchListener :
- onInterceptTouchEvent(recyclerView: RecyclerView, event: MotionEvent): Boolean
- findExactChild(view: View?, x: Float, y: Float, specialViewClickPadding: Int): View?
The first method is responsible to intercept all touch events on the recyclerview. Inside the MotionEvent object we can find the X and Y coordinates of the touch event. With these coordinates we can use recyclerView.findChildViewUnder(event.x, event.y), where we can get the parent view which was clicked. Once we get the parent view, we can use recyclerView.getChildAdapterPosition(view), where we can get the exact position that has been clicked in our list.
The second method is even more interesting, hiding the secret how the “magic” shall happen. This method will try to find any collisions between the coordinates of the MotionEvent(X and Y) that we have in onInterceptTouchEvent() and the absolute boundaries of any special view, found in the parent view that we found in onInterceptTouchEvent(). The last parameter specialViewClickPadding is in case that we want to increase the clickable area (the boundaries) around the special views. The idea here is that almost all of the special view will be with smaller sizes and on the mobile display they will be hardly accessible for clicks.
As you can appreciate, our BaseRecyclerViewItemTouchListener isn’t complicated at all and it does a couple of simple things:
- It intercepts all recycler view touch events;
- It makes difference between single click events and long click events thanks to the GestureDetector implementation that we have;
- Once it detects single touch event, it tries to differentiate special views clicks from recycler view item clicks.
Based on the generic implementation that we have in BaseRecyclerViewItemTouchListener.kt, we are ready to create our CustomRecyclerViewItemTouchListener class. This implementation shall be ready to serve only the needs of our screen (MainActivity.kt). The best approach with the recycler view item click listener is to create custom listener for every single screen, where you need to have list with items, because in most of the cases every single screen shall have its own needs and requirements and it is not good to mix and reuse the listeners between the screens (Activities).
Now here is how our CustomRecyclerViewItemTouchListener.kt looks like:
CustomRecyclerViewItemTouchListener extends BaseRecyclerViewItemTouchListener, which is abstract class so we need to implement all abstract methods that we have in the parent. In general we have two abstract methods:
- getSpecialViewClickPadding(): Int — where you need to return some Int value, bigger then 0 if you want to have bigger clickable area around the special views, or if you don’t need bigger clickable area you can simply return 0;
- onSpecialViewClick(specialChildView: View, listPosition: Int) — here we need to implement some small logic about what is going to happen with our listener (which method needs to be called) if we detects that some special view was clicked.
In my opinion, the first method does not deserve any specific attention, but the second one definitely does.
In CustomRecyclerViewItemTouchListener constructor we have parameter about the click listener of all events and its type is MyCustomClickListener, which is Interface in our CustomRecyclerViewItemTouchListener class. If you take a closer look at it, this Interface extends from BaseRecyclerViewItemTouchListener.ClickListener Interface. In order to avoid any confusion in my explanation, I have created the following image:
It is apparent that CustomRecyclerViewItemTouchListener. MyCustomClickListener just extends the functionality of BaseRecyclerViewItemTouchListener.ClickListener and it just needs to provide additions for the special view clicks that our UI supports. So BaseRecyclerViewItemTouchListener.ClickListener supports the generic events about onClick() and onLongClick(), but any other special events need to be defined in our extended (CustomRecyclerViewItemTouchListener.kt) class.
At the end I would like to provide the full picture of our custom recyclerview item listener:
We finish
In general, what we may conclude, is that if a developer needs to have recyclerview with more click listeners than just simple item click listener, one can just extend BaseRecyclerViewItemTouchListener, pass the special views ids and define his custom Interface extending BaseRecyclerViewItemTouchListener.ClickListener.
The approach works really well with MVP and MVVM application architecture, where you can define your recyclerview item click listener in the View (Activity, Fragment or Custom View) and then just pass the coming click events to the Presenter where the domain logic should handle and react on them.
Hope that sharing my personal experience has been of good help. If there is something which I didn’t manage to explain clearly enough, I would appreciate any feedback from you.
Источник