web-dev-qa-db-fra.com

ListView addHeaderView provoque-t-il une augmentation d'un poste?

Ci-dessous se trouve un extrait de code avec un ListView. J'ai ajouté un emptyView et un headerView. L'ajout de headerView entraîne une augmentation d'un unité dans la position de onItemClick.

Donc, sans l'entête headerView, le premier élément de la liste aurait la position 0; avec l'en-têteView, la position du premier élément de la liste serait 1!

Cela provoque des erreurs dans mon adaptateur, par exemple. lorsque vous appelez getItem () et utilisez d'autres méthodes, voir ci-dessous . Chose étrange: dans la méthode getView () de l'adaptateur, le premier élément de la liste est demandé avec la position 0 même si l'en-tête est ajouté !!

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

Quelques méthodes d'adaptateur:

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

Est-ce le comportement normal lors de l'ajout d'un headerView? Et comment surmonter les problèmes de mon adaptateur?

94
d1rk

Je viens de rencontrer ce problème et le meilleur moyen semble utiliser le ListView.getItemAtPosition(position) au lieu de ListAdapter.getItem(position) en tant que comptes de version ListView pour les en-têtes, c'est-à-dire: -

Faites ceci à la place:

myListView.getItemAtPosition(position)
112
Ian Warwick

Si vous ne vous souciez pas du clic sur l'en-tête, soustrayez le nombre de vues d'en-tête de la position pour obtenir la position de votre adaptateur:

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

        }
    });
31
farid_z

Si vous ajoutez un en-tête à une ListView, celui-ci devient le premier élément de la liste. Vous pouvez compenser cela en remplaçant la fonction getCount() par un élément de moins, mais assurez-vous de gérer les fonctions getItem(), getItemId() et ainsi de suite, car l'en-tête correspond à l'élément en position 0.

27
akshaydashrath

Lors de la mise en œuvre de AdapterView.OnItemClickListener, nous soustrayons simplement les en-têtes de la position. 

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

Pas besoin de changer de code. Utilisez simplement le code ci-dessous. 

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

N'utilisez pas votre adaptateur, utilisez l'adaptateur 'décoré' de getAdapter.

9
cycDroid

Une solution à ce problème consiste à mapper l'identifiant sur index. En gros, make id renvoie l’index dans la liste et l’auditeur de clics ferait:

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

Bonjour, nous pouvons résoudre ce problème de cette façon D’abord, vous créez votre vue d’en-tête, après l’injection dans votre liste et la dernière étape impossible avec setOnClickListener. ça marche pour moi. toute rétroaction bienvenue 

ViewGroup headerView = (ViewGroup) getLayoutInflater().inflate(R.layout.your_header, list,false);
list.addHeaderView(headerView);
headerView.setEnabled(false);
headerView.setOnClickListener(null);
3
Ezequiel García

Utilisez getSelectedItemPosition () Renvoie la position de l'élément actuellement sélectionné dans le jeu de données de l'adaptateur . Cette méthode n'a pas à vous préoccuper de la taille des en-têtes ou des pieds de page.

0
luhaiwork

Sans ajouter beaucoup de nouvelles choses que @Ramesh n'a pas ajoutées, mais un contexte supplémentaire:

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);
        }
    }
});
0
Peter Shannon

Cela pourrait aider quelqu'un, améliorant les réponses de Farid_z et de Philipp, nous pouvons appliquer correctement setItemChecked et setTitle avec quelque chose comme ceci 

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