Change imageview in listview row dynamically

1.1k views Asked by At

I have a listview with custom row which contains textview an ImageView and a button.

This is my layout:

enter image description here

Now If I add some text and select the color beside add text and click "+" the text and the color selected should be added to the listview.

Still here everything works fine.

But now my problem is each time I select the color and click "+" the color is changing for all the list rows.

I want only to change for the newly added text.

can anyone say me where am I going wrong?

This is my adapter:

  public class MyCustomAdapter extends BaseAdapter implements ListAdapter { 
        private ArrayList<String> list = new ArrayList<String>(); 
        private Context context; 



        public MyCustomAdapter(ArrayList<String> list, Context context) { 
            this.list = list; 
            this.context = context; 
        } 

        @Override
        public int getCount() { 
            return list.size(); 
        } 

        @Override
        public Object getItem(int pos) { 
            return list.get(pos); 
        } 



        @Override
        public View getView(final int position, View convertView, ViewGroup parent) {
            View view = convertView;
            if (view == null) {
                LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
                view = inflater.inflate(R.layout.category_row, parent,false);
            } 

            //Handle buttons and add onClickListeners
           final ImageView coloredimage = (ImageView)view.findViewById(R.id.colorpicker);
           final ImageView btndelete = (ImageView)view.findViewById(R.id.btndelete);


            //Handle TextView and display string from your list
            TextView listItemText = (TextView)view.findViewById(R.id.txtCategory); 
            listItemText.setText(list.get(position)); 

            coloredimage.setBackgroundColor(selectedcolor);

            btndelete.setOnClickListener(new View.OnClickListener(){
                @Override
                public void onClick(View v) { 
                    //do something
                    list.remove(position); //or some other task
                    notifyDataSetChanged();
                }
            });

            return view; 
        }

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

This is my Activity:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.add_category);

    getActionBar().setDisplayHomeAsUpEnabled(true);
    getActionBar().setBackgroundDrawable(new ColorDrawable(Color.parseColor("#00897B")));
    getActionBar().setTitle(Html.fromHtml("<font color='#FFFFFF'>Register User</font>"));
    coloredimage = (ImageView) findViewById(R.id.colorpicker);
    colorPickerDialog = new ColorPickerDialog();
    colorPickerDialog.initialize(R.string.dialog_title, new int[] { Color.CYAN, Color.LTGRAY, Color.BLACK, Color.BLUE, Color.GREEN, Color.MAGENTA, Color.RED, Color.GRAY, Color.YELLOW }, Color.YELLOW, 3, 2);


    findViewById(R.id.colorpicker).setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            colorPickerDialog.show(getSupportFragmentManager(), "colorpicker");
        }
    });

      /** Reference to the button of the layout main.xml */



    /** Setting a custom layout for the list activity */

    lv = (ListView) findViewById(R.id.list);
    list = new ArrayList<String>();
    //instantiate custom adapter
    list.add("Inbox");
    list.add("Personal");
    adapter = new MyCustomAdapter(list, this);
    lv.setAdapter(adapter);
    adapter.notifyDataSetChanged();




    colorPickerDialog.setOnColorSelectedListener(new OnColorSelectedListener() {

        @Override
        public void onColorSelected(int color) {
            //Toast.makeText(AddTask.this, "selectedColor : " + color, Toast.LENGTH_SHORT).show();
        selectedcolor=color;
        coloredimage.setBackgroundColor(selectedcolor);

        }
    });



    btnadd = (ImageView) findViewById(R.id.btnaddcategory); 
    /** Defining a click event listener for the button "Add" */
    btnadd.setOnClickListener(new OnClickListener() {
        public void onClick(View v) {
            txtcategoryname = (EditText) findViewById(R.id.txtaddcategory);
            list.add(txtcategoryname.getText().toString());
            txtcategoryname.setText("");
            lv.setAdapter(adapter);
            adapter.notifyDataSetChanged();
        }
    });

}

This is what I'm getting now:

enter image description here

3

There are 3 answers

2
theMfromA On BEST ANSWER

The problem is that getView() is not only called if a new listitem is added, but always if the listitem is rendered again, for example if you call

adapter.notifyDataSetChanged();

So, you're setting the color of all listitems by calling this method in getView():

coloredimage.setBackgroundColor(selectedcolor);

You've got to remove this line in your code!

The question is now: HOW do you set the color of the listitems? To solve this, you should think about the following: WHERE do you store the info about which color belongs to a listitem? Your listitems are just Strings! You would need objects like this:

public class StringColorItem {
private String s;
private int c;

public StringColorItem(String s, int c) {
    this.s = s;
    this.c = c;
}
//generate getters and setters
}

This may look like a lot of work, but you'll have to store the information of the colors anywhere if you want to use them, right? If you've got further questions, comment :)

Edit: If you use the StringColorItem-Class I mentioned above you should use an Adapter for that class, like this:

public class StringColorArrayAdapter extends ArrayAdapter<StringColorItem>{

private Context context;
private int layoutResId;

public StringColorArrayAdapter(Context context, int resource,
        int textViewResourceId, List<StringColorItem> objects) {
    super(context, resource, textViewResourceId, objects);
    this.context = context;
    this.layoutResId = resource;

}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    if(convertView==null)
    {
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = inflater.inflate(layoutResId, parent, false);
    }

    StringColorItem model = this.getItem(position);

     //Handle buttons and add onClickListeners
    final ImageView coloredimage = (ImageView)convertView.findViewById(R.id.colorpicker);
    final ImageView btndelete = (ImageView)convertView.findViewById(R.id.btndelete);


     //Handle TextView and display string from your list
     TextView listItemText = (TextView)convertView.findViewById(R.id.txtCategory); 
     listItemText.setText(model.getS()); 

     coloredimage.setBackgroundColor(model.getC());

    return convertView;
}

}

3
Abhishek On

Take Array<Integer> selectedcolor; in your activity and in your adapter

and add selected color in your color Selection event

colorPickerDialog.setOnColorSelectedListener(new OnColorSelectedListener() {

        @Override
        public void onColorSelected(int color) {
            //Toast.makeText(AddTask.this, "selectedColor : " + color, Toast.LENGTH_SHORT).show();
        selectedcolor.add(color);
        coloredimage.setBackgroundColor(selectedcolor);

        }
    });

and set color from selectedcolor list and set it in getView method

 @Override
        public View getView(final int position, View convertView, ViewGroup parent) {
            View view = convertView;
            if (view == null) {
                LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
                view = inflater.inflate(R.layout.category_row, parent,false);
            } 

            //Handle buttons and add onClickListeners
           final ImageView coloredimage = (ImageView)view.findViewById(R.id.colorpicker);
           final ImageView btndelete = (ImageView)view.findViewById(R.id.btndelete);


            //Handle TextView and display string from your list
            TextView listItemText = (TextView)view.findViewById(R.id.txtCategory); 
            listItemText.setText(list.get(position)); 

            coloredimage.setBackgroundColor(selectedcolor.get(position));

            btndelete.setOnClickListener(new View.OnClickListener(){
                @Override
                public void onClick(View v) { 
                    //do something
                    list.remove(position); //or some other task
                    notifyDataSetChanged();
                }
            });

            return view; 
        }
0
Durga Mohan On

The problem is with this line in you adapter getview

coloredimage.setBackgroundColor(selectedcolor);

When you are calling adapter.notifyDatasetChanged(), it will refresh all the views in your listview. It does set the color for all images to selected color. Instead of doing this, you have to remember the color of each item. you can do this by passing a list to adapter which holds both text and color.

Create a Entity

Public class ListItemRowEntity
{
   public String CategoryText;
   public int SelectedCOlor;
}

Pass this to your adapter

 public MyCustomAdapter(List<ListItemRowEntity> list, Context context) { 
            this.list = list; 
            this.context = context; 
        } 

In getView

listItemText.setText(list.get(position).CategoryText);  
coloredimage.setBackgroundColor(list.get(position).CategoryText.SelectedColor);

Whenever a change happens in your listview, update this list in your activity and call notifydataset.