Programmatically set position in ListView without scrolling
Asked Answered
W

2

1

This is for a tablet running Android 4.4.2. I have a ListView with hundreds of items in it and about 20 are visible at a time. The user doesn't want the animation of smooth scrolling. How do I programmatically set the displayed position in a Listview without using smoothScrollToPosition()?

I searched Stack Overflow and in Android ListView setSelection() does not seem to work they suggested this:

mListView.clearFocus();
mListView.post(new Runnable() {
    @Override
    public void run() {
        mListView.setSelection(index);
    }
});

. . . but it just sets the selection; it does not bring that portion of the ListView into view. setSelection() seems like a popular solution all over the web but I couldn't find anything in the documentation saying that setSelection() also sets the position, and it ONLY sets the selection and does not change the position on mine.

In Go to a item in Listview without using smoothScrollToPosition they suggested a solution by Romain Guy ...

[myListView.post(new Runnable() 
{
    @Override
    public void run() 
    {
        myListView.setSelection(pos);
        View v = myListView.getChildAt(pos);
        if (v != null) 
        {
            v.requestFocus();
        }
    }
});] 

The problem with this one is that my ListView is part of a ListActivity being managed via a custom adapter's getView(), so Views that are not visible are recycled, i.e., if I request a child view of a view that's not on the screen it returns null. Anyway, it's really the ListView I'm trying to control, so doing it indirectly via a child View seems awfully indirect.

How do I tell the ListView what part of it I want visible on the screen?

Windproof answered 31/3, 2015 at 17:35 Comment(2)
Did you check this one?Propagate
@Propagate It didn't look like he was trying to set the position; it looked like he was trying to set the selection. I don't see a solution in there to my question. The convertViews passed in to getView will only be for the visible views anyway, so it seems like trying to solve this in getView puts the cart before the horse.Windproof
W
8

There is a method in AbsListView, called smoothScrollToPositionFromTop() and it takes duration parameter. So if you set it to 0, you may do it without scrolling, animation.

smoothScrollToPositionFromTop.

Waves answered 31/3, 2015 at 18:0 Comment(4)
Excellent. Worked perfectly. And ListView is derived from AbsListView so I get it for free. Thanks!Windproof
Doesn't work for me. Specifically, setting a duration of 0 still results in an animated scroll. Even setting it to a small, nonzero value will result in an animated transition with a duration that significantly exceeds the value I specify. It seems like maybe the API is imposing some minimum duration/maximum scrolling rate, or something. Tested against a Google Pixel, API level 25.Pickle
@Pickle I didn't really use it recently. But It used to work at the time of my answer.Waves
Yes. Agreed. smoothScrollToPositionFromTop() seems to impose a minimum duration. And if your list is 3,000 long, then that duration is ignored and it can take a long time (4-8 secs) to scroll that far.Tropology
C
1

Solution is to getView of the row which is currently choosen to getTop.

Then to setSelectionFromTop from current position and getTop to highlight without scrolling:

lv.setSelectionFromTop(position,lv.getAdapter().getView(position,view,parent).getTop());

Colcannon answered 25/2, 2019 at 2:37 Comment(2)
Welcome to StackOverflow! Can you write a comment for this line of code - how and why it solves OP problem? Please prepend your code with ` `(4 space symbols)Harty
i get view of the row which i current choose to getTop, then i setSelectionFromTop from current position and getTop to highlight without scrollingCulicid

© 2022 - 2024 — McMap. All rights reserved.