Fügen Sie in Android einen Rand über dem oberen ListView-Element (und unter dem letzten) hinzu

147

Dies ist eine ziemlich gute Frage zum Layout von Elementen in einer ListView in Android.

Ich habe eine Aktivität mit einer Titelleiste oben und einer ListView, die den Rest des Bildschirms einnimmt. Ich möchte, dass meine ListView links, rechts und oben mit 10-dp-Auffüllung angezeigt wird. Wenn Sie jedoch die ListView nach oben scrollen, soll sie die obere 10-dp-Auffüllung abdecken, bevor sie unter der verblassten Kante verschwindet. Wenn Sie nach unten scrollen, sollte das letzte Listenelement mit 10 dp zwischen dem unteren Rand des letzten Listenelements und dem tatsächlichen unteren Bildschirmrand angezeigt werden (wenn Sie sich fragen, warum, liegt es daran, dass ich ein hübsches Hintergrundbild haben möchte in der ListView herumstochern).

Ich habe versucht, der ListView selbst eine Auffüllung hinzuzufügen, aber wenn Sie durch die Liste scrollen, verschwindet sie unter dem Rand der Auffüllung.

Ich habe einen Webentwickler-Hintergrund und die Analogie wäre, einen Rand über dem ersten Listenelement (und unter dem letzten Listenelement) hinzuzufügen.

Mick Byrne
quelle
Geben Sie nur den linken und rechten Rand an. Versuchen Sie, Ihre XML-Datei hier einzufügen, damit ich das Problem bearbeiten kann: Warten Sie, Sie meinen ... Sie möchten, dass auch die obere und untere Polsterung gescrollt werden?
Tek Yin
Ich kann den linken und rechten Rand nicht angeben - es gibt keinen "Rand" im Android-Layout, nur das Auffüllen. Aber ja, ich möchte, dass die obere und untere Polsterung gescrollt werden - das ist eine gute Möglichkeit, dies zu beschreiben.
Mick Byrne
Ich habe bereits mehrere Methoden ausprobiert und bin immer noch gescheitert. Ich habe einige Tricks zu tun, aber es wird schwieriger ... Sie setzen 2 benutzerdefinierte Objekte auf das Listenelement an der ersten und letzten Position. Und verwenden einen benutzerdefinierten Adapter für Erkennen Sie den Gegenstand und zeichnen Sie ihn anders (schmale Höhe und transparent)
Tek Yin
Ja ... darauf habe ich auch zurückgegriffen. Dies hat jedoch alle möglichen Komplikationen, da ich dann die Hintergrundfarbe in den Listenelementen und nicht in der Ansicht festlegen muss. Dies bedeutet, dass ich einen Effekt manuell hacken muss, um anzuzeigen, wann Sie auf Dinge getippt haben . Trotzdem für Ihre Hilfe ...
Mick Byrne
Gute Nachrichten. Ich habe die Lösung. Sie können addHeaderView (View v) für ListActivity verwenden. Rufen Sie einfach an getListView(). addHeaderView(capView)und getListView(). addHeaderView(botView) stellen Sie sicher, dass es aufgerufen wird, bevor Sie den Inhalt der Liste initialisieren, z. setListAdapter (Adapter);
Tek Yin

Antworten:

397

Sie schrieben:

Ich habe versucht, der ListView selbst eine Auffüllung hinzuzufügen, aber wenn Sie durch die Liste scrollen, verschwindet sie unter dem Rand der Auffüllung.

Setzen Sie das ListView's clipToPaddingAttribut auf false. Dadurch können Sie das Polster auffüllen ListView und zum Ende des Layouts (und nicht nur zum Rand des Polsters) scrollen.

Ein Beispiel:

<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:clipToPaddingist ein XML-Attribut von ViewGroup, der Basisklasse für Layouts und Ansichtscontainer.

Der zugehörige Methodenaufruf lautet:

public void setClipToPadding (boolean clipToPadding)
Gunnar Karlsson
quelle
4
Zusätzlich kann dies über<item name="android:clipToPadding">false</item>
pjco
2
Oh, das gilt auch für ScrollView
pjco
4
Etwas spät zur Diskussion, aber beachten Sie, dass auf älteren Geräten (ich habe es auf einigen 2.3.x-Geräten entdeckt) Listenelementansichten zu früh wiederverwendet werden. Während die Zeichenphase weiß, dass sie dort zeichnen kann, ist dies bei der Layoutphase nicht der Fall, sodass das Objekt bereits außerhalb des Bildschirms angezeigt wird. Siehe stackoverflow.com/questions/15915226/… .
Jeffrey Klardie
@JeffreyKlardie Ich habe das Problem, dass Artikel auf älteren Geräten zu früh recycelt werden und die Bildlaufleiste sich sogar im Handumdrehen in der Größe ändert, was wirklich komisch aussieht. @pjco Ich bin mir nicht sicher warum, aber das Setzen clipToPaddingüber einen Stil funktioniert bei mir nicht. Es ist so, als würde es nicht angewendet. Wenn ich es jedoch direkt in der ListView einstelle, funktioniert es.
ForceMagic
5
Vergessen Sie nicht, android:scrollbarStyle="outsideOverlay"dass die Bildlaufleiste auch die gesamte Polsterung
durchläuft
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);

Die obige ListView hat eine Kopf- und Fußzeile von 20 Pixel.

Jake Wilson
quelle
4
Danke für die Antwort! Funktioniert super!! Wenn Sie die Höhe in dp float mDensity = getResources().getDisplayMetrics().density; int height = (int) (50 * mDensity + 0.5f); padding.setHeight(height);
eingeben
3
Oder noch besser: Abrufen von Dimensionen in dp auf Java-Ebene mit getResources (). GetDimensionPixelOffset (R.dimen.some_value);
Greg7gkb
1
Wirklich erstaunt darüber, wie viel Android-Zeug ich auf StackOverflow gegen die auf der Entwicklerseite
gelernten
1
Oder noch besser(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 100, getResources().getDisplayMetrics());
Eugen Pechanec
1
In API 23 gibt es keine Methode "setHeight ()" für View. Stattdessen können wir "setMinimumHeight ()" verwenden.
KWA
10

Anhang zu @ Jakobuds Antwort ...

Meine listView nutzte die android:divider/android:dividerHeightEigenschaften bereits, um transparente Lücken zwischen listView-Elementen zu erstellen. Dadurch konnte ich einfach die Eigenschaften und hinzufügen android:headerDividersEnabledund android:footerDividersEnableddie Kopf- und Fußzeilenansichten auf setzen new View(Activity.this).

Leichte Vereinfachung für Fälle, in denen bereits Teiler in der listView eingerichtet sind.

greg7gkb
quelle
1
Ich würde jedem raten, wenn möglich Trennwände anstelle von Artikelrändern und Polstern zu verwenden. Tolle Antwort
dzsonni
2

Meine Lösung mit a ListFragmentbasiert auf den Lösungen von @Jakobud und @ 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);
Hleinon
quelle
1

Die Antwort von @Gunnar Karlsson ist gut, hat jedoch das Problem, dass Zellansichten vorzeitig recycelt werden, wenn sie sich vollständig hinter der Polsterung befinden, aber noch nicht vollständig vom Bildschirm entfernt sind. Das Setzen von clipToPadding = false ist dafür verantwortlich und kann in einer zukünftigen Android-Version behoben werden oder nicht. ( Wenn Sie clipToPadding in ListView verwenden, werden die Elemente vorzeitig recycelt. )

Ich habe eine schöne einfache Lösung ohne Nebenwirkungen:

  1. Fügen Sie Ihrer cell_design.xml ein äußeres (lineares oder relatives) Layout hinzu
  2. Fügen Sie in diesem äußeren Layout einen Abstand (dh 10 Dip) hinzu, um einen "Rand" um die gesamte Zelle zu erstellen. (Hinweis: Nur die Polsterung funktioniert, nicht der Rand des äußeren Layouts.)
  3. Auf dem ListView-Set android:dividerHeight="-10dip"das Gegenteil von dem, was sich um die Zelle herum befindet

Im Vergleich zur anderen Antwort muss die Teilerfarbe nicht eingestellt werden. Die Polsterung an den obersten und untersten Zellen ist vorhanden, und der negative Teiler verhindert Teiler mit doppelter Höhe dazwischen.

James
quelle
"ohne Nebenwirkungen" ist das nicht ganz richtig. Das Hinzufügen einer weiteren Ebene in Ihrer Ansichtshierarchie, insbesondere in einem Listenansichtselement, bedeutet eine Verschlechterung der Leistung.
Teovald