Mikael
Mikael

Reputation: 21

Android ListView custom row with multiple buttons troubles with OnClickListener it affects multiple list items

Hello I have searched the forum for hours now and decided to place a question cause I can't really find what's wrong in my code. I have a ListView followed by a custom adapter. Each item in my listView looks like this "|txtView| |Btn 0| |Btn 1| |Btn 2|" and I'm using ViewHolder to increase performance. I use setOnClickListener from the custom adapter. Each button clicked should change it's background to Green color and the others to gray.

My problem is that when clicking on a certain button at certain row item it also changes the background on another button at another row. I don't seem to find my problem , i'm guessing it's related to the fact i'm using the reuse ability with the ViewHolder.

Hope you guys can help , many thanks.

this is my getView inside the adapter

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder holder = null;


    if (convertView == null) {
        convertView = mInflater.inflate(R.layout.bet_list_item, null);

        holder = new ViewHolder();

        holder.tvGameDescription = (TextView) convertView
                .findViewById(R.id.gameDescription);
        holder.button0 = (Button) convertView
                .findViewById(R.id.button0);
        holder.button1 = (Button) convertView
                .findViewById(R.id.button1);
        holder.button2 = (Button) convertView
                .findViewById(R.id.button2);

        convertView.setTag(holder);
    } else {

        holder = (ViewHolder) convertView.getTag();

    }

    MyOnclickListener myOnclickListener = new MyOnclickListener(holder);         

    holder.buttonSide1.setOnClickListener(myOnclickListener);
    holder.buttonSideX.setOnClickListener(myOnclickListener);
    holder.buttonSide2.setOnClickListener(myOnclickListener);

this is the listener implementation :

private class MyOnclickListener implements OnClickListener {


    private ViewHolder viewHolder;
    boolean[] buttonsClickStatus = { false, false, false }; //all gray at start and not clicked

    public MyOnclickListener(ViewHolder viewHolder) {
        this.viewHolder = viewHolder;
    }

    @Override
    public void onClick(View v) {
        switch (((Data) v.getTag()).getBtnPosition()) { 

        case Consts.BUTTON_0:
        if (!buttonsClickStatus[0]) { // case the btn is gray unclicked
                setButtonsaBackground(0); // changes the background 
                buttonsClickStatus[0] = true;
                buttonsClickStatus[1] = false;
                buttonsClickStatus[2] = false;
        } else { // case already green clicked already
                addOrRemove = false;
                setButtonsaBackground(3);
                for (int i = 0; i < buttonsClickStatus.length; i++) {
                buttonsClickStatus[i] = false;
            }
        }

        break;

        case Consts.BUTTON_1:
            if (!buttonsClickStatus[1]) { // case gray
                setButtonsaBackground(1);
                buttonsClickStatus[1] = true;
                buttonsClickStatus[0] = false;
                buttonsClickStatus[2] = false;
            } else { // case already green
                addOrRemove = false;
                setButtonsaBackground(3);
                for (int i = 0; i < buttonsClickStatus.length; i++) {
                    buttonsClickStatus[i] = false;
                }
            }
            break;

        case Consts.BUTTON_2:
            if (!buttonsClickStatus[2]) { // case gray
                setButtonsaBackground(2);
                buttonsClickStatus[2] = true;
                buttonsClickStatus[0] = false;
                buttonsClickStatus[1] = false;
            } else { // case already green
                addOrRemove = false;
                setButtonsaBackground(3);
                for (int i = 0; i < buttonsClickStatus.length; i++) {
                buttonsClickStatus[i] = false;
                }
            }
            break;

        default:
            break;
        }

                    //call a function to update data only in the activity
        myActivity.update((Data) v.getTag());

    }

SetBackground is inside the listener as private method:

    private void setButtonsaBackground(int clicked) {
        switch (clicked) {
        case 0:

            viewHolder.button0.setBackgroundColor(Color.GREEN);
            viewHolder.button1.setBackgroundColor(Color.GRAY);
            viewHolder.button2.setBackgroundColor(Color.GRAY);

            break;
        case 1:

            viewHolder.button1.setBackgroundColor(Color.GREEN);
            viewHolder.button0.setBackgroundColor(Color.GRAY);
            viewHolder.button2.setBackgroundColor(Color.GRAY);

            break;
        case 2:

            viewHolder.button2.setBackgroundColor(Color.GREEN);
            viewHolder.button0.setBackgroundColor(Color.GRAY);
            viewHolder.button1.setBackgroundColor(Color.GRAY);
            break;

        case 3:
            viewHolder.button2.setBackgroundColor(Color.GRAY);
            viewHolder.button0.setBackgroundColor(Color.GRAY);
            viewHolder.button1.setBackgroundColor(Color.GRAY);
            break;

        default:
            break;
        }

    }

Upvotes: 2

Views: 4995

Answers (3)

Hafizur Rahman
Hafizur Rahman

Reputation: 11

I have solved the problem by the following :

I tagged holder in button.

 holder.btnSetLock.setTag(holder);
 holder.btnUnLock.setTag(holder);

I have set the background color by the following :

holder.btnUnLock.setOnClickListener(new OnClickListener() {

  @Override
  public void onClick(View v) {
 // TODO Auto-generated method stub
 // Button btn = Button(v);
   holder = (ViewHolder) v.getTag();
   holder.btnSetLock.setBackgroundResource(R.drawable.btn_lock_bg_right);
holder.btnUnLock.setBackgroundResource(R.drawable.btn_unlock_bg_left);

}
});

Upvotes: 1

Raghunandan
Raghunandan

Reputation: 133560

In your getview method.

 if(posiiton==0)
 {
   holder.buttonSide1.setOnClickListener(myOnclickListener);
 }

Instead of using if condition you can use

 for(int i=0;i<yourlisitemcount;i++)
 {
 if(position==i)    //make sure you click the button in appropriate listview position
  {
    holder.buttonSide1.setOnClickListener(myOnclickListener);
  }
 }

Edit - The below code worked for me.

                    vh.b1=(Button)arg1.findViewById(R.id.b1);//button 1
            vh.b2=(Button)arg1.findViewById(R.id.b2);// button2

            vh.b1.setOnClickListener(new OnClickListener()
            {

                public void onClick(View v) {
                    if(position==1)
                    {
                        vh.b1.setBackgroundColor(Color.RED);
                        vh.b2.setBackgroundColor(Color.GREEN);
                    }


                }

            });

Upvotes: 0

Droidee
Droidee

Reputation: 94

Hey i just had a similar problem once when i was working on a project, it was an emergency then and i found out some not so good solution for this.

All i did is gave a unique content description to the text view or the buttons in your case while findViewbyId in the if condition of your getView() method and then checked the condition if the onclick() overridden method.

Will try to find out a better solution for this.

Upvotes: 0

Related Questions