Android ListView: 如何选择一个项目?

3

我有一个ListView,现在遇到了问题:当我点击其中的一个项目时,我希望它被选中。

我的代码如下:

protected void onResume() {
...
ListView lv = getListView(); 
lv.setOnItemSelectedListener(new OnItemSelectedListener() 
{
    public void onItemSelected(AdapterView<?> adapterView, View view, int pos, long id) {
        Log.v(TAG, "onItemSelected(..., " + pos + ",...) => selected: " + getSelectedItemPosition());
    }
    public void onNothingSelected(AdapterView<?> adapterView) {
        Log.v(TAG, "onNothingSelected(...) => selected: " + getSelectedItemPosition());
    }
});
lv.setOnItemClickListener(new OnItemClickListener()
{
    public void onItemClick(AdapterView<?> adapterView, View view, int pos, long id) {
        lv.setSelection(pos);               
        Log.v(TAG, "onItemClick(..., " + pos + ",...) => selected: " + getSelectedItemPosition());              
    }
});
...
}

当我运行这个程序并点击第二个项目(即pos=1)时,我会得到以下结果:
04-03 23:08:36.994: V/DisplayLists(663): onItemClick(..., 1,...) => selected: -1

即使OnItemClickListener使用正确的参数调用并调用setSelection(1),也没有选择任何项(因此也不会调用OnItemSelectedListener.onItemSelected(...)),并且在setSelection(1)-call之后getSelectedItemPosition()仍然产生-1。
我错过了什么?
迈克尔
PS:我的列表有>=2个元素...
3个回答

8

这里缺少的元素是choiceMode。这并没有很好地文档化,但在Android中,ListView(以及继承自AbsListView的所有内容,如GridView等)默认情况下不允许选择,但可以启用-无论是在XML中还是在代码中:

在XML中:

<ListView
  ...
  android:choiceMode="singleChoice" />

代码:

mListView.setChoiceMode(AbsListView.CHOICE_MODE_SINGLE);

请注意,一旦您这样做了,Android会自动为您设置setSelection(),因此您无需自行跟踪它。此时,您的onClickLister仅用于保存选择,我甚至不会使用OnSelectedItemListener:
@Override
public void onItemClick(final AdapterView<?> list, final View v,
    final int position, final long id) {
  Participant p = mAdapter.getParticipantForId(id);
  eventManager.fire(new ParticipantSelectedEvent(p));
  pxList.smoothScrollToPosition(position); // Make sure selection is plainly visible
}

2
为什么这被踩了呢?它解决了帖子作者永远不会改变的getSelectedItemPosition()问题。是的,如果他只想要相应的项目,那么在onItemClick()中使用getItemAtPosition肯定更容易。然而,choiceMode是用来向用户展示当前选择的项目,并让程序员可以访问它。 - JRaymond
1
我按照描述添加了选择模式(两种变体都有),但没有任何变化! OnItemClickListener仍然没有被调用。尽管屏幕上有反应,即项目短暂变为紫色,然后再次变为白色。 奇怪的是,我可以通过按上下按钮选择项目(然后OnIemSelectListener被调用),但显然不能通过OnItemClickListener选择。 - mmo
等等,OnItemClick从来没有被调用过吗?OnItemSelect监听器仅针对trackPad /上下操作进行配置-它不响应点击,并且我不知道它是否会响应手动调用setSelection。 - JRaymond
因为你正在使用混合控制的手机,如果想要在onItemSelected()和onClick()事件中实现相同的功能,可能需要将两个调用指向同一个函数(由您定义)。使用触摸模式和非触摸模式工作时会涉及一些棘手的问题,我并不是很了解。 - JRaymond
更奇怪的是:OnItemClick确实被调用了(位置正确)。它调用了setSelection(pos),但被忽略了(即没有任何效果)。在那个调用之后,selectedItemPosition仍然是-1。 - mmo
为了测试 setSelection(<n>),我添加了两个菜单选项来以编程方式调用 setSelection。结果对我来说非常奇怪:首先调用 onItemSelected() 并选择该项,但紧接着就会调用 onNothingSelected(),即该项立即被取消选择。我根本不理解这背后的逻辑!我想要实现的只是当用户点击或触摸某个项目(在模拟器中使用鼠标单击它)时,该项目被选择并相应地突出显示为已选择状态。 - mmo

1

试一下这个:--

    ListView lv = getListView();

    lv.setOnItemClickListener(new OnItemClickListener() {
      public void onItemClick(AdapterView<?> parent, View view,
          int position, long id) {

          // selected item
          String product = ((TextView) view).getText().toString();

         Toast.makeText(getApplicationContext(), "Selected Item :" +product, Toast.LENGTH_SHORT).show();

      }
    });

希望这能对你有所帮助。

1
我刚刚意识到,我完全错了。在触摸模式下,选择一个项目没有任何意义。当单击时,你直接对它进行操作(OnClickListener被调用)。 我开始欣赏 Android 处理所有这些不同的设备,具有方向控制按钮、触摸屏等等。但想象在一个不熟悉或无法测试的设备上执行操作并不总是容易的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接