Szukałem rozwiązań tego problemu, a jedyną odpowiedzią, jaką mogę znaleźć, wydaje się być „ nie umieszczaj ListView w ScrollView ”. Mam jeszcze zobaczyć żadnego rzeczywistego wyjaśnienia , dlaczego mimo. Wydaje mi się, że jedynym powodem jest to, że Google uważa, że nie powinieneś tego robić. Cóż, tak zrobiłem.
Pytanie brzmi: w jaki sposób można umieścić ListView w ScrollView bez zwinięcia do jego minimalnej wysokości?
ListView
.ListView
może mieć wiele stylów wierszy oraz wiersze, których nie można wybrać.Odpowiedzi:
Używanie,
ListView
aby nie przewijało się, jest niezwykle drogie i jest sprzeczne z całym celemListView
. NIE powinieneś tego robić. Po prostu użyjLinearLayout
zamiast tego.źródło
How can I put a ListView into a ScrollView without it collapsing?
... Możesz powiedzieć, że nie powinieneś tego robić, ale także dać odpowiedź, jak to zrobić, to dobra odpowiedź. Wiesz, że ListView ma inne fajne funkcje oprócz przewijania, funkcje, których nie ma LinearLayout.Oto moje rozwiązanie. Jestem całkiem nowy na platformie Android i jestem pewien, że jest to trochę hack, szczególnie w części dotyczącej bezpośredniego wywoływania .measure i bezpośredniego ustawiania
LayoutParams.height
właściwości, ale działa.Wszystko, co musisz zrobić, to zadzwonić,
Utility.setListViewHeightBasedOnChildren(yourListView)
a zostanie on przeskalowany, aby dokładnie dopasować wysokość jego przedmiotów.źródło
LinearLayout
że nie ma wszystkich nieodłącznych elementówListView
- nie ma dzielników, widoków nagłówka / stopki, selektora listy, który pasuje do kolorów motywu interfejsu telefonu itp. Szczerze mówiąc, nie ma powodu, dla którego nie można przewijać wewnętrzny pojemnik, aż dotrze do końca, a następnie przestanie przechwytywać zdarzenia dotykowe, aby zewnętrzny pojemnik przewinął się. Każda przeglądarka stacjonarna robi to, gdy używasz kółka przewijania. Sam Android może obsługiwać przewijanie zagnieżdżone, jeśli poruszasz się po trackballu, więc dlaczego nie za pomocą dotyku?listItem.measure(0,0)
wyrzuci NPE, jeśli listItem jest instancją ViewGroup. Dodałem wcześniejlistItem.measure
:if (listItem instanceof ViewGroup) listItem.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
int totalHeight = listView.getPaddingTop() + listView.getPaddingBottom();
ListView
może zawierać elementy o zmiennej wysokości. Wezwanie dogetMeasuredHeight()
zwrócenia tylko docelowej minimalnej wysokości w przeciwieństwie do rzeczywistej wysokości. Próbowałem użyćgetHeight()
zamiast tego, ale zwraca 0. Czy ktoś ma wgląd w to, jak do tego podejść?To na pewno zadziała ............
Musisz po prostu zastąpić swój
<ScrollView ></ScrollView>
plik XML w układzie tymCustom ScrollView
podobnym<com.tmd.utils.VerticalScrollview > </com.tmd.utils.VerticalScrollview >
źródło
Zamiast wstawić do
ListView
środkaScrollView
, możemy użyćListView
jakoScrollView
. Rzeczy, które muszą być wListView
środku, można umieścić w środkuListView
. Inne układy na górze i na doleListView
można umieścić, dodając układy do nagłówka i stopkiListView
. CałośćListView
da ci przewijanie.źródło
Istnieje wiele sytuacji, w których sensowne jest posiadanie ListView w ScrollView.
Oto kod oparty na sugestii DougW ... działa we fragmencie, zajmuje mniej pamięci.
wywołanie setListViewHeightBasedOnChildren (widok listy) na każdym osadzonym widoku listy.
źródło
ListView może już mierzyć swoją wysokość, aby wyświetlić wszystkie elementy, ale nie robi tego, gdy po prostu określisz wrap_content (MeasureSpec.UNSPECIFIED). Zrobi to, gdy otrzyma wysokość z MeasureSpec.AT_MOST. Dzięki tej wiedzy możesz utworzyć bardzo prostą podklasę, aby rozwiązać ten problem, który działa o wiele lepiej niż którekolwiek z powyższych rozwiązań. Nadal powinieneś używać wrap_content z tą podklasą.
Manipulowanie heightMeasureSpec o wartości AT_MOST o bardzo dużym rozmiarze (Integer.MAX_VALUE >> 4) powoduje, że ListView mierzy wszystkie swoje potomne do podanej (bardzo dużej) wysokości i odpowiednio ustawia wysokość.
Działa to lepiej niż inne rozwiązania z kilku powodów:
Z drugiej strony, można argumentować, że robienie tego polega na nieudokumentowanym zachowaniu w zestawie SDK, które może ulec zmianie. Z drugiej strony można argumentować, że tak właśnie wrap_content powinien naprawdę współpracować z ListView i że bieżące zachowanie wrap_content jest po prostu zepsute.
Jeśli obawiasz się, że zachowanie może się zmienić w przyszłości, powinieneś po prostu skopiować funkcję onMeasure i powiązane funkcje z ListView.java do swojej własnej podklasy, a następnie wykonać ścieżkę AT_MOST przez uruchomienie onMeasure również dla NIEPECYFIKOWANEJ.
Nawiasem mówiąc, uważam, że jest to całkowicie poprawne podejście, gdy pracujesz z małą liczbą elementów listy. Może być nieefektywny w porównaniu do LinearLayout, ale gdy liczba elementów jest niewielka, użycie LinearLayout jest niepotrzebną optymalizacją, a zatem niepotrzebną złożonością.
źródło
Jest do tego wbudowane ustawienie. W ScrollView:
W Javie
Romain Guy wyjaśnia to dogłębnie tutaj: http://www.curious-creature.org/2010/08/15/scrollviews-handy-trick/
źródło
Tworzysz niestandardowy widok listy, którego nie można przewijać
W twoim pliku zasobów układu
W pliku Java
Utwórz obiekt swojego customListview zamiast ListView, na przykład: NonScrollListView non_scroll_list = (NonScrollListView) findViewById (R.id.lv_nonscroll_list);
źródło
Nie moglibyśmy użyć dwóch przewijanych jednocześnie. Otrzymamy całkowitą długość ListView i rozwiniemy listview o całkowitą wysokość. Następnie możemy dodać ListView w ScrollView bezpośrednio lub za pomocą LinearLayout, ponieważ ScrollView ma bezpośrednio jedno dziecko. skopiuj metodę setListViewHeightBasedOnChildren (lv) do swojego kodu i rozwiń widok listy, a następnie możesz użyć widoku listy w widoku przewijania. plik \ layout xml
Metoda onCreate w klasie Activity:
źródło
Jest to kombinacja odpowiedzi DougW, Good Guy Greg i Paul. Okazało się, że wszystko to było potrzebne, gdy próbowałem użyć tego z niestandardowym adapterem widoku listy i niestandardowymi elementami listy, w przeciwnym razie widok listy spowodował awarię aplikacji (również zawiesił się z odpowiedzią Nex):
źródło
Nie należy umieszczać ListView w ScrollView, ponieważ ListView już jest ScrollView. To byłoby jak umieszczenie ScrollView w ScrollView.
Co próbujesz osiągnąć
źródło
Przekształciłem @ DougW
Utility
na C # (używane w Xamarinie). Poniższe działa dobrze dla elementów o stałej wysokości na liście i będzie w większości w porządku, a przynajmniej dobry początek, jeśli tylko niektóre elementy będą nieco większe niż element standardowy.Dzięki @DougW, znalazłem się w trudnej sytuacji, kiedy musiałem pracować z Kodem Innych Ludzi. :-)
źródło
setListViewHeightBasedOnChildren()
metodę? Ponieważ nie działa to dla mnie cały czas.To jedyna rzecz, która działała dla mnie:
na Lollipop możesz używać
Włącz lub wyłącz przewijanie zagnieżdżone dla tego widoku, jeśli potrzebujesz wstecznej zgodności ze starszą wersją systemu operacyjnego, będziesz musiał użyć RecyclerView.
źródło
Wcześniej nie było to możliwe. Ale dzięki wydaniu nowych bibliotek Appcompat i bibliotek projektu można to osiągnąć.
Musisz tylko użyć NestedScrollView https://developer.android.com/reference/android/support/v4/widget/NestedScrollView.html
Nie wiem, czy będzie działać z Listview, czy nie, ale działa z RecyclerView.
Fragment kodu:
źródło
hej miałem podobny problem. Chciałem wyświetlić widok listy, który się nie przewijał, i stwierdziłem, że manipulowanie parametrami działało, ale było nieefektywne i zachowywałoby się inaczej na różnych urządzeniach. W rezultacie jest to fragment mojego kodu harmonogramu, który faktycznie robi to bardzo skutecznie .
Uwaga: jeśli go użyjesz,
notifyDataSetChanged();
nie będzie działać zgodnie z przeznaczeniem, ponieważ widoki nie zostaną przerysowane. Zrób to, jeśli potrzebujesz obejśćźródło
Istnieją dwa problemy podczas korzystania z ListView wewnątrz ScrollView.
1- ListView musi całkowicie rozwinąć się do wysokości swoich dzieci. ten ListView rozwiązuje to:
Wysokość dzielnika musi wynosić 0, zamiast tego użyj dopełnienia w rzędach.
2- ListView zużywa zdarzenia dotykowe, więc ScrollView nie może być przewijany jak zwykle. Ten ScrollView rozwiązuje ten problem:
To najlepszy sposób, w jaki znalazłem sposób na załatwienie sprawy!
źródło
Rozwiązaniem, którego używam jest dodanie całej zawartości ScrollView (co powinno być powyżej i pod listView) jakoViewView i FooterView w ListView.
Działa to tak, że konwersja konwersji jest sprawdzana tak, jak powinna być.
źródło
dzięki kodowi Vinaya tutaj jest mój kod, gdy nie możesz mieć widoku listy w widoku przewijania, ale potrzebujesz czegoś takiego
relativeLayout pozostaje w ScrollView, więc wszystko staje się przewijalne :)
źródło
Oto mała modyfikacja na @djunod jest odpowiedź , że muszę zrobić to działa perfekcyjnie:
źródło
spróbuj tego, to działa dla mnie, zapomniałem, gdzie to znalazłem, gdzieś w przepełnieniu stosu, nie jestem tutaj, aby wyjaśnić, dlaczego to nie działa, ale to jest odpowiedź :).
EDYCJA! W końcu dowiedziałem się, skąd mam kod. tutaj! : ListView wewnątrz ScrollView nie przewija się na Androidzie
źródło
Chociaż sugerowane metody setListViewHeightBasedOnChildren () działają w większości przypadków, w niektórych przypadkach, szczególnie z wieloma elementami, zauważyłem, że ostatnie elementy nie są wyświetlane. Dlatego postanowiłem naśladować prostą wersję zachowania ListView w celu ponownego użycia dowolnego kodu adaptera, oto alternatywa ListView:
źródło
Wszystkie te odpowiedzi są błędne !!! Jeśli próbujesz umieścić widok listy w widoku przewijania, powinieneś przemyśleć swój projekt. Próbujesz umieścić ScrollView w ScrollView. Ingerowanie w listę obniży wydajność listy. Tak właśnie zaprojektował Android.
Jeśli naprawdę chcesz, aby lista znajdowała się w tym samym przewijaniu co inne elementy, wszystko, co musisz zrobić, to dodać pozostałe elementy na górę listy za pomocą prostej instrukcji switch w adapterze:
Adapter listy może obsłużyć wszystko, ponieważ renderuje tylko to, co jest widoczne.
źródło
Ten cały problem zniknąłby, gdyby LinearLayout miał metodę setAdapter, ponieważ wtedy, gdy ktoś powiedziałby komuś, aby go używał, alternatywa byłaby trywialna.
Jeśli rzeczywiście chcesz przewijać ListView w innym przewijanym widoku, to nie pomoże, ale w przeciwnym razie da ci to przynajmniej pomysł.
Musisz utworzyć niestandardowy adapter, aby połączyć całą zawartość, którą chcesz przewinąć i ustawić na to adapter ListView.
Nie mam pod ręką przykładowego kodu, ale jeśli chcesz czegoś takiego.
Następnie musisz utworzyć adapter, który reprezentuje całą tę zawartość. ListView / Adaptery są wystarczająco inteligentne, aby obsługiwać różne typy, ale musisz sam napisać adapter.
Interfejs API interfejsu użytkownika Androida nie jest tak dojrzały jak prawie wszystko inne, więc nie ma takich samych subtelności jak inne platformy. Ponadto, robiąc coś na Androidzie, musisz być w trybie Android (unix), w którym oczekujesz, że aby zrobić cokolwiek, prawdopodobnie będziesz musiał zebrać funkcjonalność mniejszych części i napisać kilka własnych kodów, aby to zrobić praca.
źródło
Kiedy umieszczamy w
ListView
środkuScrollView
, powstają dwa problemy. JedenScrollView
mierzy swoje dzieci w trybie UNSPECIFIED, więcListView
ustawia własną wysokość, aby pomieścić tylko jeden element (nie wiem dlaczego), drugi mierzyScrollView
zdarzenie dotykowe, więcListView
się nie przewija.Ale można umieścić
ListView
wewnątrzScrollView
z jakiegoś obejścia. Ten post przeze mnie wyjaśnia to obejście. Dzięki temu obejściu możemy również zachowaćListView
funkcję recyklingu.źródło
Zamiast umieszczać widok listy w Widoku przewijania, umieść resztę treści między widokiem listy a otwarciem Widoku przewijania jako osobny widok i ustaw ten widok jako nagłówek widoku listy. Tak więc w końcu skończysz tylko widok listy przejmujący Scroll.
źródło
Ta biblioteka jest najłatwiejszym i najszybszym rozwiązaniem problemu.
źródło
Oto moja wersja kodu, która oblicza całkowitą wysokość widoku listy. Ten działa dla mnie:
źródło