I am developing app with chat and I want my ListView to scroll to bottom when new message been posted by user and when user was at the bottom of the list and there are new messages recieved. I am using this ListView:
<ListView
android:id="#+id/list"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:divider="#null"
android:dividerHeight="0dp"
android:stackFromBottom="true"
android:paddingBottom="9dp"
android:clipToPadding="false"/>
And this method to force scroll when needed:
private void scrollListViewToBottom() {
listView.setSelection(adapter.getCount() - 1);
}
But when chat contains element (big text or image) with height bigger than screen height it is scrolling to the top of it. I need my ListView to scroll exactly to the bottom, not to the last element.
I tried to use listView.scrollTo(0, listView.getBottom()) method but the result is very strange - it is scrolling sometimes to the last message + half-screen gap and sometimes to the place where I cannot see any messages.
Any ideas? Thanks.
You can use android:stackFromBottom="true" for populating list from bottom to top and add android:transcriptMode="alwaysScroll" for auto scrolling your listview.
You just have to call notifyDataSetChanged() and your list will be auto scrolled.
For handling scrolling to absolute bottom in case of large blocks, you can add list items with height of 1 px below every list item so that you will always be directed to end of list no matter what you item's height is.
Related
Hi I have a fragment with two RecyclerViews in it, one above the other.
The first is a list of items for the user to take an action on and the second is where the items will be populated once the action is taken. So when an item is removed from the top list it is added to the bottom list.
The issue I am having is when I remove an item from the top RecyclerView all the remaining items in the top RecyclerView move up to fill in the space left by the removed item, but this leaves a gap between the top and bottom RecyclerViews.
How can I move the bottom recyclerview up to fill in the gap created once an item is removed from the top RecyclerView
Here is my layout xml
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:layout_alignParentTop="true"
android:id="#+id/pending_tasks"
android:layout_marginTop="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<android.support.v7.widget.RecyclerView
android:layout_below="#id/pending_tasks"
android:id="#+id/completed_tasks"
android:layout_marginTop="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</RelativeLayout>
I have tried calling invalidate() on the bottom RecyclerView but that has not worked. Any help would be appreciated, thanks!
It's impossible to update layout size once it's been displayed on the screen. If you modify the content of your RecyclerView you can't just simply refresh the layout to shrink it.
I would suggest using single RecyclerView and storing lower bound of the first list in some variable. Then simply update it accordingly to modifications in your first list.
Another solution which may help you:
Change Relative layout width and height dynamically
I have a real app - which you can see on the left in the below screenshot.
And I have prepared a very simple test app at GitHub, which you can see at the right:
The real app has a ListView at the bottom, which is filled with Bluetooth-related log messages. This happens pretty often, few times a second and it is impossible for the user to scroll up and look at a particular event - because the list jumps to the bottom by itself, when new events are added to the list.
My question is: How to disable autoscrolling of the ListView - when user scrolls up and how to enable autoscrolling again, when user scrolls to the bottom?
And here is my very simple test app:
MainActivity.java (filling the ListView with help of AsyncTask)
activity_main.xml (layout with Button and ListView)
As you can see the auto-scrolling is currently enabled by XML attributes in layout:
<ListView
android:id="#+id/myListView"
android:stackFromBottom="true"
android:transcriptMode="alwaysScroll"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
Okay, I have found a perfect solution for my problem:
<ListView
android:id="#+id/myListView"
android:stackFromBottom="true"
android:transcriptMode="normal"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
When the transcriptMode is set to normal, then:
The list will automatically scroll to the bottom when a data set
change notification is received and only if the last item is already
visible on screen.
Here is my updated test project (I've also added double tap listener to clear the ListView there)
I have top margin of 30dp inside some of my list view items (including always the first one). However I don't want this top margin on my first list view item.
I have tried offsetting this by adding the following to the ListView
android:paddingTop="-30dp"
However, it doesn't seem to have any effect and the first list view item is still 30dp below the top edge of the list view.
Is there a way of getting minus top padding to work on an Android ListView?
XML
<ListView
android:choiceMode="singleChoice"
android:divider="#null"
android:dividerHeight="0dp"
android:paddingTop="-30dp"
android:layout_height="match_parent"
android:layout_width="match_parent"/>
Then some of the list view items content is as follows:
<LinearLayout
android:orientation="horizontal"
android:layout_height="wrap_content"
android:layout_width="match_parent"/
android:layout_marginTop="30dp">
<!--other content here-->
</LinearLayout>
The first list view item always uses the above template and im trying to offset that 30dp top margin.
Try setting android:layout_marginBottom="30dp" in your linear layout, so that you'll have the top of list without any margin but between list items still with margin. Does it look like what you want? Because minus padding is normally possible but in your case its overridden by the margin in list items.
I have a listView that expands upwards instead of downwards.
I have another listView on another page that works just fine and populates itself from the top -> bot.
Why does my listView start from the bottom instead of the top?
My XML
`
<ListView
android:id="#+id/list_view_showRegister"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_above="#+id/showRegister"
android:layout_alignParentLeft="true"
android:layout_marginTop="50dp"
android:clickable="false" >
</ListView>`
Your ListView is still actually populating from the top downwards. Just not from the top of the page.
You have set the layout_height="wrap_content" and the layout_above="#+id/showRegister". With the height being wrap_content, the view will only be as large as it's contents. Then, due to the fact you have used layout_above, it will be directly above another view.
The listview is not filling from the bottom, it is filling from the top (of the listview) - but the listview itself is only starting from halfway up the screen. Anything above the listview is not actually part of the listview, but empty space instead.
The solution is to either set the layout_height="match_parent", or remove the layout_above tag.
I know this is an old question but I hope this helps anyone else who may have found this issue via google.
Have a look a these links. Is it possible to make a ListView populate from the bottom?. populating from bottom.
Add new items to top of list view on Android?. Add new item at the top of list.
See for android:stackFromBottom attribute.
I have a ListView that with alphabetical headers for each letter. I also have an index function that brings the letter headers to the top of the screen.
My problem is when I reach the end of the list setSelection is unable to bring the last few headers to the top because it will not scroll past the end of the list.
My question is this: Is there a way to add a blank space to the end of the screen dependent on screen size? I would like to scroll until the last item in the list is at the top of the listView.
The easiest way to add space is to add padding in xml and set clipToPadding:"false".
For RecyclerView
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="20dp"
android:paddingBottom="20dp"
android:clipToPadding="false"/>
For ListView
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="20dp"
android:paddingBottom="20dp"
android:clipToPadding="false"/>
And same goes for the ScrollView
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="20dp"
android:paddingBottom="20dp"
android:clipToPadding="false"/>
This specifically adds the blank space to top and bottom but hide the space when you scroll the view.
Try the followings:
View footer = new View(getActivity());
footer.setLayoutParams( new AbsListView.LayoutParams( LayoutParams.FILL_PARENT, 100 ));
mListView.addFooterView(footer, null, false);
I'm assuming you are using an extension of BaseAdapter to populate your ListView?
There may be a built-in way to do what you are asking, but I don't know of one. If you end up creating it yourself, how about this approach:
Return list.size() + EXTRA in getCount()
Modify getItem() to return something sane if it asks for an item not in your list
Modify getView() to configure the given view as a simple horizontal padding with the same height as the rest of your views if the position index is more than your list size
You would need to fiddle around with the EXTRA constant to see what value is best.