3

So, what I want is to individually disable a button for the concerned item in the ListView when clicked on the button itself. This should work for multiple buttons as well.

I tried many places for solutions but didn't get a good enough answer.

What's happening is when i click on a button in the listview, i see other buttons getting clicked automatically when i scroll down to see other buttons which is quite weird and not helping the situation.

This is the Adapter.

public class ListViewAdapter extends BaseAdapter implements ListAdapter {

private ArrayList<String> list = new ArrayList<String>();
private Context context;
private StringBuilder user_id;
private Button sendReq;
private ListViewAdapter adapter;
private JSONArray peopleArray;
private int selectedIndex;
private ViewHolder viewHolder;
private static boolean[] buttonsClicked;
private View rowView;

public ListViewAdapter(ArrayList<String> list, Context context,String user_id,JSONArray jsonArray) {
    this.user_id = new StringBuilder(user_id.toString());
    this.list = list;
    this.context = context;
    peopleArray = jsonArray;
    selectedIndex = -1;
    this.adapter = this;
    buttonsClicked = new boolean[list.size()];
}

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

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

@Override
public long getItemId(int pos) {
    //return list.get(pos).getId();
    //just return 0 if your list items do not have an Id variable.
    return 0;
}

@Override
public boolean isEnabled(int position){
    return false;
}

static class ViewHolder{
    public TextView ItemText;
    public Button ItemButton;
}

public void setSelectedIndex(int index){
    selectedIndex = index;
    notifyDataSetChanged();
}

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

    if (rowView == null) {
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        rowView = inflater.inflate(R.layout.my_custom_list_layout, null);
        //configure view holder
        viewHolder = new ViewHolder();
        viewHolder.ItemText = (TextView) rowView.findViewById(R.id.list_item_text);
        viewHolder.ItemButton = (Button) rowView.findViewById(R.id.list_item_button);
        rowView.setTag(viewHolder);
    }
    else {
        //fill data
        viewHolder = (ViewHolder) rowView.getTag();
    }
    //Handle TextView and display string from your list
    TextView listItemText = (TextView)rowView.findViewById(R.id.list_item_text);
    listItemText.setText(list.get(position));

    //Handle buttons and add onClickListeners
    sendReq = (Button) rowView.findViewById(R.id.list_item_button);

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

            Log.d("Button position: ", " " +  position);
            ((Button)v).setEnabled(false);
            notifyDataSetChanged();
        }
    });

    return rowView;
}
}

This is the layout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="60dp"
android:weightSum="100"
android:orientation="horizontal">

    <ImageView
        android:id="@+id/list_item_image"
        android:layout_width="0dp"
        android:layout_height="fill_parent"
        android:layout_weight="20"
        android:src="@drawable/default_picture"/>

    <TextView
        android:id="@+id/list_item_text"
        android:layout_width="0dp"
        android:layout_height="fill_parent"
        android:gravity="center"
        android:layout_weight="50"
        android:textSize="18sp"
        android:textStyle="bold" />

    <Button
        android:id="@+id/list_item_button"
        android:layout_width="0dp"
        android:layout_height="fill_parent"
        android:layout_weight="30"
        android:text="Send Req"
        android:focusable="false"/>

</LinearLayout>

This is how I am using the adapter in an activity

arrayList.add("Never");
arrayList.add("let");
arrayList.add("anyone");
arrayList.add("make");
arrayList.add("you");
arrayList.add("that");
arrayList.add("you");
arrayList.add("have");
arrayList.add("limits");
myAdapter = new ListViewAdapter(arrayList,this,"",jsonArray);
listview.setAdapter(myAdapter);
Community
  • 1
  • 1
rv.
  • 81
  • 1
  • 2
  • 8
  • If its happenning that button in every nth row element in the listview is getting clicked then probably you can refer this question -http://stackoverflow.com/questions/6470089/why-did-the-listview-repeated-every-6th-item – Ameya Kulkarni Jan 08 '16 at 15:14

1 Answers1

2

When you click a button, it will disable one Button. Then, when you scroll, that Button will get recycled and reused by other items. You never reenable that Button, so after a while, scrolling up and down, all your Buttons will be disabled.

This isn't the correct way to do this. You cannot make changes in any View based on some action that the user makes (like clicking a button) because the Views in a ListView all get recycled and reused for different list items. When the user takes some action you need to change your data. In getView() you need to use the data to set the state of the Views.

In your case, you could do something like this:

  • Add a private boolean[] enabled array as a member variable in the adapter.
  • Initialize the array in your adapter constructor like this:

    enabled = new boolean[list.size()]; // Enable all items for (int k = 0; k < enabled.length; k++) { enabled[k] = true; }

  • In your onClick() method, do this instead of disabling the Button:

    enabled[position] = false; notifyDataSetChanged();

  • In getView(), set the Button enabled state based on your data like this:

    viewHolder.ItemButton.setEnabled(enabled[position]);

David Wasser
  • 93,459
  • 16
  • 209
  • 274
  • Thanks a ton David Wasser. I was on the same tangent, but didn't have the expertise and knowledge that you do. Any book or resource you suggest where I could actually start getting such expertise. – rv. Jan 08 '16 at 16:17
  • Not specifically, but View recycling is something that trips up a lot of people, especially ListView. There are some good talks from Google engineers on YouTube about ListView and there are some good tutorials that explain how View recycling works. Search for "view recycling" or "view reuse" – David Wasser Jan 09 '16 at 09:13
  • I just migrated to [RecyclerView](https://developer.android.com/reference/android/support/v7/widget/RecyclerView.html) to get rid of all these sorts of problems. It's much better now. – Kathir Dec 04 '18 at 09:00