Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android ListView setSelection() does not seem to work

I have a ListActivity that implements onListItemClick() and calls a doSomething() function of the class. The latter contains l.setSelection(position) where l is the ListView object.

Now there is a onClickListener() listening for a button click that perfoms some actions and that too calls doSomething().

In the first case, the selected item get positioned appropriately, but in the latter, nothing happens.

Any clues about this strange behaviour and how I might make it work?

like image 698
alkar Avatar asked Sep 18 '09 19:09

alkar


10 Answers

maybe you need to use function:

ListView.setItemChecked(int position, boolean checked);
like image 58
meizilp Avatar answered Oct 03 '22 17:10

meizilp


use requestFocusFromTouch() before calling setSelection() method

like image 39
AlexD Avatar answered Oct 01 '22 17:10

AlexD


I know this is an old question but I just had a similar problem that I solved in this way:

mListView.clearFocus();
mListView.post(new Runnable() {
    @Override
    public void run() {
        mListView.setSelection(index);
    }
});
like image 20
mr_hyde Avatar answered Oct 05 '22 17:10

mr_hyde


You might need to wrap setSelection() in a posted Runnable (reference).

like image 37
kostmo Avatar answered Oct 03 '22 17:10

kostmo


setSelection() does not necessarily have visual impact. The selection bar only appears if you use the D-pad/trackball to navigate the list. If you tap on the screen to click something, the selection bar appears briefly and vanishes.

Hence, setSelection() will only have a visual impact if the activity is not in touch mode (i.e., the last thing the user did was use the D-pad/trackball).

I am not 100% certain this explains your phenomenon given the description you provided, but I figured it is worth a shot...

like image 24
CommonsWare Avatar answered Oct 03 '22 17:10

CommonsWare


If you use an Adapter for your ListView add this code to your adapter:

public class MyAdapter extends
        ArrayAdapter<MyClass> {


    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            LayoutInflater inflator = (LayoutInflater) getContext()
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            rowView = inflator.inflate(R.layout.my_adapter, null);
        } else {
            rowView = (View) convertView;
        }

        //...

        // set selected item
        LinearLayout ActiveItem = (LinearLayout) rowView;
        if (position == selectedItem)
        {
            ActiveItem
                    .setBackgroundResource(R.drawable.background_dark_blue);

            // for focus on it
            int top = (ActiveItem == null) ? 0 : ActiveItem.getTop();
            ((ListView) parent).setSelectionFromTop(position, top);
        }
        else
        {
            ActiveItem
                    .setBackgroundResource(R.drawable.border02);
        }

    }

    private int selectedItem;

    public void setSelectedItem(int position) {
        selectedItem = position;
    }

}

In your Activity:

myAdapter.setSelectedItem(1);
like image 22
Bobs Avatar answered Oct 02 '22 17:10

Bobs


For me calling

listView.notifyDataSetChanged();
listView.requestFocusFromTouch();

and then

 listView.setSelection(position);

solved the issue.

if you do that in a runnable it works without calling requestFocusFromTouch(), but the old position of the ListView is showen for a sekound.

like image 39
MaInStReAm Avatar answered Oct 02 '22 17:10

MaInStReAm


I have an very large Request with Webcontent. When I used the code in onCreateView the Listview wasnt even finished loading. I put it in onPostExecute of my AsyncTask.

            //Get last position in listview
        if (listView != null && scrollPosition != 0) {
            listView.clearFocus();
            listView.requestFocusFromTouch();
            listView.post(new Runnable() {
                @Override
                public void run() {
                    listView.setItemChecked(scrollPosition, true);
                    listView.setSelection(scrollPosition);
                }
            });
        }

Dont forget to set the item checked in on Click ;)

like image 28
Nick Avatar answered Oct 04 '22 17:10

Nick


Maybe you should use the smoothScrollToPosition(int position) method of ListView

like image 37
TaoZang Avatar answered Oct 02 '22 17:10

TaoZang


You can try 2 ways like these:
Solution A:

    mListView.post(new Runnable() {
        @Override
        public void run() {
            if (null != mListView) {
                mListView.clearFocus();
                mListView.requestFocusFromTouch();
                mListView.setSelection(0);
            }
        }
    });

In some complicated situation, this solution will bring some new problems in Android 8.x.
Besides it may cause unexpected onFocusChange().

Solution B: Define a custom view extends ListView. Override method handleDataChanged().Then setSelection(0). In CustomListView:

@Override
protected void handleDataChanged() {
    super.handleDataChanged();
    if (null != mHandleDataChangedListener){
        mHandleDataChangedListener.onChanged();
    }
}
HandleDataChangedListener mHandleDataChangedListener;

public void setHandleDataChangedListener(HandleDataChangedListener handleDataChangedListener) {
    this.mHandleDataChangedListener = handleDataChangedListener;
}

public interface HandleDataChangedListener{
    void onChanged();
}

In activity:

    mListView.setHandleDataChangedListener(new CustomListView.HandleDataChangedListener() {
        @Override
        public void onChanged() {
            mListView.setHandleDataChangedListener(null);
            mListView.setSelection(0);
        }
    });
    mAdapter.notifyDataSetChanged();

Ok, That's it.

like image 25
Courysky Avatar answered Oct 02 '22 17:10

Courysky