Ajouter une marge au-dessus de l'élément ListView supérieur (et en dessous du dernier) dans Android

147

C'est une très bonne question sur la disposition des éléments dans un ListView sous Android.

J'ai une activité avec une barre de titre en haut et un ListView occupant le reste de l'écran. Je veux que mon ListView apparaisse avec un rembourrage de 10dp à gauche, à droite et en haut, mais lorsque vous faites défiler le ListView vers le haut, je veux qu'il couvre le remplissage de 10dp supérieur avant de disparaître sous le bord fané. De même, lorsque vous faites défiler vers le bas, le dernier élément de la liste devrait apparaître avec 10dp entre le bas du dernier élément de la liste et le bas réel de l'écran (si vous vous demandez pourquoi, c'est parce qu'il y a une jolie image de fond que je veux poussant autour de la ListView).

J'ai essayé d'ajouter un rembourrage au ListView lui-même, mais lorsque vous faites défiler la liste, il disparaît sous le bord du rembourrage.

Je viens d'un contexte de développement Web et l'analogie serait d'ajouter une marge au-dessus du premier élément de la liste (et en dessous du dernier élément de la liste).

Mick Byrne
la source
spécifiez juste la marge gauche et droite ... essayez de coller votre xml ici, pour que je puisse voir le problème edit: attendez, vous voulez dire .... Vous voulez que le rembourrage du haut et du bas défile aussi?
Tek Yin le
Je ne peux pas spécifier la marge gauche et droite - il n'y a pas de `` marge '' dans la mise en page Android, seulement un remplissage. Mais oui, je veux que le rembourrage du haut et du bas défile - c'est une bonne façon de le décrire.
Mick Byrne le
J'ai déjà essayé plusieurs méthodes, et j'ai toujours échoué .. J'ai quelques astuces à faire, mais cela sera plus difficile à faire cependant ... vous mettez 2 objets personnalisés dans l'élément de liste sur la première et la dernière position .. et utilisez un adaptateur personnalisé pour détecter l'objet et le dessiner différemment (hauteur étroite et transparent)
Tek Yin
Ouais ... c'est ce sur quoi je pensais me rabattre aussi. Mais il y a toutes sortes de complications avec cela, car je devrai ensuite définir la couleur d'arrière-plan dans les éléments de la liste, pas dans la vue, ce qui signifie que je devrai ensuite pirater manuellement un certain effet pour afficher lorsque vous avez tapé des choses . Merci pour votre aide quand même ...
Mick Byrne
Bonne nouvelle .. J'ai eu la solution ... vous pouvez utiliser addHeaderView (View v) sur ListActivity .. appelez simplement getListView(). addHeaderView(capView)et getListView(). addHeaderView(botView) assurez-vous qu'il est appelé avant d'initialiser le contenu de la liste, par exemple. setListAdapter (adaptateur);
Tek Yin

Réponses:

397

Tu as écrit:

J'ai essayé d'ajouter un rembourrage au ListView lui-même, mais lorsque vous faites défiler la liste, il disparaît sous le bord du rembourrage.

Définissez l' ListView's clipToPaddingattribut sur false. Cela activera le remplissage autour du ListView et le défilement jusqu'à la fin de la mise en page (et pas seulement jusqu'au bord du remplissage).

Un exemple:

<ListView
    android:id="@+id/list_view"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:divider="@android:color/transparent"
    android:dividerHeight="10.0sp"
    android:padding="16dip"
    android:clipToPadding="false"/>

android:clipToPaddingest un attribut XML de ViewGroup, la classe de base pour les présentations et les conteneurs de vues.

L' appel de méthode associé est:

public void setClipToPadding (boolean clipToPadding)
Gunnar Karlsson
la source
4
De plus, cela peut être transformé en style ou thème via<item name="android:clipToPadding">false</item>
pjco
2
Oh, cela s'applique également à ScrollView
pjco
4
Un peu tard dans la discussion, mais notez que sur les appareils plus anciens (je l'ai repéré sur certains appareils 2.3.x), les vues des éléments de liste sont recyclées trop tôt. Alors que la phase de dessin sait qu'elle peut y dessiner, la phase de mise en page ne le fait pas, donc elle pense que l'élément est déjà hors écran. Voir stackoverflow.com/questions/15915226/… .
Jeffrey Klardie
@JeffreyKlardie Je rencontre le problème où les éléments sont recyclés trop tôt sur un appareil plus ancien et cela oblige même la barre de défilement à se redimensionner à la volée, ce qui semble vraiment étrange. @pjco Je ne sais pas pourquoi mais définir clipToPaddingvia un style ne fonctionne pas pour moi, c'est comme s'il ne s'appliquait pas. Bien que, si je le place directement sur ListView, cela fonctionne.
ForceMagic
5
N'oubliez pas android:scrollbarStyle="outsideOverlay"que la barre de défilement traverse également le remplissage
jfcartier
19
View padding = new View(this);
padding.setHeight(20); // Can only specify in pixels unfortunately. No DIP :-(

ListView myListView = (ListView) findViewById(R.id.my_list_view);

myListView.addHeaderView(padding);
myListView.addFooterView(padding);

myListView.setAdapter(myAdapter);

Le ListView ci-dessus aura un remplissage d'en-tête et de pied de page de 20 pixels.

Jake Wilson
la source
4
Merci d'avoir répondu! Fonctionne très bien!! Si vous voulez mettre la hauteur en dp, cela peut être fait en utilisant DisplayMetrics: float mDensity = getResources().getDisplayMetrics().density; int height = (int) (50 * mDensity + 0.5f); padding.setHeight(height);
Tony Ceralva
3
Ou mieux encore, obtenez des dimens dans dp au niveau Java en utilisant getResources (). GetDimensionPixelOffset (R.dimen.some_value);
greg7gkb
1
Vraiment étonné de voir tout ce que j'apprends sur Android sur StackOverflow par rapport à ceux que j'apprends sur le site des développeurs
TrueCoke
1
Ou encore mieux(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 100, getResources().getDisplayMetrics());
Eugen Pechanec
1
Il n'y a pas de méthode "setHeight ()" pour View dans l'API 23. Au lieu de cela, nous pouvons utiliser "setMinimumHeight ()".
KWA le
10

Annexe à la réponse de @ Jakobud ...

Mon listView utilisait déjà les android:divider/android:dividerHeightpropriétés pour créer des espaces transparents entre les éléments listView. Cela m'a permis d'ajouter simplement les android:headerDividersEnabledet android:footerDividersEnabledpropriétés et définissez les vues en- tête et pied de page à new View(Activity.this).

Légère simplification pour les cas où vous avez déjà configuré des diviseurs dans la listView.

greg7gkb
la source
1
Je conseillerais à quiconque, dans la mesure du possible, d'utiliser des séparateurs au lieu des marges et des rembourrages des articles.
Bonne
2

Ma solution utilisant a ListFragment, basée sur les solutions de @Jakobud et @ greg7gkb.

ListView listView = getListView();
listView.setDivider(null);
listView.setDividerHeight(getResources().getDimensionPixelSize(R.dimen.divider_height));
listView.setHeaderDividersEnabled(true);
listView.setFooterDividersEnabled(true);
View padding = new View(getActivity());
listView.addHeaderView(padding);
listView.addFooterView(padding);
hleinone
la source
1

La réponse de @Gunnar Karlsson est bonne, mais il y a un problème de recyclage prématuré des vues de cellule lorsqu'elles sont complètement derrière le rembourrage, mais pas encore complètement hors de l'écran. La définition de clipToPadding = false en est responsable et peut ou non être corrigée dans une future version d'Android ( lors de l'utilisation de clipToPadding dans ListView, les éléments sont recyclés prématurément )

J'ai une belle solution simple sans effets secondaires:

  1. Ajoutez une mise en page externe (linéaire ou relative) à votre cell_design.xml
  2. Sur cette mise en page externe, ajoutez un remplissage (c'est-à-dire 10dip) pour créer une «marge» autour de la cellule entière. (NB seul le remplissage fonctionnera, pas la marge sur la mise en page extérieure)
  3. Sur l'ensemble ListView android:dividerHeight="-10dip", l'opposé de ce qui entoure la cellule

Par rapport à l'autre réponse, il n'est pas nécessaire de définir la couleur du séparateur. Le rembourrage des cellules les plus hautes et les plus basses sera présent et le diviseur négatif empêchera les diviseurs à double hauteur entre les deux.

James
la source
"sans effets secondaires" ce n'est pas tout à fait vrai. Ajouter une autre couche dans votre hiérarchie de vues, en particulier dans un élément de liste, signifie dégrader les performances.
Teovald