Aggiungi margine sopra l'elemento ListView superiore (e sotto l'ultimo) in Android


147

Questa è una bella domanda sul layout degli oggetti in un ListView in Android.

Ho un'attività con una barra del titolo in alto e un ListView che occupa il resto dello schermo. Voglio che il mio ListView appaia con un'imbottitura di 10dp a sinistra, a destra e in alto, ma quando scorri ListView in alto, voglio che copra l'imbottitura di 10dp prima di scomparire sotto il bordo sbiadito. Allo stesso modo, quando scorri verso il basso, l'ultimo elemento dell'elenco dovrebbe apparire con 10dp tra il fondo dell'ultimo elemento dell'elenco e il fondo effettivo dello schermo (se ti stai chiedendo perché, è perché c'è una bella immagine di sfondo che voglio frugando in ListView).

Ho provato ad aggiungere il riempimento al ListView stesso, ma quando si scorre l'elenco scompare sotto il bordo del riempimento.

Vengo da uno sfondo di sviluppo web e l'analogia sarebbe quella di aggiungere un margine sopra il primo elemento dell'elenco (e sotto l'ultimo elemento dell'elenco).


specifica solo il margine sinistro e destro ... prova a incollare qui il tuo XML, così posso vedere il problema modificare: aspetta, vuoi dire ... Vuoi scorrere anche il padding superiore e inferiore?
Tek Yin

Non riesco a specificare il margine sinistro e destro: non esiste un "margine" nel layout Android, ma solo il riempimento. Ma sì, voglio far scorrere le imbottiture superiore e inferiore: è un buon modo per descriverlo.
Mick Byrne,

Ho già provato diversi metodi, e ancora fallito .. Ho alcuni trucchi da fare, ma sarà più difficile farlo però ... hai messo 2 oggetti personalizzati nella voce di elenco nella prima e ultima posizione .. e usi l'adattatore personalizzato per rileva l'oggetto e disegnalo in modo diverso (altezza ridotta e trasparente)
Tek Yin

Sì ... è quello su cui ho pensato di ricorrere anche io. Ma ci sono molte complicazioni, dato che dovrò impostare il colore di sfondo nelle voci dell'elenco, non la vista, il che significa che dovrò quindi hackerare manualmente in qualche modo per mostrare quando hai toccato le cose . Grazie comunque per il tuo aiuto ...
Mick Byrne

Buone notizie .. Ho ottenuto la soluzione ... è possibile utilizzare addHeaderView (Visualizza v) su ListActivity .. basta chiamare getListView(). addHeaderView(capView)e getListView(). addHeaderView(botView) assicurarsi che abbia chiamato prima di inizializzare il contenuto dell'elenco, ad es. setListAdapter (adattatore);
Tek Yin,

Risposte:


397

Hai scritto:

Ho provato ad aggiungere il riempimento al ListView stesso, ma quando si scorre l'elenco scompare sotto il bordo del riempimento.

Impostato ListView's clipToPadding attributo su false. Ciò consentirà il riempimento intorno ListView e lo scorrimento fino alla fine del layout (e non solo al bordo del riempimento).

Un esempio:

<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:clipToPaddingè un attributo XML di ViewGroup, la classe di base per i layout e i contenitori delle viste.

La chiamata del metodo correlato è:

public void setClipToPadding (boolean clipToPadding)

4
Inoltre, questo può essere trasformato in uno stile o in un tema tramite<item name="android:clipToPadding">false</item>
pjco

2
Oh, questo vale anche per ScrollView
pjco

4
Un po 'tardi alla discussione, ma nota che sui dispositivi più vecchi (l'ho notato su alcuni dispositivi 2.3.x), le visualizzazioni degli elementi dell'elenco vengono riciclate troppo presto. Mentre la fase di disegno sa che può disegnare lì, la fase di layout no, quindi pensa che l'elemento sia già fuori schermo. Vedi stackoverflow.com/questions/15915226/… .
Jeffrey Klardie,

@JeffreyKlardie Riscontro il problema in cui gli articoli vengono riciclati troppo presto sul dispositivo più vecchio e persino la barra di scorrimento si ridimensiona al volo, il che sembra davvero strano. @pjco Non sono sicuro del perché, ma l'impostazione clipToPaddingtramite uno stile non funziona per me, è come se non venisse applicato. Tuttavia, se l'ho impostato direttamente su ListView funziona.
ForceMagic,

5
Non dimenticare che android:scrollbarStyle="outsideOverlay"anche la barra di scorrimento attraversa completamente l'imbottitura
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);

Il ListView sopra avrà un'intestazione e un piè di pagina di 20 pixel.


4
Grazie per la risposta! Funziona alla grande!! Se vuoi mettere l'altezza in dp, puoi farlo usando DisplayMetrics: float mDensity = getResources().getDisplayMetrics().density; int height = (int) (50 * mDensity + 0.5f); padding.setHeight(height);
Tony Ceralva,

3
O ancora meglio, ottenere dimens in dp a livello Java usando getResources (). GetDimensionPixelOffset (R.dimen.some_value);
greg7gkb,

1
Veramente stupito da quante cose Android imparo su StackOverflow contro quelle che imparo sul sito degli sviluppatori
TrueCoke

1
O meglio(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 100, getResources().getDisplayMetrics());
Eugen Pechanec,

1
Non esiste un metodo "setHeight ()" per View in API 23. Invece possiamo usare "setMinimumHeight ()".
KWA,

10

Appendice alla risposta di @ Jakobud ...

Il mio listView stava già facendo uso delle android:divider/android:dividerHeightproprietà per creare spazi trasparenti tra gli elementi di listView. Questo mi ha permesso di aggiungere semplicemente le android:headerDividersEnablede android:footerDividersEnabledproprietà e impostare i punti di vista Header e Footer anew View(Activity.this) .

Leggera semplificazione per i casi in cui hai già settaggi divisori in listView.


1
Consiglierei a chiunque, ove possibile, di utilizzare i divisori anziché nei margini e nelle imbottiture degli articoli. Ottima risposta
dzsonni il

2

La mia soluzione utilizza un ListFragment, basato sulle soluzioni di @Jakobud e @ 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);

1

La risposta di @Gunnar Karlsson è buona, ma il problema è che le visualizzazioni delle celle vengano riciclate prematuramente quando sono completamente dietro l'imbottitura, ma non ancora completamente fuori dallo schermo. L'impostazione di clipToPadding = false è responsabile di ciò e può o non può essere risolto in una versione futura di Android. ( Quando si utilizza clipToPadding in ListView, gli elementi vengono riciclati prematuramente )

Ho una bella soluzione semplice senza effetti collaterali:

  1. Aggiungi un layout esterno (lineare o relativo) a cell_design.xml
  2. Su questo layout esterno aggiungi un'imbottitura (cioè 10dip) per creare un "margine" attorno all'intera cella. (NB funziona solo l'imbottitura, non il margine sul layout esterno)
  3. Nel set ListView android:dividerHeight="-10dip", l'opposto di ciò che è intorno alla cella

Rispetto all'altra risposta, non è necessario impostare il colore del divisore. L'imbottitura nelle celle più in alto e più in basso sarà presente e il divisore negativo impedirà i divisori a doppia altezza in mezzo.


"senza effetti collaterali" non è del tutto vero. L'aggiunta di un altro livello nella gerarchia della vista, specialmente in un elemento di visualizzazione elenco, significa degradare le prestazioni.
Teovald,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.