Android ListView addHeaderView 导致位置增加一?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11106397/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 06:01:47  来源:igfitidea点击:

ListView addHeaderView causes position to increase by one?

androidlistviewlistadapter

提问by d1rk

Below is a code snippet with a ListView. I added an emptyView and a headerView. Adding the headerView causes the position in the onItemClick to be increased by one.

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

So without the headerView the first list element would have position 0, with the headerView the position of the first list element would be 1!

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

This causes errors in my adapter, e.g. when calling getItem() and using some other methods, see below. Strange thing: In the getView() method of the adapter the first list element is requested with position 0 even if the headerView is added!!

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

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
        }
    });
}

Some adapter methods:

一些适配器方法:

@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());
}

Is this the normal behaviour when adding a headerView?? And how to overcome the issues in my adapter?

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

回答by Ian Warwick

I just came across this problem and the best way seems to use the ListView.getItemAtPosition(position)instead of ListAdapter.getItem(position)as the ListViewversion accounts for the headers, ie:-

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

Do this instead:

改为这样做:

myListView.getItemAtPosition(position)

回答by farid_z

If you don't care about the click to the header, subtract the number of header views from the position to get the position for your adapter:

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

        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);

        }
    });

回答by akshaydashrath

If you add a header to a ListViewthat becomes the first item in the list. You could compensate for this by overriding the getCount()to return one item less, but ensure you handle the getItem(), getItemId()and so on as the header would be the item in position 0.

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

回答by philipp

When implementing AdapterView.OnItemClickListenerwe just subtract the headers from the position.

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

@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    position -= mListView.getHeaderViewsCount();
    // what ever else follows...
}

回答by Ramesh Akula

No need to change any code. Simply use below code.

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

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

回答by cycDroid

Do not use your adapter, use 'decorated' adapter from getAdapter.

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

回答by Heinrisch

One solution to this is to map the id to index. Basically make id return the index in the list and the the click listener would do:

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

public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            listAdapter.getItem((int) id);
}

回答by Ezequiel García

Hi we can resolve this in this way first you create your header view, after inject in your list and the last step unable the setOnClickListener. its works for me. any feedback welcome

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

ViewGroup headerView = (ViewGroup) getLayoutInflater().inflate(R.layout.your_header, list,false);
list.addHeaderView(headerView);
headerView.setEnabled(false);
headerView.setOnClickListener(null);

回答by truespan

This might help somebody, improving on Farid_z and Philipp's answer, we can correctly apply the setItemChecked and setTitle with something like this

这可能对某人有所帮助,改进 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);

回答by luhaiwork

Use getSelectedItemPosition() Return the position of the currently selected item within the adapter's data set. This method don't need to worry about the size of headers or footers.

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