I have a ListActivity which gets its data from a database query. I also have a custom adapter which extends simple cursor adapter.
To show the customised content, I have overridden the newView and bindView methods.
Each element of the view has:
TextView containing a title
ImageView containing number of stars - the image shown is changed based on a value obtained from the database
A button - the button text changes on clicks (Favourite/Make Favourite), and triggers a database update event.
My problem is this - when I scroll the ListView, the changes I made seem to disappear .. for instance, the first item is marked favourite, and the list is scrolled ... when I come back to the first item, the text reverts back to its previous value, although internally the db has been updated.
I read that the notifyDatasetChanged() is not right for this case as the adapter should be notified of the database changes. I am trying to use the reQuery() method, but do not know where to place it.
Should I place the reQuery() in the onClick method of the button? If not, where should it be placed?
What so ever Adapter is you are using must have getView Method.. Whenever a list is scrolled this getView Method got called for all the listItem in the view. Make Sure in the getView Method. That the view is getting generated dynamically.
It should check for clicked or changed value.
to update the list without scrolling your have to call listView.getAdapter().notifyDataSetChanged()
Check the following link. here i mentioned a complete code to use listview properly. Using this we can achieve any listview behavior. We can embed animation also.
Change ListView background - strange behaviour
Hope this help :)
If you have extended BaseAdapter ,
after data is changed call , listView.setAdapter() and in getView() , update the view's data too.
Use SetListAdapter with ArrayAdapter to display the list. Use ConvertView to avoid inflating View.
if (convertView==null)
{
//inflate your list
}
Related
I'm new to Android and can't quite figure out the right approach for the problem I'm trying to solve. I have an ExpandableListView with several items. Each item has an EditText, except the last item has a button. The contents of the EditTexts are to be loaded from the database. When the button is clicked or when the activity is navigated away from, I want to save the contents of each EditText to my database.
I'm not sure what to call from the activity's class, what to call from my adapter, and how exactly to access each item appropriately. Code is welcome but not necessary, I'm just looking for guidance on the general approach. Thanks.
I'd recommend putting a method in your adapter called saveAllValues. It iterates through the list of objects in the adapter and saves them to the database. Call this when your button is clicked and in your activity's onStop() method (which is called when the activity is no longer visible).
You should have your activity fetch the values for the item IDs in an AsyncTask in its onCreate method. Then pass the list of id/value pairs to the adapter in its constructor. It should maintain this list so it can go back through it and save the IDs and values to the DB.
Hope my answers in these links help:
Values of counter changes after scrolling ExpendableListView shows how to maintain the list inside the adapter and how to get list from the activity.
Remove the divider view in the expandablelistview last item shows how to make the last child different from the others.
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)
I have a listview with 4 identical rows. Inside those rows, I have a RelativeLayout which contains a TextView (id : R.id.notif). In my Activity, I use my own ArrayAdapter.
I would like to be able to modify the text of the third row. I tried this but it isn't working.
((TextView)listview.getAdapter().getView(2, null, listview).findViewById(R.id.notif)).setText("50");
Thank you.
Do not use adapter.getView() for that! This method is used internally for the adapter to create the view that gets displayed in the list! The correct way to do this is to modify the underlying data and to refresh the list with adapter.notifyDataSetChanged(). Do not try to access views in the list directly, you don't know if they are visible at the moment or scrolled outside the view.
I have following code that works fine when my ListView is already rendered (eg. when fired by onClick events, etc.)
TextView tv = (TextView)list.getChildAt(position); //list is my ListView
if (tv!=null) {
tv.setPaintFlags(tv.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
}
However, sometimes I need to apply this STRIKE_THRU_TEXT_FLAG flag to some items of ListView when activity is being restored (after rotation, restart...). If I try to run this code in onCreate or onStart methods then list.getChild(position) returns null because no ListView item is visible yet (in fact screen is black at this time and actual drawing seems to be done in some later function).
Is there any easy way how to get around this? Maybe getChild function is not the best for this case...Or would you override rendering function of the ListView to make it work (seems like overkill to me)? Thanks
Don't modify the view itself like that; modify the actual data object that represents that list item (for example, if your ListView is backed by an ArrayAdapter, this would be the array item for that list position). You could set a flag or property to denote that the item should be displayed differently, and then add some conditional code to your adapter's getView() method to display the text in the proper style based on the properties of that list item's object.
You can then let the view render itself accordingly the next time it's shown, or trigger the redraw yourself by calling notifyDataSetChanged() on the list adapter.
I would like to create a ListView in Android where I have the ability to add a new blank row, and have the controls in the new row be editable. Then on some event (either the user clicks add again, selects another row, or some other trigger I haven't determined yet), I want to update the Adapter with whatever values the user entered into the editable row.
I currently have editable controls within each row and the ability to add a blank row via a menu item. I cannot figure out how to sync the user entered data with the Adapter.
I originally thought that Adapters are two way data binds, but that doesn't seem to be the case. From my research and experimenting, if I change an Adapter value and call notifyDataSetChanged(), then the UI gets updated. Is there a reverse operation?
I was able to accomplish the two-way data binding by adding a KeyListener and OnFocusChangeListener to each of the controls on my row's View. Both of these events will call into a method I created on my row's View to loop through all the controls on the view and update my adapter's data with the current values. I had to make sure to not call notifyDataSetChanged(). This method is necessary only for programmatically changing the data source object and having the UI reflect the changes.
Not the most efficient way ever, but it works decently well.
Another thing to note, adding and deleting rows I needed to set both control and view level squelching of updating of my adapter view. For deletions, what I did was add a long click event on my row's View to have a menu with a delete option. Then I started squelching updates on a View level, because I programmatically edit my data source object to remove the given row data and call notifyDataSetChanged() (necessary otherwise OS will throw an exception). Squelching here makes sure I don't hit my events and get into an infinite loop and that my data is properly synced. Then on the deleted row View I set all my controls to squelch their event's update adapter. This is because the deleted row View will still have focus, and I want to make sure I don't update my data source object with values not on the UI. This flag gets flipped once I get the row's View back from the ListView recycling process in getView() of my adapter.
Adding a new row I also need to squelch on just the row's View level. This is because I programmatically change my data source with a new empty row of data, and call notifyDataSetChanged. Reasons are exactly the same as the delete.
your problem is hat you, for example may hav 300 items on the list (that are repesented by EditItems) but only 12-20 EditItems in reality that are recycled.
i guess your only way to know that use has finished with his row is FocsedChangedListener on each of your views.
Once focus is off use:
in your adapter's getView use: if v is your View then do v.setTag(position)
in the OnFocusChangedListener once focus is off use: int pos = (Integer)v.getTag(); mAdapter.updatePosition(text,pos)
make sure your adapter has an updat mthod that will update the object in position pos with the String 'text'
To refine C Nick's solution a bit, you can use EditText.addTextChangedListener.