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)
Related
I have a list view with a list view adapter in my kotlin project. It works perfectly fine for the first thirteen entries, once I go past that the next two entries don't show up however for every entry after those next two the entry I entered two entries before shows up and I can scroll to it (So if I put in a sixteenth entry then the fourteenth will show up). When deleting so that the whole page is no longer full the final two show up. When debugging I saw that they should be visible as the list view adapter shows the code to display them running so I think the problem is that when scrolling the listview I just cant scroll till the bottom 2. Due to this I suspect that the navigation bar is maybe covering the bottom two entries or that the list view for some reason is longer than or as long as the parent so the bottom of it is past the end of the page. However I am still not sure how to fix this problem even though I think I know what it is.
The xml code for the list is below:
<ListView
android:id="#+id/listview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/header" />
Can you try to change your constraint for ListView like this
<ListView
android:id="#+id/listview"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="#+id/header" />
here i have consider that there is not other view below listview to show
that's why i have set bottom constraint to parent
I have the following xml (some attributes were omitted for simplicity):
<FrameLayout>
<RecyclerView
android:id="#+id/list"
android:focusable="true"
android:contentDescription="Some content"/>
</FrameLayout>
When I activate TalkBack (TTS) to test accessibility in my app, I want to be able to click in the RecyclerView (in any item on it) so the whole RecyclerView gets focused and its content description gets read.
I've tryed:
removed any android:focusable="true" from the items in the list, alsto there is no TextView in them, so TTS cannot read them.
added android:focusable="true" to the RecyclerView. Even by making the view larger than its children and being able to click directly on it, it was not receiving any focus at all.
was able to "focus" on the RecyclerView by wrapping it with a FrameLayout and adding android:focusable="true" to it, so the FrameLayout was being focused giving the impression the whole list was focused (but this is more of a workaround).
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.
I have this xml file. The list contains 2 items. When I test the application on the SDK emulator or a tablet, it is displayed as intented. However, when I download the application on a Samsung GT-S5570 with Android v2.2.1, the user can drag the list from the top and move it towards the bottom of the screen. Is there any way to prevent this from happening?
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<ListView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:paddingTop="20dip"
android:id="#android:id/list"
android:cacheColorHint="#android:color/transparent"
android:textAppearance="?android:attr/textAppearance"/>
</RelativeLayout>
If you just want to display limited number of items, then put that items within the ScrollView instead of using ListView.
ListView is intended to display unlimited number of items with scrollview to scroll other items.
This answer is the more informative and helpful: how can i automatically size listview so it doesn't scroll
I am developing an application that needs to pair with other devices through Bluetooth. I was having trouble in order to show the list of paired devices in correct manner. I had also viewed the example in the android api (Bluetooth Chat), but i was having the same problem.
The list of paired devices are to big and then hides a search button that are at the bottom of the list.
My xml code is very the same of the example:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView android:id="#+id/listpaired_devices"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/title_paired_devices"
android:visibility="gone"
android:background="#666"
android:textColor="#fff"
android:paddingLeft="5dp"
/>
<ListView android:id="#+id/paired_devices"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:stackFromBottom="true"
android:layout_weight="1"
/>
<TextView android:id="#+id/list_new_devices"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/title_other_devices"
android:visibility="gone"
/>
<ListView android:id="#+id/new_devices"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:stackFromBottom="true"
android:layout_weight="2"
/>
<Button android:id="#+id/btscan"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/btscan"
/>
</LinearLayout>
But and i can't show the search button at the bottom.
Here my screen:
My Screen
You could see a bit of the button at the bottom of the dialog window.
It's possible to limit the number of rows shown at the listview ? Can anyone tell me how i can fix this problem
Firstly some points about your code:
layout_weight is only meaningful if an object has no size in a certain dimension, that is you set layout_height or layout_width to 0, so this has no effect on your code.
Setting the height of a ListView to wrap_content is pretty meaningless, and even if it works it's bad practice. Use either 'fill_parent' or a definite height.
The button is hidden because, as per the point above, the ListViews you have created have no predefined size so take up as much space as they can, pushing the button off the screen.
So let's think about what you really have there - it's just a single list with a button at the bottom (yes you may have headers or multiple sources of data in there but we'll get onto that).
The following layout will give you a ListView at the top and a Button at the bottom. The ListView will take up any space not being used by the Button. Notice how the Button is defined before the ListView in the layout - this causes Android to calculate how much height the button takes up before considering the ListView. It then gives the ListView the rest of the height available.
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<Button android:id="#+id/btscan"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:text="#string/btscan"
/>
<ListView android:id="#+id/all_devices"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_above="#id/btscan"
android:stackFromBottom="true"
/>
</RelativeLayout>
So that's the layout. Now lets consider the actual content of your list: you have a header, followed by a list of paired devices, followed by another header and then a list of new devices.
You can create this using a single Adapter - Commonsware provides a very good implementation called MergeAdapter but you could code your own. MergeAdapter doesn't directly let you a view (e.g. for the headers) but thankfully Commonsware also provides the SackOfViewsAdapter which allows you to add views to it, and then you can add the SackOfViewsAdapter to the MergeAdapter.
Here is some pseudo-code which should accomplish what is outlined above.
// This is the adapter we will use for our list with ListView.setAdapter
MergeAdapter listAdapter = new MergeAdapter();
// The first header - you'll need to inflate the actual View (myHeaderView1) from some resource
// using LayoutInflater
List<View> firstHeaderViews = new List<View();
firstHeaderViews.add(myHeaderView1);
SackOfViewsAdapter firstHeaderAdapter = new SackOfViewsAdapter(firstHeaderViews)
// Second header
List<View> secondHeaderViews = new List<View();
secondHeaderViews.add(myHeaderView2);
SackOfViewsAdapter secondHeaderAdapter = new SackOfViewsAdapter(secondHeaderViews);
// Now to add everything to the MergeAdapter
// First goes the first header
listAdapter.addAdapter(firstHeaderAdapter);
// Now your first list
listAdapter.addAdapter(firstListAdapter);
// Now your second header
listAdapter.addAdapter(secondHeaderAdapter);
// Now your second list
listAdapter.addAdapter(secondListAdapter);
// Now set the adapter to the list
myList.setAdapter(listAdapter)
The layout produced should look something like this. Note I extended the list to show how it behaves with a list longer than the screen; the button still remains visible. The red box marks the bounds of the screen.
You can limit the number of rows shown at the list view, but not sure if that will really help you in what you want to achieve, because you're hiding information from the user that might be important to him. You can limit the number of rows by limiting the number of items you pass to the listview adapter, or you can set the visibility to 'gone' in the getView method when the list view reaches a certain position (you can check the 'position' parameter of getView()).
However, I would suggest you use only one list view (add a separator for the 'new/other devices' title into the view for a list item, but hide it by default, and then, as already suggested by suri, use headers and footers for the listview (to place the scan button).