Dodaj margines nad górnym elementem ListView (i poniżej ostatniego) w systemie Android

147

To całkiem dobre pytanie dotyczące układu elementów w ListView w systemie Android.

Mam działanie z paskiem tytułu u góry i ListView zajmującym resztę ekranu. Chcę, aby mój ListView pojawił się z dopełnieniem 10dp po lewej, prawej i u góry, ale kiedy przewiniesz ListView w górę, chcę, aby obejmował górne wypełnienie 10dp, zanim zniknie pod wyblakłą krawędzią. Podobnie, kiedy przewiniesz do dołu, ostatni element listy powinien pojawić się z 10 dp między dolną częścią ostatniej pozycji listy a faktycznym dolną częścią ekranu (jeśli zastanawiasz się, dlaczego, to dlatego, że jest ładny obraz tła, który chcę przeglądając ListView).

Próbowałem dodać dopełnienie do samego ListView, ale kiedy przewijasz listę, znika ona pod krawędzią wypełnienia.

Jestem twórcą stron internetowych i analogią byłoby dodanie marginesu powyżej pierwszej pozycji listy (i poniżej ostatniej pozycji listy).

Mick Byrne
źródło
określ tylko lewy i prawy margines ... spróbuj wkleić tutaj swój xml, aby zobaczyć problem edytuj: czekaj, masz na myśli ... Chcesz, aby górne i dolne wypełnienie również zostało przewinięte?
Tek Yin
Nie mogę określić lewego i prawego marginesu - w układzie Androida nie ma „marginesu”, tylko wypełnienie. Ale tak, chcę, żeby górne i dolne wypełnienie było przewijane - to dobry sposób na opisanie tego.
Mick Byrne
Wypróbowałem już kilka metod i nadal zawiodłem. Mam kilka sztuczek do zrobienia, ale będzie to trudniejsze ... umieszczasz 2 obiekty niestandardowe w pozycji listy na pierwszej i ostatniej pozycji ... i używasz niestandardowego adaptera do wykryj przedmiot i narysuj go inaczej (wąska wysokość i przezroczystość)
Tek Yin
Tak ... to jest to, o czym myślałem, żeby się wycofać. Ale jest z tym wiele komplikacji, ponieważ będę musiał wtedy ustawić kolor tła w elementach listy, a nie widok, co oznacza, że ​​będę musiał ręcznie zhakować w pewnym efekcie, aby pokazać, kiedy dotkniesz rzeczy . W każdym razie dziękuję za pomoc ...
Mick Byrne
Dobra wiadomość .. Mam rozwiązanie ... możesz użyć addHeaderView (View v) na ListActivity .. po prostu zadzwoń getListView(). addHeaderView(capView)i getListView(). addHeaderView(botView) upewnij się, że zostało wywołane przed zainicjalizowaniem zawartości listy np. setListAdapter (adapter);
Tek Yin

Odpowiedzi:

397

Napisałeś:

Próbowałem dodać dopełnienie do samego ListView, ale kiedy przewijasz listę, znika ona pod krawędzią wypełnienia.

Ustaw ListView's clipToPaddingatrybut na false. Umożliwi to dopełnienie ListView i przewijanie do końca układu (a nie tylko do krawędzi wypełnienia).

Przykład:

<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:clipToPaddingjest atrybutem XML ViewGroup, klasą bazową dla kontenerów układów i widoków.

Powiązane wywołanie metody to:

public void setClipToPadding (boolean clipToPadding)
Gunnar Karlsson
źródło
4
Dodatkowo można to przekształcić w styl lub motyw za pośrednictwem<item name="android:clipToPadding">false</item>
pjco
2
Och, dotyczy to również
ScrollView
4
Trochę późno na dyskusję, ale zauważ, że na starszych urządzeniach (zauważyłem to na niektórych urządzeniach 2.3.x), widoki elementów listy są zbyt szybko przetwarzane. Podczas gdy faza rysowania wie, że może tam rysować, faza układu nie, więc uważa, że ​​element jest już poza ekranem. Zobacz stackoverflow.com/questions/15915226/… .
Jeffrey Klardie
@JeffreyKlardie Napotykam problem polegający na tym, że przedmioty są zbyt wcześnie poddawane recyklingowi na starszym urządzeniu, a nawet powoduje, że pasek przewijania zmienia rozmiar w locie, co wygląda naprawdę dziwnie. @pjco Nie jestem pewien, dlaczego, ale ustawienie clipToPaddingza pomocą stylu nie działa dla mnie, to tak, jakby nie zostało zastosowane. Chociaż, jeśli ustawię to bezpośrednio w ListView, to działa.
ForceMagic
5
Nie zapomnij android:scrollbarStyle="outsideOverlay", że pasek przewijania przechodzi również przez wypełnienie
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);

Powyższy ListView będzie miał wypełnienie nagłówka i stopki w wysokości 20 pikseli.

Jake Wilson
źródło
4
Dziękuję za odpowiedź! Działa świetnie!! Jeśli chcesz podać wysokość w dp, możesz to zrobić za pomocą DisplayMetrics: float mDensity = getResources().getDisplayMetrics().density; int height = (int) (50 * mDensity + 0.5f); padding.setHeight(height);
Tony Ceralva
3
Albo jeszcze lepiej, pobierz wymiary w dp na poziomie Java za pomocą metody getResources (). GetDimensionPixelOffset (R.dimen.some_value);
greg7gkb
1
Naprawdę zdumiony tym, ile rzeczy na Androida uczę się na StackOverflow w porównaniu z tymi, których uczę się na stronie programistów
TrueCoke,
1
Albo jeszcze lepiej(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 100, getResources().getDisplayMetrics());
Eugen Pechanec
1
Nie ma metody "setHeight ()" dla View w API 23. Zamiast tego możemy użyć "setMinimumHeight ()".
KWA,
10

Dodatek do odpowiedzi @ Jakobud ...

Mój listView już używał tych android:divider/android:dividerHeightwłaściwości do tworzenia przezroczystych przerw między elementami listView. To pozwoliło mi wystarczy dodać android:headerDividersEnabledi android:footerDividersEnabledwłaściwości i ustawić widoki nagłówek i stopkę do new View(Activity.this).

Nieznaczne uproszczenie w przypadkach, w których masz już skonfigurowane separatory w listView.

greg7gkb
źródło
1
Radziłbym każdemu, gdzie to możliwe, aby zamiast marginesów i dopełnień pozycji stosować separatory. Świetna odpowiedź
dzsonni
2

Moje rozwiązanie przy użyciu a ListFragment, oparte na rozwiązaniach @Jakobud i @ 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
źródło
1

Odpowiedź @Gunnara Karlssona jest dobra, ale występuje problem z przedwczesnym odtwarzaniem widoków komórek, gdy są one całkowicie za wyściółką, ale jeszcze nie całkowicie poza ekranem. Odpowiedzialne za to jest ustawienie clipToPadding = false i może, ale nie musi, zostać naprawione w przyszłej wersji Androida ( podczas używania clipToPadding w ListView elementy są przedwcześnie poddawane recyklingowi )

Mam fajne proste rozwiązanie bez skutków ubocznych:

  1. Dodaj układ zewnętrzny (liniowy lub względny) do pliku cell_design.xml
  2. Na tym zewnętrznym układzie dodaj dopełnienie (np. 10dip), aby utworzyć „margines” wokół całej komórki. (Uwaga: tylko wypełnienie będzie działać, a nie margines na zewnętrznym układzie)
  3. W zestawie ListView android:dividerHeight="-10dip", przeciwieństwo tego, co znajduje się wokół komórki

W porównaniu z drugą odpowiedzią nie ma potrzeby ustawiania koloru separatora. Dopełnienie w komórkach najwyższych i najniższych będzie obecne, a ujemny dzielnik zapobiegnie podwójnemu podziałowi wysokości pomiędzy.

James
źródło
„bez skutków ubocznych” to nie do końca prawda. Dodanie kolejnej warstwy w hierarchii widoków, szczególnie w elemencie widoku listy, oznacza obniżenie wydajności.
Teovald