Add new items to top of list view on Android? - android

Android has the transcript mode to allow to automatically scroll a list view to the bottom when new data is added to the adapter.
Can this be somehow reversed so that new items are automatically added at the top of the list ("inverse transcript mode")
Method stackFromBottom seems about right, but does not do the auto-scrolling on input change.
Does anyone have some example code where a list is constantly adding stuff that gets always inserted at the top? Am I on the right track here?
Update
Thanks for the answers, that made me think more. Actually. I want to have new entries to appear at the top, but the screen still show the item the user is looking at. The user should actively scroll to the top to view the new items. So I guess that transcript mode is not what I want.

Hmm, well, if I was going to try this, I'd do something like the following:
List items = new ArrayList();
//some fictitious objectList where we're populating data
for(Object obj : objectList) {
items.add(0, obj);
listAdapter.notifyDataSetChanged();
}
listView.post(new Runnable() {
#Override
public void run() {
listView.smoothScrollToPosition(0);
}
}
I don't know for certain that this will work, but it seems logical. Basically, just make sure to add the item at the beginning of the list (position 0), refresh the list adapter, and scroll to position (0, 0).

instead of this:
items.add(edittext.getText().toString());
adapter.notifyDataSetChanged();
you should try that (works for me):
listview.post(new Runnable() {
#Override
public void run() {
items.add(0, edittext.getText().toString());
adapter.notifyDataSetChanged();
listview.smoothScrollToPosition(0);
}
});

Shouldn't it be enough to just add a smoothScrollToPosition(0) whenever stuff gets added to the ListView? Don't think there's an automatic scroll option.

I spent several hours attempting to accomplish the same thing. Essentially, this acts like a chat app where the user scrolls up to view older messages at the top of the list.
The problem is that, you want to dynamically add another 50 or 100
records to the top but the scrolling should be continuous from where
the prepended items were added.
The moment you do a notifyDataSetChanged, the ListView will automatically position itself at the first item in your data set and NOT at the position that preceded the position where the new items got inserted.
This makes it look like your list just jumped 50 or 100 records. I believe TranscriptMode set to normal is not the solution. The listview needs to function as a normal listview and you need to programmatically scroll to the bottom of the list to simulate the TranscriptMode as it functions under "normal".

Try to use
LinkedList items = new LinkedList<Object>();
//some fictitious objectList where we're populating data
for(Object obj : objectList) {
items.addFirst(obj);
}
listAdapter.notifyDataSetChanged();

This resolves the problem:
...
ListView lv;
ArrayAdapter<String> adapter;
ArrayList<String> aList;
...
lv = (ListView) findViewById(R.id.mylist);
aList = new ArrayList<String>();
adapter = new ArrayAdapter<String>(getApplicationContext(), android.R.layout.simple_spinner_item, aList);
lv.setAdapter(aAdapter);
...
adapter.insert ("Some Text 1", 0);
adapter.insert ("Some Text 2", 0);
adapter.insert ("Some Text 3", 0);
...

you should try that (list position and refresh adapter)
list.add(0,editTextSName.getText().toString());
adapter.notifyDataSetChanged();

Related

Click on last item in AdapterView in Espresso

I'm working on a note taking app. I add a note, and it get's added to the bottom of the list. As the last assertion in the espresso test, I want to make sure that the ListView displays a listItem that has just been added. This would mean grabbing the last item in the listView. I guess you might be able to do it in other ways? (e.g. get the size of adapted data, and go to THAT position? maybe?), but the last position of the list seems easy, but I haven't been able to do it. Any ideas?
I've tried this solution, but Espresso seems to hang. http://www.gilvegliach.it/?id=1
1. Find the number of elements in listView's adapter and save it in some variable. We assume the adapter has been fully loaded till now.:
final int[] numberOfAdapterItems = new int[1];
onView(withId(R.id.some_list_view)).check(matches(new TypeSafeMatcher<View>() {
#Override
public boolean matchesSafely(View view) {
ListView listView = (ListView) view;
//here we assume the adapter has been fully loaded already
numberOfAdapterItems[0] = listView.getAdapter().getCount();
return true;
}
#Override
public void describeTo(Description description) {
}
}));
2. Then, knowing the total number of elements in listView's adapter you can scroll to the last element:
onData(anything()).inAdapterView(withId(R.id.some_list_view)).getPosition(numberOfAdapterItems[0] - 1).perform(scrollTo())

Add new items on top of list view

Because android automatically moves new items to the bottom of list view I want that to be reversed. In any case my condition is met, I want to add new items on top of list view.
I have seen this post here but I don't know how to add that to my code, here it is:
if(condition){
listView = (ListView) findViewById(R.id.ListView1);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(
this, R.layout.list_b_text, R.id.list_content, ArrayofName);
listView.setAdapter(adapter);
}
Just simply add every item at position 0 of your ArrayList so when you call listView.notifyDataSetChanged(); it will show latest items on top.
for (Object obj : objectList) {
ArrayofName.add (0, obj); // this adds new items at top of ArrayList
}
objectList is basically an ArrayList or List of Object or String (whatever is your case). If you want to add items one by one, remove for loop. This loop actually iterates every item of objectList and adds it in your ArrayList at top position.

Remove items from listview on its ItemClickListener

I am using a collection of ArrayList to fill my Listview. My ListView contains two separate rows types.
Header and Footer.
I am trying to achieve the ExpandableListView Functionality on my Listview from which I am trying to remove some items on click of header till next header.
I am using this function to loop through items and removing items
private void removeItems(int value)
{ Log.e(Constant.LOG, items.size()+"");
for (int i = value;i < items.size(); i++) {
if(!items.get(i).isSection())
items.remove(i);
}
Log.e(Constant.LOG, items.size()+"");
adapter = new EntryAdapter(this, items, this);
mListView.setAdapter(adapter);
}
QUESTION IS : I am not able to remove all items from the list in one shot, some stays there !
I have tried looping through adapter.count(); but no luck
My List :
SECTION 1
ITEM 1
ITEM 2
Item N
Section 2
But when I click on Section 1 not all ITEMS get deleted in one shot WHY!
I am not able to use Expandable Listview at this stage because activity contains many more complex functionality on List. Please help me where I am going wrong!
Create a new ArrayList<Collection> , Then add your item in it and then use removeAll(collection).
TRY THIS:
private void removeItems(int value)
{ Log.e(Constant.LOG, items.size()+"");
ArrayList<Collection> deleteItems= new ArrayList<Collection>();
for (int i = value;i < items.size(); i++) {
if(!items.get(i).isSection())
deleteItems.add(items.get(i));
}
items.removeAll(deleteItems);
Log.e(Constant.LOG, items.size()+"");
adapter = new EntryAdapter(this, items, this);
mListView.setAdapter(adapter);
}
EDIT
Every time you are deleting an item, you are changing the index of the elements inside .
e.g : let suppose you are deleting list1 , then list[2] becomes list1 and hence your code will skip list1 next time because now your counter would be moved to 2.
Here are other ways by which you can achieve this also,
Removing item while iterating it
So what exactly I did now. Instead of looping through items again I did like this :
I created another list and parallely populate it with the main array.
items.add(user);
// after populating items did this
newItems.addAll(items); // same collection ArrayList
and finally I can play with the main array by using removeAll and addAll methods.
items.removeAll(newItems); // remove items
items.addAll(afterPosition,newItems); // add items after position

keep Scroll position with every refresh in list view

I set a timer in my app, I could get some information from a web service and resulted in a list view to display. Now my problem is that every time the timer runs, scroll back to the beginning ...
how can i keep Scroll position with every refresh in list view ?
part of my code:
runOnUiThread(new Runnable() {
public void run() {
/**
* Updating parsed JSON data into ListView
* */
ListAdapter adapter = new SimpleAdapter(DashboardActivity.this,
all_chat,
R.layout.list_item,
new String[] { TAG_FULLNAME,
TAG_DATE,
TAG_MESSAGE },
new int[] { R.id.fullname,
R.id.date,
R.id.message }
);
// updating listview
setListAdapter(adapter);
}
});
TNx.
Do not call setAdapter(). Do something like this:
ListAdapter adapter; // declare as class level variable
runOnUiThread(new Runnable() {
public void run() {
/**
* Updating parsed JSON data into ListView
*/
if (adapter == null) {
adapter = new SimpleAdapter(
DashboardActivity.this, all_chat, R.layout.list_item, new String[]{TAG_FULLNAME, TAG_DATE, TAG_MESSAGE},
new int[]{R.id.fullname, R.id.date, R.id.message});
setListAdapter(adapter);
} else {
//update only dataset
allChat = latestetParedJson;
((SimpleAdapter) adapter).notifyDataSetChanged();
}
// updating listview
}
});
You can add the following attribute to your ListView in xml.
android:stackFromBottom="true"
android:transcriptMode="alwaysScroll"
Add these attributes and your ListView will always be drawn at bottom like you want it to be in a chat.
or if you want to keep it at the same place it was before, replace alwaysScroll to normal
in the android:transcriptMode attribute.
Cheers!!!
I had the same issue, tried a lot of things to prevent the list from changing its scroll position, including:
android:stackFromBottom="true"
android:transcriptMode="alwaysScroll"
and not calling listView.setAdapter();
None of it worked until I found this answer:
Which looks like this:
// save index and top position
int index = mList.getFirstVisiblePosition();
View v = mList.getChildAt(0);
int top = (v == null) ? 0 : (v.getTop() - mList.getPaddingTop());
// ...
// restore index and position
mList.setSelectionFromTop(index, top);
Explanation:
ListView.getFirstVisiblePosition() returns the top visible list item. But this item may be partially scrolled out of view, and if you want to restore the exact scroll position of the list you need to get this offset. So ListView.getChildAt(0) returns the View for the top list item, and then View.getTop() - mList.getPaddingTop() returns its relative offset from the top of the ListView. Then, to restore the ListView's scroll position, we call ListView.setSelectionFromTop() with the index of the item we want and an offset to position its top edge from the top of the ListView.
There's a good article by Chris Banes. For the first part, just use ListView#setSelectionFromTop(int) to keep the ListView at the same visible position. To keep the ListView from flickering, the solution is to simply block the ListView from laying out it's children.

How to add more item in a list view without refreshing the previous item

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();
}

Categories

Resources