I have a problem with ListView which recycles views that are visible on the screen.
I can have up to 4 items in my ListView, they are all visible on screen.
After I update a property of an object in the ArrayList that the ListAdapter uses i call the notifyDataSetChanged() method of the list adapter.
This causes the ListView to recycle the views and to redraw it self.
The problem is that it's doing the recycling in a reverse order. so if i have a button on the first Listview item it will be in the second list view item after the notifyDataSetChanged().
I have getView that changes the convertView properties except for the button onTouchListener.
This is very problematic if i have a button that works with touch event (Like PTT button). its visible for sometime and then it becomes invisible :-(.
1. why does the ListView recycle items that are visible on the screen ? is this normal behaviour? why does it do in reverse order ?
2. what can I do to solve my issue ?
You should provide code for getview() method. And adding button to an item could cause problems when you are not using checks on adding button.
Rather than adding button you should include button in all items and just make visible invisible the button at specific position where you want.
Also make check of "null" for creating convertview in getview() method. This way it would not recycle/create views/item if they are not null.
Related
I have a listview with a custom adapter. Everything populates correctly, however, I can only click on a listview item if i scroll the listview up and down. I've tried a bunch of SO answers, but nothing so far has worked, any help would be appreciated.
How do you set the click listener? Do you use listView.setOnItemClickListener(...) or use some view.setOnClickListener() inside the adapter? It seems you use the second approach and set the listener only after the views are reused (using convertView), not immediately after they're inflated. If that's the case check and update the conditions inside the getView() method of the adapter.
My app have an button(B1) custom ListView that item view include : checkbox,textview
Goal is I press button B1 then all checkbox in ListView will be setVisible and I had done it BUT THIS IS WORK FOR WHAT IS SHOWING ON SCREEN. When I scroll Listview in case multi-rows that the others not be visibled
Let's see my explanation:
- Example that there is 10 items in list data -> Listview on current screen just show 5 items ( 10 items is still visible when scroll)
- When press button B1 that just CHECKBOX of 5 items is visible, the others is not working
I mean I want to change layout of view item right on Activity
Because you are only updating the views of layout. You need to also update your data set (array of your adapter of listview) but I know you don't have a boolean variable in your data set to decide whether checkboxs are visible or not. First you need to add variables. After button clicked, don't update views of layout. Only change the datas (boolean variables) and call notifyDataSetChanged() method of your custom adapter. notifyDataSetChanged() method will recall your getView() method of your adapter for all views visible in your screen. Values will be updated correctly if you check visibility of views in your getView() method. Other items after scrolling will be correct because your getView() method is correct.
If you don't understand the answer add your OnClickListener of button and your custom adapter class. I will update them.
Edit: You have focused on the wrong problem. Your solution isn't related to updating the layout. You have problem about logic of how listView should works.
I have a situation involving animation of listview's item appearances.
I have a few views in a ScollView , the last of which is the listview. I have attached an appearence animation of the row (a fade in animation).
The problem I have is that when the screen is loaded , the getView() of listview already executes for the initial items , even though the listview is not currently in view.
Hence when a user scroll downs , he sees the list plainly.
I am unsure how to go about this situation . Is there any callback that can be invoked when a row from a listview becomes visible on screen ? .
Yes there is a callback (OnScrollChangeListener), first visible index and last visible index etc. You can achieve what you are trying to using combination of these.
But you need to try that yourself first. No one can simply write a code for you.
You can learn about listview here
I have a listview with 1 checkbox and 2 buttons, I set checkbox VISIBLE and both buttons GONE. In main class, I have 1 method that to turn on/off show 2 button VISIBLE/GONE again, work perfect but when I am scrolling the listview some rows of listview lost 2 button again.
This is my source code here
You should use an array or list to save button/checkbox state, and also handle VISIBLE/GONE in the adapter's getView() method according to saved button/checkbox state. Because when you scroll, the cell content might be reconstructed by getView().
What is the correct way to modify all child elements (not only the visible ones) of a listview.
I have an image which is set, by default, to visibilty gone. I wish to make it visible after the user clicks a button (for all items).
Thanks!
What is the correct way to modify all child elements (not only the visible ones) of a listview.
One thing to understand about a ListView is that not all of the list items are generated (inflated/populated) at any given time.
Suppose, for example, your list Adapter has 1000 items in it but the ListView can only display 10 at once. It would be a very bad waste of resources (e.g., memory) to create all 1000 list items.
Instead, only the 10 visible items are created and each time you scroll one off the top or bottom of the screen, the one which has disappeared is re-cycled by being passed as convertView into the Adapter's getView method.
getView (int position, View convertView, ViewGroup parent)
To do what you are asking you should extend whatever Adapter type you wish to use and override the getView method. In that method check if convertView is null or not. If it is, inflate your own instance of your list item layout. If it is not null then re-use the UI elements (TextView, ImageView etc).
To have all ImageView elements visible, use a global Boolean such as showImageView which will be toggled by the button press. Then use that in getView to decide whether or not to set the visibility of the ImageView.
See Adapter.getView(...)
Probably you should set the image visibility in your ListAdapter's getView() depending on some field value. Upon button clicking you change this field value and then you invoke ListAdapter.notifyDataSetChanged so the List View updates - getView then gets called and image changes because your field value has changed.
Inside the getView() of your adapter, you grab the ImageView and set its visibility to gone:
ImageView iv = (ImageView)convertView.findViewById(R.id.image_view);
iv.setVisibility(buttonClicked ? View.GONE : View.VISIBLE);
Then when users click on the button, set buttonClicked = true, and call notifyDataSetChanged() to refresh the ListView.