I have a list of items: List<SomeObject> items that is mapped to an adapter to show on a ListView. When I set a new field for a specific item in that list and call adapter.notifyDataSetChanged() then list doesn't update. For example, I want to show a date TextView in a specific row in the ListView by setting
item.get(position).showDate(true);
adapter.notifyDataSetChanged();
The view doesn't show until I scroll away from that row and back to it (I'm assuming because of recycling).
Doing list.setAdapter(adapter); works but the entire view flashes and there shouldn't be a reason to re-set the adapter.
How can I get the list to update without scrolling?
You could try to change the List that is referenced in the adapter. Add something like this to your adapter:
public void updateData(List<SomeObject> dataItems) {
this.mDataItems = dataItems;
notifyDataSetChanged();
}
And then:
items.get(position).showDate(true);
adapter.updateData(items);
you can use adapter.getitem(postion) to get SomeObject and refresh it.
SomeObject sobj = (SomeObject)adapter.getItem(position);
sobj .showDate(true);
adapter.notifyDataSetChanged();
Related
I have Mainactivity which contain listview with some item and I want to add another listview in that listview as footer.How can I add this
Its not recommended to add a ListView as a footer of another ListView. You might consider making a list of objects containing both list and pass the list to your Adapter.
So if you merge two lists in a common format, you need to be tricky for the layout selection for each item in your list. Let me show you an example of a common class.
public class CommonClass {
// Set null values initially.
private ClassA mFirstListClass = null;
private ClassB mSecondListClass = null;
}
Now take an ArrayList of this object to pass it to your Adapter. In your bindView check if the item is a ClassA object or ClassB object (as you can easily determine them by checking which object is null) and then set proper action.
I think for these kinds of problems RecyclerView is better. Its very simple to implement and you can find the implementation document here.
// Create a List from String Array elements
final List<String> tests = new ArrayList<String>(Arrays.asList(test));
// Create an ArrayAdapter from List
final ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>
(this, android.R.layout.simple_list_item_1, tests);
// DataBind ListView with items from ArrayAdapter
lv.setAdapter(arrayAdapter);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Add new Items to List
tests.add("abc");
tests.add("def");
/*
notifyDataSetChanged ()
Notifies the attached observers that the underlying
data has been changed and any View reflecting the
data set should refresh itself.
*/
arrayAdapter.notifyDataSetChanged();
}
});
for more http://android--code.blogspot.in/2015/08/android-listview-add-items.html
I am using listview in my app.I am adding items to list with this line:
conversationsAdapter.add(user);
and this initializes list
conversationsAdapter=new ArrayAdapter<JsonObject>(this,0) {
#Override
public View getView(int c_position,View c_convertView,ViewGroup c_parent) {
if (c_convertView == null) {
c_convertView=getLayoutInflater().inflate(R.layout.random_bars,null);
}
JsonObject user=getItem(c_position);
String name=user.get("name").getAsString();
String image_url="http://domain.com/photos/profile/thumb/"+user.get("photo").getAsString();
TextView nameView=(TextView)c_convertView.findViewById(R.id.tweet);
nameView.setText(name);
ImageView imageView=(ImageView)c_convertView.findViewById(R.id.image);
Ion.with(imageView)
.placeholder(R.drawable.twitter)
.load(image_url);
return c_convertView;
}
};
ListView conversationsListView = (ListView)findViewById(R.id.conversationList);
conversationsListView.setAdapter(conversationsAdapter);
conversationsListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
startChat(conversationsAdapter.getItem(position));
}
});
My list view is looking like this:
I want to update an item in the list.How can I do this ?
Example:We can write a method like: changeName when this method calls,method sets name "Tolgay Toklar" to "Tolgay Toklar Test" so I want to update custom listview item attributes.
I totally disagree with tyczj. You never want to externally modify an ArrayAdapter's list and yes it's possible to update just an individual item. Lets start with updating an individual item.
You can just invoke getItem() and directly modify the object and call notifyDataSetChanged(). Example:
JSONObject object = conversationAdapter.getItem(position);
object.put("name", data);
conversationAdapter.notifyDataSetChanged();
Why does this work? Because the adapter will feed you the same object reference used internally, allowing you to modify it and update the adapter. No problem. Of course, I'd recommend instead building your own custom adapter to perform this directly on the adapter's internal list. As an alternative, I highly recommend using the ArrayBaseAdapter instead. It already provides that ability for you while fixing some other major bugs with Android's ArrayAdapter.
So why is tyczj wrong about modifying the external list? Simple. There's no guarantee that your external list is the same as the adapters. Once you perform a filter on the ArrayAdapter, your external list and the adapters are no longer the same. You can get into a dangerous scenario where (for example) index 5 no longer represents position 5 in the adapter because you later added an item to the adapter. I suggest reading Problems with ArrayAdapter's Constructors for a little more insight.
Update: How External List Fails
Lets say you create a List of objects to pass into an ArrayAdapter. Eg:
List<Data> mList = new ArrayList<Data>();
//...Load list with data
ArrayAdapter<Data> adapter = new ArrayAdapter<Data>(context, resource, mList);
mListView.setAdapter(adapter);
So far so good. You have your external list, you have an adapter instantiated with it and assigned to listview. Now lets say at some later point, the adapter is filtered and cleared.
adapter.filter("test");
//...later cleared
adapter.filter("");
Now at this point mList is NOT the same as the adapter. So if the adapter is modified:
adapter.add(newDataObject);
You'll find that mList does not contain that new data object. Hence why external lists like this can be dangerous as the filter creates a NEW ArrayList instance. It won't continue to use your mList referenced one. You could even try adding items to mList at this point and it won't be reflected in the adapter.
If you change the data in your list you need to call notifyDatasetCanged on the adapter to notify the list that the underlying data has changed needs to be updated and.
Example
List<MyData> data = new ArrayList<MyData>();
private void changeUserName(String name){
//find the one you need to change from the list here
.
.
.
data.set(myUpdatedData);
notifyDatasetChanged()
}
I have a Listview and a custom adapter, I am trying to change swap two arraylist items inside the apdapter in onclick of button as listview item.
My code is
viewHolder.btnUp.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Integer pos = (Integer) v.getTag();
if (!pojos.get(pos).equals(pojos.get(0))) {
Collections.swap(pojos, pos, pos - 1);
notifyDataSetChanged();
}
}
});
But I can not see the changes in listview, though arraylist has modified, but UI changes has not reflected.
Thats because your adapter has already finished its work. The adapter will turn the data into views and pass those views to the list view. Notice that changing the order in the original collection wont change the views inside the list view. What you could do is remove the views and add them at the correct positions. Get access to the list view by doing viewHolder.getParent()
If pojos is a local final variable, make sure the one the adaptor uses still points to the same collection otherwise the anonymous class will swap 2 elements in an collection that's not being used.
I would recommend to pass the arrayList to the adapter again and setting adapter to the list view, all this before the notifyDataSetChanged(); method.
Hi friends i have a listview and the contents are fetched from a webservice call. In that webservice call, there are fields like
"OGType": "ORG" and "OGType": "GROUP"
If click a button, the listview must shows the item having "OGType": "ORG", and hide the item having "OGType": "GROUP". Hope you understand what i meant. Please anyone help me for that. Thanks in Advance.
Try to set new data (only with ORG) to adapter and then call
adapter.notifyDataSetChanged();
You can do it in your getView Method in your Adapter Class. That's the header
public View getView(int pos, View convertView, ViewGroup, parent)
There you can properly hide the element(s) you want, you know, using the method setVisibility()
For more help you can take a look here
You can create a custom adapter and pass data to it in the form of Array or ArrayList (ArrayList is better when dealing with Custom Adapters). Whenever you need to add or remove the data from ListView, just add or remove the item to or from you ArrayList and call notifyDataSetChanged() on your custom adapter and it will update the ListView automatically.
In your case, whenever you click a button, edit you ArrayList and call your custom adapter's method called notifyDataSetChanged() and that's it. You'll see every time you call this method ListView will refresh itself if you have made any changes to the data. Hope it helps.
NOTE - CUSTOM ADAPTER IS NOT COMPULSORY. ANY ADAPTER CAN BE USED e.g SimpleAdapter, ArrayAdapter etc.
You can use a visible list and filters lists. You should use "visible" for complete the BaseAdpter as always, then, you can change the pointer of visible to other list (all, filter...)
Don't worry by the memory, are pointers, you only have each element only once.
public class MyAdapter extends BaseAdapter {
private ArrayList<MyItem> visible;
private ArrayList<MyItem> all;
private ArrayList<MyItem> filter;
public MyAdapter(ArrayList<MyItem> items) {
all = items;
visible = all; //Set all as visible
filter = new ArrayList<Item>();
for (Item i : items)
if (i.getType().equals("ORG"))
filter.add(i);
}
//Complete adapter using "visible"
public void showOnlyOrg() {
visible = filter;
notifydatasetchanged();
}
}
The non hackish way will be to remove the items from your Collection which you use to generate the listview and then call notifyDataSetChanged();
I have a listview in which i am adding some data after fixed interval.but I don't want to set the adapter again as it will refresh the complete list.Is there any method to add item without refreshing the complete list.
Thanks in advance.
You probably want to use the following (in RecycleView not ListView):
notifyItemInserted(0);//NOT notifyDataChanged()
recyclerViewSource.scrollToPosition(0);
//Scroll up, to use this you'll need an instance of the adapter's RecycleView
You can call adapter.notifyDataSetChanged() to just update the list.
Adapter's getView() is called at different times and there is no particular pattern. So your views are updated whenever ListView wants it to be updated.
But as far as I see it, you are looking for adapter.notifyDataSetChanged. The workflow should be something like this.
Set adapter to ListView
Add data to adapter`
Call notifyDataSetChanged() on adapter.
It will at least prevent your list to bounce back to first item on the list.
Hope that helps.
you can use this .notifyDataSetChanged()
However notifyDataSetChanged() only works For an ArrayAdapter,if you use the add, insert, remove, and clear functions on the Adapter.
You can use
adapter.add(<new data item>); // to add data to your adapter
adapter.notifyDatasetChanged(); // to refresh
For eg.
ArrayAdapter<String> adapter;
public void onCreate() {
....
....
ArryList<String> data = new ArrayList<String>();
for(int i=0; i<10; i++) {
data.add("Item " + (i+1));
}
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, data);
setListAdapter(adapter);
}
Now whenever you have new data to be added to list you can do following
private void appendToList(ArrayList<String> newData) {
for(String data : newData)
adapter.add(data);
adapter.notifyDatasetChanged();
}