Search code examples
androidlistviewandroid-listviewandroid-cursoradapter

Change row color of a ListView with Cursoradapter and bindView


I got some trouble, when I click on my Listview I would like to change the color of the selected row, but a several row change color instead of the one I want.

If I click on another row i want that the previous clicked row keep his color.

There's another little problem because I call every time setAdapter so the list scroll up every time i click

The code of the onclicklistener in the Fragment :

private AdapterView.OnItemClickListener ajouter_joueur_liste_listener = new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView parent, View v, int position, long id ) {
        //I take all player in my database 
        Cursor cursor = joueurDab.getAll();
        CursorListJoueur cl = new CursorListJoueur(context, cursor, position, true);
        liste_joueurs.setAdapter(cl);
     }
}

The cursor Adapter

public class CursorListJoueur extends CursorAdapter {
        int poscolor;
        boolean selection;
        private CategorieDAO categorieDab;
        public CursorListJoueur(Context pContext, Cursor c, int poscolor, boolean selection) {
            super(pContext, c, 0);
            this.poscolor = poscolor;
            this.selection = selection;
        }        

        @Override
        public View newView(Context context, Cursor cursor, ViewGroup parent) {
            categorieDab = new CategorieDAO(context);
            return LayoutInflater.from(context).inflate(R.layout.row_player, parent, false);
        }

        @Override
        public void bindView(View view, Context context, Cursor cursor) {
            int pos = cursor.getPosition();
            if ( poscolor != -1 ){
                if ( cursor.getPosition() == poscolor && selection ) {
                    view.setBackgroundColor( Color.GRAY );
                }else if ( cursor.getPosition() == poscolor && !selection ){
                    view.setBackgroundColor( Color.WHITE );
                }
            }

In CursorListJoueur(context, cursor, int poscolor, boolean selection);

the argument poscolor correspond at the row I want to color and the boolean indicate if i want to set Grey color or White color, and you don't need to care about the if (poscolor != -1)

I see some other topic but I don't want to use the XML method for color Row (because i want to remove row color in another onclicklistener) and if it's possible i want to keep my bindview() and don't use getView()

Thanks


Solution

  • Instead of creating a new Adapter every time your list got clicked (which caused the list to scroll back to top) you could utilize a SparseBooleanArray to keep track on what items is currently in selection.

    In your adapter:

    public class YourAdapter extends CursorAdapter {
    
       // Initialize the array
       SparseBooleanArray selectionArray = new SparseBooleanArray();
    
       ...
    
       // Method to mark items in selection
       public void setSelected(int position, boolean isSelected) {
           selectionArray.put(position, isSelected);
       }
    
       ...
    
       @Override
       public void bindView(View view, Context context, Cursor cursor) {
           int position = cursor.getPosition();
           boolean isSelected = selectionArray.get(position);
           if (isSelected ) {
               view.setBackgroundColor( Color.GRAY );
           } else if (!isSelected){
               view.setBackgroundColor( Color.WHITE );
           }
       }
    }
    

    And then upon item click, you could just toggle the selection likewise:

    @Override
    public void onItemClick(AdapterView parent, View v, int position, long id ) {
        YourAdapter adapter = (YourAdapter) parent.getAdapter();
        adapter.setSelected(position, true);
        adapter.notifyDataSetChanged();
    }
    

    Hope this helped. :)