Использование ListAdapter для заполнения LinearLayout внутри макета ScrollView
Я столкнулся с очень распространенной проблемой:
Я выложил активность, и теперь выясняется, что в этом ScrollView
должно отображаться несколько элементов. Обычный способ сделать это - использовать существующий ListAdapter
, подключить его к ListView
и BOOM. У меня будет список элементов.
НО Вы не должны размещать вложенные ListView
в ScrollView
, поскольку он закручивает прокрутку - даже Android Lint жалуется на это.
Итак, вот мой вопрос:
Как подключить ListAdapter
к LinearLayout
или что-то подобное?
Я знаю, что это решение не будет масштабироваться для большого количества элементов, но мои списки очень короткие (< 10 элементов), поэтому повторное использование представлений не требуется. Производительность мудрый я могу жить с размещением всех представлений непосредственно в LinearLayout
.
Одно из решений, которое я придумал, - разместить мой существующий макет действий в секции headerView ListView
. Но это похоже на злоупотребление этим механизмом, поэтому я ищу более чистое решение.
Идеи?
ОБНОВЛЕНИЕ: Чтобы вдохновить в правильном направлении, я добавляю образец макета, чтобы показать свою проблему:
<?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>
ОБНОВЛЕНИЕ 2 Я изменил заголовок, чтобы его было легче понять (получило downvote, doh!).
Ответы
Ответ 1
Вероятно, вы должны просто вручную добавить свои элементы в 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);
}
РЕДАКТИРОВАТЬ. Я отклонил этот подход, когда мне нужно было отображать около 200 нетривиальных элементов списка, это очень медленно - для Nexus 4 потребовалось около 2 секунд, чтобы отобразить мой "список", что было неприемлемо, Поэтому я обратился к Flo с заголовками. Он работает намного быстрее, потому что представления списков создаются по требованию, когда пользователь прокручивает, а не во время создания представления.
Резюме.. Ручное добавление представлений в макет проще кодировать (таким образом, потенциально менее подвижные части и ошибки), но страдает от проблем с производительностью, поэтому, если у вас есть 50 просмотров или более, я советуем использовать подход заголовка.
Пример. В основном макет активности (или фрагмента) преобразуется в нечто подобное (больше не требуется ScrollView):
<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"/>
Затем в onCreateView()
(я буду использовать пример с фрагментом) вам нужно добавить представление заголовка, а затем установить адаптер (я предполагаю, что идентификатор ресурса заголовка 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 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.
}
}
});
Ответ 2
Я бы придерживался решения просмотра заголовка. В этом нет ничего плохого. В настоящий момент я реализую деятельность с использованием того же подхода.
Очевидно, что "элемент детали" более динамичен, чем статический (изменение количества элементов по сравнению с количеством элементов фида и т.д.), иначе вы вообще не будете думать об использовании адаптера. Поэтому, когда вам нужен адаптер, используйте ListView.
Реализация решения, которое заполняет LinearLayout из адаптера, в конечном итоге не что иное, как создание ListView с пользовательским макетом.
Только мои 2 цента.
Ответ 3
Установите свой вид на main.xml onCreate, затем надуйте его из row.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>
row.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>