J'ai quelques problèmes lorsque j'essaie de supprimer l'en-tête d'une listView
. Au début, j'utilise addHeaderView()
pour l'ajouter, mais lorsque je change de présentation, je veux qu'il disparaisse, mais removeHeaderView()
ne fonctionne pas ...
J'ai aussi essayé de régler la visibilité sur GONE et cela ne disparaît pas ...
Que puis-je faire?
Merci d'avance
Essayez l'approche mentionnée ci-dessous.
Les méthodes Android ListView#addHeaderView
et ListView#addFooterView
sont étranges: vous devez ajouter les vues d'en-tête et de pied de page avant de configurer l'adaptateur de ListView afin que ListView puisse prendre en compte les en-têtes et les pieds de page. Sinon, vous obtenez une exception. Ici, nous ajoutons un ProgressBar (spinner) comme headerView:
// spinner est une barre de progression
listView.addHeaderView(spinner);
Nous aimerions être en mesure de montrer et de cacher ce spinner à volonté, mais le supprimer de façon pure et simple est dangereux car nous ne pourrions plus jamais l'ajouter sans détruire ListView - souvenez-vous, nous ne pouvons pas ajouter HeaderView après avoir c'est adaptateur:
listView.removeHeaderView(spinner); //dangerous!
Alors cachons-le! Il s'avère que c'est difficile, aussi. Si vous masquez simplement la vue en rotation, vous obtenez une zone d’en-tête vide, mais toujours visible.
Maintenant, essayez de cacher le spinner:
spinner.setVisibility(View.GONE);
Résultat: zone d'en-tête toujours visible avec un espace moche:
La solution consiste à placer la barre de progression dans un LinearLayout qui englobe son contenu et masque le contenu. De cette façon, LinearLayout encapsulant se réduira lorsque son contenu sera masqué, ce qui produira un headerView techniquement toujours présent, mais ayant une valeur 0dip élevée:
<LinearLayout
xmlns:a="http://schemas.Android.com/apk/res/Android"
Android:orientation="vertical"
Android:layout_width="fill_parent"
Android:layout_height="wrap_content">
<!-- simplified -->
<ProgressBar
Android:id="@+id/spinner"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"/>
</LinearLayout>
Ensuite, définissez la mise en page comme en-tête:
spinnerLayout = getLayoutInflater().inflate(R.layout.header_view_spinner, null);
listView.addHeaderView(spinnerLayout);
Et quand nous devons le cacher, cachez le contenu de la mise en page, pas la mise en page:
spinnerLayout.findViewById(R.id.spinner).setVisibility(View.GONE);
L'en-tête disparaît de la vue. Pas plus d'espace laide au sommet!
La plupart des gens n'aiment pas utiliser AddHeaderView
. Cependant, j'ai parfois trouvé cela très pratique d'éviter de modifier des adaptateurs complexes ou si les en-têtes ne leur sont pas très proches.
Avec cette astuce simple, vous pourrez supprimer/ajouter des en-têtes de manière transparente :
J'ajoute une LinearLayout
vide avec orientation vertical
et une hauteur wrap_content
, en tant que vue d'en-tête unique (laissez mListView
la cible listView
):
LinearLayout mCustomHeaders=new LinearLayout(context);
mCustomHeaders.setOrientation(LinearLayout.VERTICAL);
mListView.addHeaderView(mCustomHeaders);
mListView.setAdapter (.......)
Ensuite, je peux ajouter des éléments aléatoires, n'importe où, à la liste en tant qu'en-tête, même lorsque la liste est pleine:
mCustomHeaders.add(myHeaderView1);
mCustomHeaders.add(myHeaderView2);
mCustomHeaders.add(myHeaderView3);
Vous pouvez également supprimer tous les en-têtes, à tout moment:
mCustomHeaders.removeAllViews(); // will erase all headers
Vous avez l'idée ... J'espère que ça aide!
Le problème est que vous créez toujours un nouvel objet quand vous faites:
View headerView = someView
Donc, la nouvelle vue n'est pas la même que la vue déjà ajoutée en tant qu'en-tête de listView, essayez ceci:
View headerView = inflater.inflate(R.layout.adapter_datatable_saleitem_header, null, false);
headerView.setTag(this.getClass().getSimpleName() + "header");
if (listView.getHeaderViewsCount() > 0) {
View oldView = listView.findViewWithTag(this.getClass().getSimpleName() + "header");
if (oldView != null) {
listView.removeHeaderView(oldView);
}
}
Où drawerLogoView
est mon aperçu, voici ce que je fais:
drawerLogoView = mInflater.inflate(R.layout.navigation_drawer_custom_layout, null);
mDrawerList.addHeaderView(drawerLogoView,null,false);
LinearLayout layOut = ((LinearLayout)drawerLogoView.findViewById(R.id.NavProfilePreviewLayout));
layOut.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, 0));
Ainsi, il devient invisible: D Pour le montrer, vous pouvez utiliser ceci:
LinearLayout layOut = ((LinearLayout)drawerLogoView.findViewById(R.id.NavProfilePreviewLayout));
layOut.setLayoutParams(newRelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT));
Vous pouvez vérifier si le nombre d'en-têtes> 0 puis supprimer l'en-tête et l'ajouter à nouveau.
Cela fonctionne très bien pour moi.
View _headerView;
private void function HandleHeaderView(){
if(listView.getHeaderViewsCount() > 0)
{
listView.removeHeaderView(_headerView);
}
/* Add list view header */
_headerView = GetHeaderView();
listView.addHeaderView(_headerView);
}
private View GetHeaderView()
{
View header = getLayoutInflater().inflate(R.layout.header_layout, null);
// TODO: ...
return header
}
J'ai rencontré ce problème dans un scénario légèrement déguisé: le ListView que je traitais provenait de PreferenceFragment et l'en-tête représente une PreferenceCategory. Ainsi, ma liberté d'installation du ListView était sévèrement limitée. Mais il y avait deux approches (inspirées en partie par d’autres réponses sur cette page). L'une consistait à ajouter une mise en page personnalisée à ma PreferenceCategory (à l'aide d'une classe qui extends Android.preference.PreferenceCategory
, voir Rubriques personnalisées PreferenceCategory). Mais j’ai trouvé une solution de contournement plus simple: pour la première préférence de cette PreferenceCategory, je remplace onCreateView()
:
@Override public View onCreateView(ViewGroup parent) {
parent.setTop(-parent.getChildAt(0).getTop());
return super.onCreateView(parent);
}
Si vous utilisez addHeaderView (), vous ne pouvez pas supprimer votre en-tête après cela.
Donc, n'utilisez pas addHeaderView (). Créez plutôt votre propre adaptateur qui Fusionne votre liste principale de vues avec votre en-tête. Bien que mon MergeAdapter ne traite pas votre cas spécifique, vous pouvez l'utiliser pour voir Le concept de fusion de plusieurs sources de lignes: