Używanie Listadaptera do wypełniania liniowości wewnątrz układu przewijania
Mam do czynienia z bardzo częstym problemem:
Ustawiłem aktywność i teraz okazuje się, że powinna ona wyświetlać kilka pozycji w tym ScrollView
. Normalnym sposobem na to byłoby użycie istniejącego ListAdapter
, podłączenie go do ListView
i BOOM miałbym swoją listę przedmiotów.
Ale nie powinieneś umieszczać zagnieżdżonego ListView
w ScrollView
, ponieważ psuje przewijanie-nawet Android Lint narzeka na to.
Oto moje pytanie:
Jak podłączyć ListAdapter
do Czy coś podobnego?
Wiem, że to rozwiązanie nie będzie skalowane dla wielu pozycji, ale moje listy są bardzo krótkie (LinearLayout.
Jednym z rozwiązań, które wymyśliłem, byłoby umieszczenie mojego istniejącego układu aktywności w sekcji widoku nagłówka ListView
. Ale to wygląda jak nadużywanie tego mechanizmu, więc szukam czyściciela rozwiązanie.
Pomysły?
UPDATE: aby zainspirować właściwy kierunek dodaję przykładowy layout, aby pokazać mój problem:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/news_detail_layout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:visibility="visible">
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#FFF"
>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:paddingLeft="@dimen/news_detail_layout_side_padding"
android:paddingRight="@dimen/news_detail_layout_side_padding"
android:paddingTop="@dimen/news_detail_layout_vertical_padding"
android:paddingBottom="@dimen/news_detail_layout_vertical_padding"
>
<TextView
android:id="@+id/news_detail_date"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:gravity="center_horizontal"
android:text="LALALA"
android:textSize="@dimen/news_detail_date_height"
android:textColor="@color/font_black"
/>
<Gallery
android:id="@+id/news_detail_image"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:paddingTop="5dip"
android:paddingBottom="5dip"
/>
<TextView
android:id="@+id/news_detail_headline"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:gravity="center_horizontal"
android:text="Some awesome headline"
android:textSize="@dimen/news_detail_headline_height"
android:textColor="@color/font_black"
android:paddingTop="@dimen/news_detail_headline_paddingTop"
android:paddingBottom="@dimen/news_detail_headline_paddingBottom"
/>
<TextView
android:id="@+id/news_detail_content"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:text="Here comes a lot of text so the scrollview is really needed."
android:textSize="@dimen/news_detail_content_height"
android:textColor="@color/font_black"
/>
<!---
HERE I NEED THE LIST OF ITEMS PROVIDED BY THE EXISTING ADAPTER.
They should be positioned at the end of the content, so making the scrollview smaller is not an option.
---->
</LinearLayout>
</ScrollView>
</LinearLayout>
UPDATE 2 zmieniłem nagłówek, aby ułatwić zrozumienie (mam negatywną opinię, doh!).
4 answers
Prawdopodobnie powinieneś po prostu ręcznie dodać swoje pozycje do LinearLayout
:
LinearLayout layout = ... // Your linear layout.
ListAdapter adapter = ... // Your adapter.
final int adapterCount = adapter.getCount();
for (int i = 0; i < adapterCount; i++) {
View item = adapter.getView(i, null, null);
layout.addView(item);
}
EDIT : odrzuciłem to podejście, gdy musiałem wyświetlić około 200 nietrywialnych elementów listy, jest to bardzo powolne - Nexus 4 potrzebował około 2 sekund, aby wyświetlić moją "listę", co było nie do przyjęcia. Zwróciłem się więc do podejścia Flo z nagłówkami. Działa to znacznie szybciej, ponieważ widoki list są tworzone na żądanie podczas przewijania przez użytkownika, a nie w momencie tworzenia widoku.
Resume: ręczne dodawanie widoki do układu są łatwiejsze do kodowania (potencjalnie mniej ruchomych części i błędów), ale cierpi na problemy z wydajnością, więc jeśli masz jakieś 50 widoków lub więcej, radzę użyć podejścia nagłówka.
Przykład. Zasadniczo układ aktywności (lub fragmentu) przekształca się w coś takiego (nie jest już potrzebny widok przewijania):
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/my_top_layout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
Następnie w onCreateView()
(użyję przykładu z fragmentem) musisz dodać Widok nagłówka, a następnie ustawić adapter (zakładam, że identyfikator zasobu nagłówka jest header_layout
):
ListView listView = (ListView) inflater.inflate(R.layout.my_top_layout, container, false);
View header = inflater.inflate(R.layout.header_layout, null);
// Initialize your header here.
listView.addHeaderView(header, null, false);
BaseAdapter adapter = // ... Initialize your adapter.
listView.setAdapter(adapter);
// Just as a bonus - if you want to do something with your list items:
view.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// You can just use listView instead of parent casted to ListView.
if (position >= ((ListView) parent).getHeaderViewsCount()) {
// Note the usage of getItemAtPosition() instead of adapter's getItem() because
// the latter does not take into account the header (which has position 0).
Object obj = parent.getItemAtPosition(position);
// Do something with your object.
}
}
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-05 07:04:39
Trzymałbym się rozwiązania widoku nagłówka. Nie ma w tym nic złego. W tej chwili realizuję działanie przy użyciu dokładnie tego samego podejścia.
Oczywiście "część elementu" jest bardziej dynamiczna niż statyczna (zmienna liczba elementów vs.poprawiona liczba elementów itd.) w przeciwnym razie nie będziesz myślał o użyciu adaptera w ogóle. Więc kiedy potrzebujesz adaptera, użyj ListView.
Implementacja rozwiązania, które zapełnia LinearLayout z adaptera jest w końcu niczym innym jak Tworzenie widoku listy z niestandardowym układem.
Tylko moje 2 centy.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-13 12:10:43
Ustaw widok na główny.xml onCreate, a następnie napompować z wiersza.xml
Main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="450dp" >
<ListView
android:id="@+id/mainListView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_above="@+id/size"
android:layout_below="@+id/editText1"
android:gravity="fill_vertical|fill_horizontal"
android:horizontalSpacing="15dp"
android:isScrollContainer="true"
android:numColumns="1"
android:padding="5dp"
android:scrollbars="vertical"
android:smoothScrollbar="true"
android:stretchMode="columnWidth" >
</ListView>
<TextView
android:id="@+id/size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:background="#ff444444"
android:gravity="center"
android:text="TextView"
android:textColor="#D3D3D3"
android:textStyle="italic" />
</EditText>
</RelativeLayout>
Wiersz.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:paddingTop="3dp">
<TextView
android:id="@+id/rowTextView"
android:layout_width="0dip"
android:layout_height="41dp"
android:layout_margin="4dp"
android:layout_weight="2.83"
android:ellipsize="end"
android:gravity="center_vertical"
android:lines="1"
android:text="John Doe"
android:textColor="@color/color_white"
android:textSize="23dp" >
</TextView>
</LinearLayout>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-13 11:53:18
Używam poniższego kodu, który powtarza funkcjonalność adaptera z ViewGroup
i TabLayout
. Dobrą rzeczą jest to, że jeśli zmienisz listę i ponownie połączysz, wpłynie to tylko na zmienione elementy:
Użycie:
val list = mutableListOf<Person>()
layout.bindChildren(list, { it.personId }, { bindView(it) }, {d, t ->bindView(d, t)})
list.removeAt(0)
list+=newPerson
layout.bindChildren(list, { it.personId }, { bindView(it) }, {d, t ->bindView(d, t)})
Dla ViewGroups
:
fun <Item, Key> ViewGroup.bindChildren(items: List<Item>, id: (Item) -> Key, view: (Item) -> View, bind: (Item, View) -> Unit) {
val old = children.map { it.tag as Key }.toList().filter { it != null }
val new = items.map(id)
val add = new - old
val remove = old - new
val keep = new.intersect(old)
val tagToChildren = children.associateBy { it.tag as Key }
val idToItem = items.associateBy(id)
remove.forEach { tagToChildren[it].let { removeView(it) } }
keep.forEach { bind(idToItem[it]!!, tagToChildren[it]!!) }
add.forEach { id -> view(idToItem[id]!!).also { it.tag = id }.also { addView(it, items.indexOf(idToItem[id])) } }
}
Dla TabLayout
mam to:
fun <Item, Key> TabLayout.bindTabs(items: List<Item>, toKey: (Item) -> Key, tab: (Item) -> TabLayout.Tab, bind: (Item, TabLayout.Tab) -> Unit) {
val old = (0 until tabCount).map { getTabAt(it)?.tag as Key }
val new = items.map(toKey)
val add = new - old
val remove = old - new
val keep = new.intersect(old)
val tagToChildren = (0 until tabCount).map { getTabAt(it) }.associateBy { it?.tag as Key }
val idToItem = items.associateBy(toKey)
remove.forEach { tagToChildren[it].let { removeTab(it) } }
keep.forEach { bind(idToItem[it]!!, tagToChildren[it]!!) }
add.forEach { key -> tab(idToItem[key]!!).also { it.tag = key }.also { addTab(it, items.indexOf(idToItem[key])) } }
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-18 23:41:10