Having a button means that you need to listen the click events on that button. But, if the button is inside a list item, you can not simply sense the clicks to the button, because ListView's OnItemClickListener overwhelms all the click events on that item. In order to avoid this and make your button clickable you need to do the following changes...
At first you need to set android:focusable and android:focusableInTouchMode attributes of your button inside the list item to "false".
<Button
.....
android:focusable="false"
android:focusableInTouchMode="false"
.....
>
</Button>
The next thing you need to do is setting an OnClickListener to your button inside your list adapter class. You can achieve this by adding a parameter to your adapter's constructor and/or adding a setter method to the adapter that sets the button's OnClickListener.
In my example I put an OnClickListener instance as a field in my adapter and I set it in my constructor and also added a setter for the field.
public class MyAdapter extends BaseAdapter {
.....
public OnClickListener listener;
.....
public MyAdapter (Context context, OnClickListener listener) {
this.context = context;
mInflater = LayoutInflater.from(this.context);
this.listener = listener;
}
public void setButtonListener(OnClickListener listener) {
this.listener = listener;
}
.....
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView =
mInflater.inflate(R.layout.my_list_row, null);
holder = new ViewHolder();
...
holder._button =
(Button) convertView
.findViewById(R.id.listRowButton);
...
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
.....
if (this.listener != null) {
holder._button.setOnClickListener(this.listener);
}
.....
}
}
And lastly you need to set an OnClickListener to your adapter instance where you set your ListView's adapter inside your Activity. And this is the tricky part that you need to sense which list item's button has received a click event by by using a for loop. (It doesn't look so efficient, but this was the easiest way to achieve my goal, so I did it like this. If you have any other efficient solutions please provide a comment.)
ListView myList = (ListView) findViewById(R.id.myList);
// Firstly I set the OnClickListener as null.
MyAdapter adapter = new MyAdapter(this, null);
.....
// Here is where I set the listener for button inside list item.
myAdapter.setButtonListener(new OnClickListener() {
@Override
public void onClick(View v) {
for (int i = 0; i < _listView.getChildCount(); i++) {
if (v == _listView
.getChildAt(i).findViewById(R.id.listRowButton))
{
// Do Something on Button Click
}
}
}
}});
.....
myList.setAdapter(myAdapter);
That's it! You can do whatever with your list item's button now. You can also use the same procedure with CheckBoxes, RadioButtons or any other Views.
Enjoy!