This is a request for a best practice for handling the views in the onItemClick events in a ListView.
Each view in my ListView contains an ImageView, some TextViews, and a CheckBox wrapped in a RelativeLayout. On the item view being selected anywhere, I'd like to have the checkbox ticked/unticked as required. I would also like to have the option to change the view style i.e. so the item is highlighted by colouring the stroke.
My current issue is similar to everyone else who does this. Due to ListView recycling, if I grab the View passed into onItemClick and set the backgroundresource or checkbox checked value, it also changes them for Views that aren't currently rendered. I'd like to know the best way to achieve this goal.
I know there is a pattern to handle the CheckBox events in the ArrayAdapter directly by implementing an onClickListener, but I believe this will only respond to direct selection of the CheckBox; it will ignore any clicks on the rest of the view. Plus, if the CheckBox onClick event is fired, it will consume the click event so onItemClick won't fire, which I need to set my data.
Also, using CheckedTextView will not work since it is inside the RelativeLayout, which won't pass the checked event to the ListView. There was a post where it was recommended to create your own CheckedViewLayout that implements Checkable to handle the View checked events. If I go ahead with this, will I be able to reference my new layout class in xml, or would I then have to design each of my views again but in Java code?
If anyone else has a better solution, then please let me know.
Hey I think this link may be useful to you,there is a details for you
Android ListView Checkbox Example - OnItemClickListener() and OnClickListener()
In the end, I created my own CheckableRelativeLayout that implemented Checkable and used it as the main container for each ListView item. I used a Boolean value within CheckableRelativeLayout to track whether the view was clicked or not.
If required, I can post the final class.
Related
I have a listview with a custom adapter (extends BaseAdapter).
It recieves a list of objects I have to populate a ListView.
One of my object's atribute is a boolean called "checked".
on my method getView, this atribute is responsible for checking or not checking a CheckBox on my View.
Everything is working just fine and when my Activity loads, the ListView itens apear as they are on my list of objects (which was received from my database), some checked and some not checked.
But when I check one of my ListView's checkbox, I need to update my object and therefore it's value on my database. The problem is:
"How do I know which item (object) I have to update just by checking my CheckBox?"
"Don't they have the same name?"
I have a listView.setOnItemClickListener(...) where I can get my object by it's position, but it works when I click on the "row" of my list view itself, not on my checkbox... I thought about using it to check/uncheck my CheckBox... But how would I do that? Can I use the position to get a specific CheckBox from my listView?
In the end, I also thought that the best method would use the "listView.setOnItemClickListener(...)" to check my CheckBox, once it would be easier for my user to check one Item by it's row than by a tiny CheckBox, so can someone help me with the best way to solve my problem?
I'm sorry I didn't post my code, but right now I can't access it.
Take a look at this tutorial
You need to add an method in the onClick of the checkbox that will be implemented by the activity. One way to do that is to add an abstract method to the adpater and make the activity implement it. lets call onCheckBoxClicked(int position)
As I know, there are two methods to handle click on different list items:
Use setTag() to set types for items of list in Adapter, then setOnItemClickListener() for the list and getTag() of the view to differentiate the type, like this:
listview.setOnItemClickListener(new OnItemClcikListener(){});
Inside the adapter, setOnClickListener() individually for each item during getView(), like this:
item.setOnClickListener(new OnClickListener() {});
What is the difference and which one is preferred?
OnItemClickListener is very easy to manage compare to OnClickListener.
If you still would love to manage OnClickListener I will tell why OnItemClickListener is much better than OnClickListener.
Once you start scrolling ListView items will start getting reused and you ended up creating lot of OnClickListener. Don't worry, this is not a memory leak as GC will come into picture and collect those but you should not feel safe also because GC pauses your activity even if it is fraction of second that's considerable.
So would I go with OnItemClickListener unless you planned something different for individual list item.
If you need to create specific portions of each item to be clickable or want more than one action to be performed for a given item, it would be best if possible to collect those actions into a single OnClickListener that is created once and then attached to each item in getView(). You can differentiate which item was clicked by attaching metadata about the click action and maybe list position to the views themselves with setTag().
I'm not sure i really understood what do you mean but i will try to give you a reply.
Use setTag() to set types for items of list in Adapter, then setOnItemClickListener() for the list and getTag() of the view to differentiate the type, like this:
listview.setOnItemClickListener(new OnItemClcikListener(){});
You can use setTag() for set an Object like a tag, it means you can use it to put some informations into your cell view (ex: text, id and so on).
To "differentiate the type" of your view i would suggest you to use `getViewTypeCount().
inside the adapter, setOnClickListener() individually for each item during getView(), like this:
item.setOnClickListener(new OnClickListener() {});
This actually depends more on what you want to do with your list, if the behaviour of the click is strictly related to the informations which belong to your adapter or for example if you have a button inside your cell view, then set a listener for the cell view inside the adapter could be a good solution.
But except for the last case i would say the first is the best solution, since you can put everything you want into your tag, and it gives you the chance to manage your list's click from your main Activity or Fragment.
In my layout I have a button and a listview. How can I change the imageview of item I selected when the button is clicked. So lets say, I select 5 items, and after I click the button, images for those 5 items will be changed.
So I am confused what function I should use. Right now i used button.setOnClickListener but it seems wrong because only the very first item's imageview will be changed when button clicked. Should I use listview.setItemOnClickListener? Or is there any other way I can do this?
Thanks a lot!
Add a boolean to the data object in your adapter. Say you've got ArrayAdapter<MyDataObject>. Add some kind of "selected" field in the MyDataObject, and toggle it when you "select" the row.
Override getView in the adapter (you'll need a custom Adapter, btw. I'd just extend ArrayAdapter). When you render the row, if the "selected" field is true, show the "other" image.
When you click the button, call 'notifyDataSetChanged' on the adapter. The will cause the visible rows to refresh themselves (and call getView for each).
I think that'll work.
Since you only want images to change when you click the button, you'll need to have some kind of global boolean, so the getView won't show the image until the button has been clicked.
The complication here is, you have to deal with rows that may have been scrolled out of view, which don't have active views, but logically exist. It would be really hard to explain the concept here. I'd suggest some tutorials on ListView if you're not familiar with the recycling of row views.
You can used custom baseadapter for listview and setonclicklistener in the getView() method.... see tutorial here this is hope for help
You can use button click listener as well as on itemClickListener too but to make a image view in selected state in a list, you have to call setSelected method of imageview parent layout.
Please put a comment if you don't get me.
Thanks
This question is often asked here .Lot of people got the solution and working also.
I am also facing the same problem, My gridview onitemclick listner not working.
In my case
I have a viewpager.
Inside that I have fragments. On those fragments I have Gridview. Setting onItemclick listner to grid view not working, tried all case which I found on internet.
This viewpager is itself added in a sepratefragment. See the Picture For better Understanding.
The code is almost simple so not adding here for reference. Where I could be wrong. if not how to hack this
Working case: I am getting pressed events when i am adding onclicklistner to buttons in adapter. But not able to update the button text, when calling notifydatasetchanged.
Sounds like you have buttons inside your gridView adapter. Having buttons, checkboxes etc.. inside the adapter itemView will cause the actual row not to respond to onItemClick events. There are some solutions you would find in fixing this, but what i would suggest is to add a onClickListener to the row (contentView) inside the getView() method of the adapter and handle what you need there. You can pass the position of the clicked view either by a constructor (if you implement the onClickListener into a class which you use for the setOnClickListener or set the position to final in getView and use an anonymous class for the setOnClickListener method call.
If you need to do something based on this click back into the fragment read a bit on how to create a callback with the help of an interface.
I have a ListView with custom items - 3 ImageViews and a TextView. I have a call to setItemsCanFocus(true), so I can make the ImageViews clickable. I'm currently using SimpleAdapter to populate the View.
I'd like to trigger the AdapterView's onItemClick event when one of those subviews is clicked. The onItemClickListener receives a view as the second argument and that can be used to identify which subview was clicked. Frankly, I was expecting this to be the default behaviour but it isn't, unfortunately.
Is there any way to implement this behaviour without bluntly breaking encapsulation (i.e. creating an Adapter that holds a reference to its View)?
What is the accepted way of dealing with events from views in list items? How do you keep the Adapter from knowing too much about the ListView?
Unfortunately you have to choose between using onItemClick() or onClick() on individual children. One way to do it however is to make the top-level view of each item clickable.
Setting android:addStatesFromChildren="true" on the listview in your xml will send clicks on the child elements to the onItemClick method in the onItemClickListener connected to your listview.