ListView addHeaderView вызывает увеличение позиции на единицу?


Ниже приведен фрагмент кода с 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?? И как преодолеть проблемы в моем адаптере?

11 92

11 ответов:

Я только что столкнулся с этой проблемой, и лучший способ, кажется, использовать ListView.getItemAtPosition(position) вместо ListAdapter.getItem(position) как ListView версия учитывает заголовки, т. е.: -

вместо этого:

myListView.getItemAtPosition(position)

Если вы не заботитесь о щелчке по заголовку, вычитайте количество просмотров заголовка из позиции, чтобы получить позицию для вашего адаптера:

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

        }
    });

если вы добавляете заголовок к ListView это становится первым пунктом в списке. Вы можете компенсировать это, переопределив getCount() вернуться на один элемент меньше, но убедитесь, что вы обрабатывать getItem(),getItemId() и так далее, поскольку заголовок будет элементом в позиции 0.

при осуществлении AdapterView.OnItemClickListener мы просто вычитаем заголовки из позиции.

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

нет необходимости менять какой-либо код. Просто используйте ниже код.

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

Не используйте свой адаптер, используйте "украшенный" адаптер от getAdapter.

одним из решений этого является сопоставление идентификатора с индексом. В основном make id возвращает индекс в списке, и прослушиватель щелчка будет делать:

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

Привет, мы можем решить это таким образом сначала вы создаете свой вид заголовка, после ввода в свой список и последнего шага не удается setOnClickListener. это работает для меня. любая обратная связь приветствуется

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

не добавить много нового, что @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);
        }
    }
});

с помощью getSelectedItemPosition () возвращает позицию текущего выбранного элемента в наборе данных адаптера. Этот метод не нужно беспокоиться о размере верхних или нижних колонтитулов.

Это может помочь кому-то, улучшая ответ 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);