visionix visionix
visionix visionix

Reputation: 780

selected item of listview remain at same position after notifyDataSetChanged

I implemented a simple listview with an option to select each time only one item from it, this functionality is working properly. Also I have a button for sorting the records in Asc or Desc order, when I am selecting a record and after that I am sorting the records the selector of the old record remains in the same old position, even when the selected position is updated different position.

MainActivity:

    public class MainActivity extends Activity
{

    private ListView        _listView;
    private PersonAdapter   _adapter;
    private Button          _sortBtn;
    private List<Person>    _data;
    private int             _sort;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        _listView = (ListView) findViewById(R.id.list);
        _sortBtn = (Button) findViewById(R.id.sort_list_btn);

        _sort = 1;
        _data = new ArrayList<Person>();
        _data.add(new Person("abc", "defg", 1));
        _data.add(new Person("aaa", "defg", 12));
        _data.add(new Person("ccc", "defg", 13));
        _data.add(new Person("bb", "defg", 14));
        _data.add(new Person("aa", "defg", 144));
        _data.add(new Person("fff", "defg", 199));

        _adapter = new PersonAdapter(this, _data);
        _listView.setAdapter(_adapter);

        _sortBtn.setOnClickListener(new OnClickListener()
        {

            @Override
            public void onClick(View v)
            {
                Comparator<Person> sortById = Person.getComperatorByFirstName(_sort);
                Collections.sort(_data, sortById);

                _adapter.setData(_data);
                _sort = -_sort;
            }
        });

    }

    public static class Person
    {
        public String   _fName;
        public String   _lName;
        public int      _age;
        public boolean  _selected;

        public Person(String fName, String lName, int age)
        {
            _fName = fName;
            _lName = lName;
            _age = age;
        }

        public static Comparator<Person> getComperatorByFirstName(final int ascendingFlag)
        {
            return new Comparator<Person>()
            {
                @Override
                public int compare(Person patient1, Person patient2)
                {
                    return patient1._fName.compareTo(patient2._fName) * ascendingFlag;
                }
            };
        }

    }

}

listView adapter

public class PersonAdapter extends BaseAdapter
{

    private Context         _con;
    private List<Person>    _data;

    public PersonAdapter(Context context, List<Person> data)
    {
        _con = context;
        _data = data;
    }

    @Override
    public int getCount()
    {
        // TODO Auto-generated method stub
        return _data.size();
    }

    @Override
    public Person getItem(int position)
    {
        return _data.get(position);
    }

    @Override
    public long getItemId(int position)
    {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent)
    {
        Holder h = null;
        if (convertView == null)
        {
            h = new Holder();
            convertView = LayoutInflater.from(_con).inflate(R.layout.item_layout, parent, false);

            h._backgroundItem = (LinearLayout) convertView.findViewById(R.id.item_layout);
            h._fName = (TextView) convertView.findViewById(R.id.f_name);
            h._lName = (TextView) convertView.findViewById(R.id.l_name);
            h._age = (TextView) convertView.findViewById(R.id.age);
            convertView.setTag(h);
        }
        else
        {
            h = (Holder) convertView.getTag();
        }

        Person p = getItem(position);
        h._fName.setText(p._fName);
        h._lName.setText(p._lName);
        h._age.setText(String.valueOf(p._age));
        h._backgroundItem.setActivated(p._selected);



        return convertView;

    }


    public void setData(List<Person> data)
    {
        _data = data;
        notifyDataSetChanged();

    }

    private static class Holder
    {
        public LinearLayout _backgroundItem;
        public TextView     _fName;
        public TextView     _lName;
        public TextView     _age;
    }



}

item layout:

  <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/item_layout"
    android:layout_width="match_parent"
    android:layout_height="48dp"
    android:orientation="horizontal"
    android:background="@drawable/list_selector"
    android:weightSum="3" >

    <TextView
        android:id="@+id/f_name"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1" />

    <TextView
        android:id="@+id/l_name"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1" />

    <TextView
        android:id="@+id/age"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1" />

</LinearLayout>

I tried already to use clearChoices but after sorting I do not see the selector at all, also I tried to change the choise mode from single mode to none and then again single but without any success.

Upvotes: 0

Views: 842

Answers (2)

Isaac Urbina
Isaac Urbina

Reputation: 1313

It is because you are switching the contents of the items inside the list item, but the click is bound to the position withing the ListView, therefore it doesn't "update" to the new position of the item. I suggest you to programatically click on the new item when you finish the sorting. Get the ID of the clicked item

public int getItemPosition(long id)
{
    for (int position=0; position<mList.size(); position++)
        if (mList.get(position).getId() == id)
            return position;
    return 0;
}

then after the sorting do the click

mList.performItemClick(
    mList.getAdapter().getView(mActivePosition, null, null),
    mActivePosition,
    mList.getAdapter().getItemId(mActivePosition));

hope it helps!

Upvotes: 1

Matias Elorriaga
Matias Elorriaga

Reputation: 9150

I suggest to store the id of the selected item when it is selected, and after order the dataset, search for that id and re-select it.

Upvotes: 0

Related Questions