0
votes

I've a problem with my simple application. It uses a listview that has to: - open a new Activity when pressed and it's on view mode - highlight the selected item when it's on edit mode

I'm doing the following:

        ListView lv = (ListView)findViewById(R.id.categoryListView);

        lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position,
                                    long id) {

                String entry = (String) parent.getItemAtPosition(position);

                if (_editMode)
                    view.setBackgroundColor(Color.parseColor("#5B5B5B"));
                else 
                {
                    Intent intent = new Intent(MainActivity.this, CategoryActivity.class);
                    intent.putExtra("CATEGORY", entry);
                    startActivity(intent);
                }
            }
        });

Then I want that when I turn to view mode, all items must be deselected, and I do this:

for (int i = 0; i < lv.getAdapter().getCount(); i++)
{
    lv.getChildAt(i).setBackgroundColor(Color.parseColor("#FFFFFF"));
}

But this is working fine only if all the items in listview are visible. I've tried implementing this on the adapter without success...

Any suggestion?

Thanks!

EDIT

Ok after Jawad answer I just figured out how does "getView" method work. So this is the solution I've used:

I declared an arraylist containing selected items:

ArrayList<String> itemSelected = new ArrayList<String>();

This is the ListView onItemClick listener (where you can select and deselect items):

lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position,
                                long id) {


                String entry = (String) parent.getItemAtPosition(position);

                if (itemSelected.contains(entry))
                {
                    itemSelected.remove(entry);
                }
                else
                {
                    itemSelected.add(entry);
                }

                ((ArrayAdapter<String>)lv.getAdapter()).notifyDataSetChanged();
        }
    });

This is the ovverride of getView method:

itmList.setAdapter(new ArrayAdapter<String>(this,R.layout.list_black_text,R.id.list_content, itmStrList){
        @Override
        public View getView(int position, View convertView, ViewGroup parent)
        {
            if (convertView != null)
            {
                if (itemSelected.contains(itmList.getAdapter().getItem(position))) {
                    convertView.setBackgroundColor(Color.RED);
                } else {
                    convertView.setBackgroundColor(Color.parseColor("#5B5B5B"));
                }
            }

            return super.getView(position, convertView, parent);
        }
    });

And this is how to deselect all items:

        itemSelected.clear();

        ((ArrayAdapter<String>)lv.getAdapter()).notifyDataSetChanged();

Thank you man :)

1
instead of changing background color of listview item here change in adapter class getView(...) method.Rustam

1 Answers

2
votes

I think your problem is your are not paying attention to view recycling. When you are changing the color of a view's background, the view can be recycled and you will have something not desired. Check this link for details.

You should have a, lets say boolean variable, in your underlyning data called something like isSelected. And add this code in your getView() method.

    if(item.isSelected()){ 
            setBackgroundColor(Color.parseColor("#5B5B5B"));
    }
    else{
           setBackgroundColor(Color.parseColor("#FFFFFF"));
    }

Then in your onItemClick add replace view.setback... by

    lv.getAdapter().getItem(position).setSelected(true);
    lv.getAdapter().notifyDataSetChanged();

You may need a cast.

Finally change this

for (int i = 0; i < lv.getAdapter().getCount(); i++)
{
    lv.getChildAt(i).setBackgroundColor(Color.parseColor("#FFFFFF"));
}

to this:

for (int i = 0; i < lv.getAdapter().getCount(); i++)
{
    lv.getAdapter().getItem(i).setSelected(false);
}

lv.getAdapter().notifyDataSetChanged();

The reason why your portion of code works only if all the items are visible is view recycling. Moreover lv.getChildAt() gives you only the views that are visible. Your code may then crash because adapter.getcount maybe bigger then the number of listview childs.

Hope it helps.