如何使用 list 中的按钮在 Listactivity 激活 onListItemClick?

我有一个简单的 ListActivity,它使用自定义 ListAdapter 生成列表中的视图。通常 ListAdapter 只会用 TextView 填充视图,但是现在我也想在那里放一个按钮。

然而,根据我的理解和经验,在列表项中放置一个可定焦的视图可以防止单击列表项时在 ListActivity 中触发 onListItemClick ()。按钮仍然在列表项中正常工作,但是当按下按钮之外的某个按钮时,我希望 onListItemClick 被触发。

我该怎么做?

65097 次浏览

I hope I can help here. I assume that you have custom layout for listView items, and this layout consists of button and some other views - like TextView, ImageView or whatever. Now you want to have different event fired on button click and different event fired on everything else clicked.

You can achieve that without using onListItemClick() of your ListActivity.
Here is what you have to do:

You are using custom layout, so probably you are overriding getView() method from your custom adapter. The trick is to set the different listeners for your button and different for the whole view (your row). Take a look at the example:

private class MyAdapter extends ArrayAdapter<String> implements OnClickListener {


public MyAdapter(Context context, int resource, int textViewResourceId,
List<String> objects) {
super(context, resource, textViewResourceId, objects);
}




@Override
public View getView(int position, View convertView, ViewGroup parent) {
String text = getItem(position);
if (null == convertView) {
convertView = mInflater.inflate(R.layout.custom_row, null);
}
//take the Button and set listener. It will be invoked when you click the button.
Button btn = (Button) convertView.findViewById(R.id.button);
btn.setOnClickListener(this);
//set the text... not important
TextView tv = (TextView) convertView.findViewById(R.id.text);
tv.setText(text);
//!!! and this is the most important part: you are settin listener for the whole row
convertView.setOnClickListener(new OnItemClickListener(position));
return convertView;
}


@Override
public void onClick(View v) {
Log.v(TAG, "Row button clicked");
}
}

Your OnItemClickListener class could be declared like here:

private class OnItemClickListener implements OnClickListener{
private int mPosition;
OnItemClickListener(int position){
mPosition = position;
}
@Override
public void onClick(View arg0) {
Log.v(TAG, "onItemClick at position" + mPosition);
}
}

Of course you will probably add some more parameters to OnItemClickListener constructor.
And one important thing - implementation of getView shown above is pretty ugly, normally you should use ViewHolder pattern to avoid findViewById calls.. but you probably already know that.
My custom_row.xml file is RelativeLayout with Button of id "button", TextView of id "text" and ImageView of id "image" - just to make things clear.
Regards!

I've had the same problem with ToggleButton. After half a day of banging my head against a wall I finally solved it. It's as simple as making the focusable view un-focusable, using 'android:focusable'. You should also avoid playing with the focusability and clickability (I just made up words) of the list row, just leave them with the default value.

Of course, now that your focusable views in the list row are un-focusable, users using the keyboard might have problems, well, focusing them. It's not likely to be a problem, but just in case you want to write 100% flawless apps, you could use the onItemSelected event to make the elements of the selected row focusable and the elements of the previously selected row un-focusable.

When a custom ListView contains focusable elements, onListItemClick won't work (I think it's the expected behavior). Just remove the focus from the custom view, it will do the trick:

For example:

public class ExtendedCheckBoxListView extends LinearLayout {


private TextView mText;
private CheckBox mCheckBox;


public ExtendedCheckBoxListView(Context context, ExtendedCheckBox aCheckBoxifiedText) {
super(context);
…
mText.setFocusable(false);
mText.setFocusableInTouchMode(false);


mCheckBox.setFocusable(false);
mCheckBox.setFocusableInTouchMode(false);
…
}
}

I have the same problem: OnListItemClick not fired ! [SOLVED]
That's happen on class that extend ListActivity,
with a layout for ListActivity that content TextBox and ListView nested into LinearLayout
and another layout for the rows (a CheckBox and TextBox nested into LineraLayout).

That's code:

res/layout/configpage.xml (main for ListActivity)

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<TextView
android:id="@+id/selection"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="pippo" />
<ListView
android:id="@android:id/list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:drawSelectorOnTop="false"
android:background="#aaFFaa" >
</ListView>
<LinearLayout>


res/layout/row.xml (layout for single row)
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<CheckBox
android:id="@+id/img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
**android:focusable="false"**
**android:focusableInTouchMode="false"** />


<TextView
android:id="@+id/testo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
**android:focusable="false"**
**android:focusableInTouchMode="false"** />
</LinearLayout>

src/.../.../ConfigPage.java

public class ConfigPage extends ListActivity
{
TextView selection;


public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.configpage);
// loaded from res/value/strings
String[] azioni = getResources().getStringArray(R.array.ACTIONS);
setListAdapter(new ArrayAdapter&lt;String&gt;(this, R.layout.row,
R.id.testo,   azioni));
selection = (TextView) findViewById(R.id.selection);
}


public void onListItemClick(ListView parent, View view, int position, long id)
{
selection.setText(" " + position);
}
}

This begin to work when I added on row.xml

  • android:focusable="false"
  • android:focusableInTouchMode="false"

I use Eclipse 3.5.2
Android SDK 10.0.1
min SDK version: 3

I hope this is helpful
... and sorry for my english :(

I used the getListAdapter().getItem(position) instantiating an Object that holds my values within the item

MyPojo myPojo = getListAdapter().getItem(position);

then used the getter method from the myPojo it will call its proper values within the item .

 ListView lv = getListView();
lv.setTextFilterEnabled(true);


lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// When clicked, show a toast with the TextView text
Toast.makeText(getApplicationContext(), ((TextView) view).getText(),
Toast.LENGTH_SHORT).show();
}
});

as I wrote in previous comment solution is to setFocusable(false) on ImageButton.

There is even more elegant solution try to add android:descendantFocusability="blocksDescendants" in root layout of list element. That will make clicks onListItem possible and separately u can handle Button or ImageButton clicks

Hope it helps ;)

Cheers

just add android:focusable="false" as one of the attributes of your button