98

下面是一个带有 ListView 的代码片段。我添加了一个emptyView 和一个headerView。添加 headerView 会导致 onItemClick 中的位置增加一。

因此,如果没有 headerView,第一个列表元素的位置将为 0,而使用 headerView,第一个列表元素的位置将为 1!

这会导致我的适配器出现错误,例如在调用 getItem() 和使用其他一些方法时,请参见下文。奇怪的事情:在适配器的 getView() 方法中,第一个列表元素被请求位置为 0,即使添加了 headerView !

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    ListView list = (ListView) viewSwitcher.findViewById(R.id.list);
    View emptyView = viewSwitcher.findViewById(R.id.empty);
    list.setEmptyView(emptyView);

    View sectionHeading = inflater.inflate(R.layout.heading, list, false);
    TextView sectionHeadingTextView = (TextView) sectionHeading.findViewById(R.id.headingText);
    sectionHeadingTextView.setText(headerText);
    list.addHeaderView(sectionHeading);

    list.setAdapter(listAdapter);

    list.setOnItemClickListener(new OnItemClickListener() {

        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            listAdapter.getItem(position);
            //Do something with it
        }
    });
}

一些适配器方法:

@Override
public int getViewTypeCount() {
    return TYPE_COUNT;
}

@Override
public int getItemViewType(int position) {
    return (position < items.size()) ? ITEM_NORMAL : ITEM_ADVANCED;
}

    @Override
public Product getItem(int position) {
    return items.get(position);
}
@Override
public boolean areAllItemsEnabled() {
    return false;
}

@Override
public boolean isEnabled(int position) {
    return (position < items.size());
}

这是添加 headerView 时的正常行为吗?以及如何克服适配器中的问题?

4

11 回答 11

113

我刚刚遇到了这个问题,最好的方法似乎是使用ListView.getItemAtPosition(position)而不是ListAdapter.getItem(position)作为ListView标题的版本帐户,即:-

改为这样做:

myListView.getItemAtPosition(position)
于 2012-11-15T16:56:11.873 回答
32

如果您不关心对标题的点击,请从位置中减去标题视图的数量以获得适配器的位置:

        listView.addHeaderView(inflater.inflate(
                R.layout.my_hdr_layout, null), null, false);
        listView.setAdapter(m_adapter);
        listView.setOnItemClickListener(new OnItemClickListener() {

        @Override
        public void onItemClick(AdapterView<?> parent, View view,
                int position, long id) {
            position -= listView.getHeaderViewsCount();
            final MyObject object = m_adapter.getItem(position);

        }
    });
于 2013-04-17T14:10:33.100 回答
27

如果您将标题添加到ListView成为列表中的第一项。您可以通过覆盖来弥补这一点,getCount()以少返回一个项目,但确保您处理getItem(),getItemId()等等,因为标题将是位置 0 中的项目。

于 2012-06-19T17:55:30.710 回答
14

在实现时AdapterView.OnItemClickListener,我们只是从位置中减去标题。

@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    position -= mListView.getHeaderViewsCount();
    // what ever else follows...
}
于 2015-02-26T04:14:03.487 回答
13

无需更改任何代码。只需使用下面的代码。

 list.setOnItemClickListener(new OnItemClickListener() {
     @Override
     public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
      parent.getAdapter().getItem(position);
         //Do something with it
     }
});
于 2013-02-27T05:26:15.007 回答
9

不要使用您的适配器,请使用 getAdapter 中的“装饰”适配器。

于 2013-01-20T04:03:06.763 回答
5

一种解决方案是将 id 映射到索引。基本上让 id 返回列表中的索引,点击监听器会这样做:

public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            listAdapter.getItem((int) id);
}
于 2012-11-21T08:48:57.510 回答
3

嗨,我们可以通过这种方式解决此问题,首先您创建标题视图,然后在您的列表中注入,最后一步无法 setOnClickListener。它对我有用。欢迎任何反馈

ViewGroup headerView = (ViewGroup) getLayoutInflater().inflate(R.layout.your_header, list,false);
list.addHeaderView(headerView);
headerView.setEnabled(false);
headerView.setOnClickListener(null);
于 2016-05-23T13:16:46.570 回答
0

不要添加很多@Ramesh 没有添加的新内容,而是添加一些额外的上下文:

personList.setOnItemClickListener(new OnItemClickListener() {
    @SuppressWarnings("unchecked")
    public void onItemClick( AdapterView<?> parent, View view, int position, long duration) {
        Map<String, Object> person = (Map<String, Object>) parent.getAdapter().getItem(position);
        if (person != null){

            // If the header was clicked on a null  is returned

            OnPersonUiChangeListener listener = (OnPersonUiChangeListener) getActivity();
            listener.onSelectedPersonChanged(person);
        }
    }
});
于 2013-11-26T03:35:18.287 回答
0

使用 getSelectedItemPosition() 返回当前选中项在适配器数据集中的位置。这种方法不需要担心页眉或页脚的大小。

于 2015-12-11T02:39:44.293 回答
0

这可能对某人有所帮助,改进 Farid_z 和 Philipp 的答案,我们可以正确应用 setItemChecked 和 setTitle 类似这样的东西

        FragmentManager fragmentManager = getSupportFragmentManager();
        fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).commit();
        position += 1;
        mDrawerList.setItemChecked(position, true);
        mDrawerList.setSelection(position);
        position -= 1;
        setTitle(mNavigationDrawerItemTitles[position]);
        mDrawerLayout.closeDrawer(mDrawerList);
于 2016-10-09T11:32:03.120 回答