0

i have a listview that has a textview, an editText and an imageButton. when an image button is clicked i change the image resource. the challenge is when changing the background resource on a row reflects on another row when i scroll down. likewise also the editext content of a particular row also reflects in another row when i scrolled down as well. This is my overriden getview method code

@Override
    public View getView(int position, View convertView, ViewGroup parent) {
        final ViewHolder holder;
        if (convertView == null) {
            convertView = Utilities.inflateView(context, R.layout.syllabus_row,
                    null);
            holder = createViewHolder(convertView);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        holder.txtTopic.setText(model.get(position).getTopic());
        holder.btnDone.setTag(model.get(position).getTopicId());
        holder.btnDone.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                //int position = (Integer) v.getTag();
                //model.get(position).set
                ((ImageButton)v).setImageResource(R.drawable.ic_radio_checked);
                Utilities.ShowMessage(context, holder.edtComment.getText()+"");
            }
        });


        return convertView;
    }
my ViewHolder class and CreatViewHolder Method
private ViewHolder createViewHolder(View view) {
        holder = new ViewHolder();
        holder.txtTopic = (TextView) view.findViewById(R.id.txtSyllabusTopic);
        holder.btnDone = (ImageButton) view.findViewById(R.id.btnSyllabusDone);

        holder.edtComment = (EditText) view
                .findViewById(R.id.edtSyllabusComment);

        // set on item click Listener
        return holder;
    }

    static class ViewHolder {
        public TextView txtTopic;
        public ImageButton btnDone;
        public EditText edtComment;
    }

I don't know what am doing wrong. i have tried various suggestions seen on this site none seems to e working for me.

2 Answers2

0
    Try using - 

    holder.btnDone.setImageResource(R.drawable.ic_radio_checked);

    instead of 

    ((ImageButton)v).setImageResource(R.drawable.ic_radio_checked);

One more thing List View reuses it item view show you have to maintain a list of position where view has changed there color so that you can set default color on the same view at any other position.

You can do Something like this.


public class CustomAdapter extends BaseAdapter{

    private LayoutInflater mInflater;

    private ArrayList<Boolean> mButtonStatusList = new ArrayList<>(50);


    public CustomAdapter(Context context){
        mInflater = LayoutInflater.from(context);
        initializedDefaultButtonList();
    }

    private void initializedDefaultButtonList(){
        for(int i = 0 ; i<50 ; i++){
            mButtonStatusList.add(false);
        }
    }


    private class ViewHolder{
        private TextView textView;
    }


    @Override
    public int getCount() {
        return 50;
    }

    @Override
    public Object getItem(int position) {
        return null;
    }

    @Override
    public long getItemId(int position) {
        return 0;
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {

        ViewHolder holder = null;
        if(convertView == null ){
            convertView = mInflater.inflate(R.layout.item_view, parent, false);
            holder = new ViewHolder();
            holder.textView = (TextView) convertView.findViewById(R.id.mItemText);
            convertView.setTag(holder);
        }else {
            holder = (ViewHolder) convertView.getTag();
        }

        if(mButtonStatusList.get(position)){
            holder.textView.setBackgroundColor(Color.RED);
        }else{
            holder.textView.setBackgroundColor(Color.WHITE);
        }

        holder.textView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mButtonStatusList.set(position, true);
                notifyDataSetInvalidated();
            }
        });

        return convertView;
    }
}
Ishan
  • 1,172
  • 10
  • 25
  • those are the same object, why would this change anything ? – csenga Dec 07 '15 at 12:58
  • i initially used holder.btnDone.setImageResource(drawable). it didnt work – Matthew Odedoyin Dec 07 '15 at 13:09
  • 1
    You have to maintain the position of item where image have been changed and you have to set default image at other positions so that if adapter reuses that view at any other position it should have its default background. – Ishan Dec 07 '15 at 13:22
0

A ListView typically contains more data than the number of displayed rows. If the user scrolls the list, then rows and their associated views are being scrolled out of the visible area. The Java objects which represents the rows can be reused for newly visible rows.

If Android determines that a row is not visible anymore, it allows the getView() of the adapter method to reuse the associated view via the convertView parameter.

The adapter can assign new data to the views contained in the view hierarchy of the convertView. This avoids inflating an XML file and creating new Java objects.

In case Android cannot reuse a row, the Android system passes null to the convertView parameter. Therefore the adapter implementation needs to check for this.

Taken from Vogella.

This means if you do this:

 ((ImageButton)v).setImageResource(R.drawable.ic_radio_checked);

this will appear on another elements in the list too, unless you do not reset it.

if(isAtDefaultState)
{
 holder.btnDone.setImageResource(//default);
}
else if(clicked)
{
 holder.btnDone.setImageResource(R.drawable.ic_radio_checked);
}
   //remains the same
    holder.btnDone.setOnClickListener(new View.OnClickListener()...

So in your getView you must determine whether this item is clicked or not, and set the background according to it.

Edit:

Boolean[] clicked; //store whether the element is clicked or not

int the adapter constructor:
clicked=new Boolean[**listItemSize**];
Arrays.fill(clicked, Boolean.FALSE); // default, none of the is clicked


public View getView(int position, View convertView, ViewGroup parent)

    ...
    if(clicked[position]==false)
    {
     holder.btnDone.setImageResource(//default);
    }
    else if(clicked[position]==true)
    {
     holder.btnDone.setImageResource(R.drawable.ic_radio_checked);
    }


holder.btnDone.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {

        clicked[position]=true;                


                ((ImageButton)v).setImageResource(R.drawable.ic_radio_checked);
                Utilities.ShowMessage(context, holder.edtComment.getText()+"");
            }
        });
csenga
  • 3,819
  • 1
  • 21
  • 31