Почему элементы ListView не растут, чтобы обернуть их содержимое?
У меня довольно сложный ListView с переменной высотой элемента списка. При определенных условиях мне нужно отобразить дополнительное представление в элементе списка, который по умолчанию скрыт (View.GONE). Включив его (View.VISIBLE), элемент списка растет по высоте (или, по крайней мере, он должен).
Проблема:
Несмотря на то, что я объявляю макет корня элемента wrap_content и каждый компонент в элементе fill_parent, представление, которое я скрываю/показываю, которое должно изменить высоту элемента, просто обрезается внизу, а не его родителем (макет элемента) растущий в высоту, чтобы полностью отобразить его.
Есть ли какие-либо ошибки, связанные с ListViews и макетами элементов и высотой элемента, которые я, возможно, пропустил?
Дополнительные наблюдения:
В целях тестирования я теперь уменьшил макет элемента списка, чтобы просто добавить корень LinearLayout и ImageView. Когда я устанавливаю высоту LinearLayout, например, 200dip и ImageView для fill_parent, я бы ожидал, что ImageView будет расти до тех пор, пока он не достигнет предела 200dip, установленного его родителем.
Однако вместо этого изображение будет только высотой, чем его растровый ресурс (как если бы я установил его для wrap_content), и весь элемент списка будет иметь одинаковую высоту (то есть, как если бы я установил его в wrap_content, тоже).
Если, однако, я устанавливаю высоту изображения, например. 200dip, тогда элемент списка будет расти в высоту, и будет также макет элемента.
Другими словами, layout_height макета элемента списка полностью игнорируется, и поэтому любое значение высоты изображения в ImageView отличается от значения жесткого кодированного пикселя.
Ответы
Ответ 1
Мне удалось это исправить, но я не понимаю, почему.
Как я уже упоминал, я установил layout_height
в макете элемента списка wrap_content
(поскольку fill_parent
здесь не имеет смысла, учитывая, что ListView бесконечно высокий).
Однако я установил layout_height
всех видов внутри этого макета на fill_parent
. Проблема исчезла при установке на них wrap_content
.
Это вызывает еще два вопроса:
1) Какова семантика представления с запросом fill_parent
, когда родительский wraps_content
? Какой запрос размера имеет приоритет?
2) Как бы мне сделать вид, чтобы заполнить элемент списка, если fill_parent
, по-видимому, не работает?
Спасибо за ваши ребята.
Ответ 2
Попробуйте следующее:
http://www.java2s.com/Code/Android/UI/setListViewHeightBasedOnChildren.htm
public class Utils {
public static void setListViewHeightBasedOnChildren(ListView listView) {
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) {
// pre-condition
return;
}
int totalHeight = 0;
for (int i = 0; i < listAdapter.getCount(); i++) {
View listItem = listAdapter.getView(i, null, listView);
listItem.measure(0, 0);
totalHeight += listItem.getMeasuredHeight();
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
listView.setLayoutParams(params);
listView.requestLayout();
}
}
Ответ 3
Как вы накачиваете свои строки?
Если вы не используете его прямо сейчас, попробуйте использовать LayoutInflater#inflate(layoutId, parent, false)
(где parent
- это AdapterView
, предоставленный getView()
или newView()
):
v = getLayoutInflater().inflate(R.layout.list_item, parent, false);
Ответ 4
Проблемы с макетом могут быть вызваны тем, что ScrollView является оберткой
Я наткнулся на какую-то заметку в
http://developer.android.com/reference/android/widget/ExpandableListView.html
"... Примечание. Вы не можете использовать значение wrap_content для атрибута android: layout_height ExpandableListView в XML, если размер родителя также не определен строго (например, если родительский элемент был ScrollView, вы не можете указать wrap_content, поскольку он также может быть любой длины. Однако вы можете использовать wrap_content, если родитель ExpandableListView имеет определенный размер, например 100 пикселей.
Я удалил обертку. ScrollView и линейный макет начали работать исправно. Теперь его только понять, как обернуть материал в ScrollView. Помоги мне Бог
Но в любом случае это действительно странное поведение. Я думаю, что fill_parent - это не совсем правильная формулировка. При использовании инструмента heirarchyviewer я всегда вижу значения WRAP_CONTENT и MATCH_PARENT для layout_width и leayout_height. Так что, вероятно, fill_parent на самом деле означает match_parent, что ставит меня в когнитивный диссонанс.
Ответ 5
Я использую "AbsListView.LayoutParams" для настройки ширины и высоты вручную внутри "Adapter.getView()".
Ответ 6
Если вы используете пользовательский View
в качестве элемента списка, размер которого изменяется, вы можете взять ответ PeBek и сделать это, когда вы построите View
addOnLayoutChangeListener(
new OnLayoutChangeListener() {
@Override
public void onLayoutChange(View _, int __, int ___, int ____, int bottom, int _____, int ______,
int _______, int old_bottom) {
final ListView list_view = (ListView) getParent();
final ViewGroup.LayoutParams params = list_view.getLayoutParams();
params.height += bottom - old_bottom;
list_view.setLayoutParams(params);
list_view.requestLayout();
}
});
Когда размер View
будет изменен, этот метод обратного вызова будет запущен, и он обновит высоту ListView
, чтобы включить изменение высоты (дно треугольника). Другие значения, если они окажутся полезными для вас, - это View
(ссылка на представление), left
, top
, right
, bottom
, old_left
, old_top
, old_right
, old_bottom
. Он работает для расширения и свертывания представления.
API 11 требуется для OnLayoutChangeListener
, не знаю, есть ли способ, совместимый с обратной совместимостью.
Ответ 7
У меня была та же проблема: я хотел бы иметь список внутри своей деятельности, который заполняет весь экран, когда устройство находится в вертикальном положении, чем в горизонтальной ориентации.
Я решаю проблему, используя al Linear Layout, которые имеют высоту, которая должна заполнять_parent, и устанавливая высоту элемента в списке на 0dp, в то время как layout_weight устанавливается на 1.
android:layout_weight="1"
android:layout_height="0dp"
Ответ 8
это работает для меня
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="@dimen/activity_vertical_margin">
<TextView
android:id="@+id/tv_status"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="17sp"
android:text="@string/text_list_devices" />
<ListView
android:id="@+id/lv_paired"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/activity_vertical_margin"
android:cacheColorHint="#00000000"
android:layout_above="@+id/signup_t"
android:layout_below="@id/tv_status"
/>
<Button
android:id="@+id/signup_t"
style="?android:textAppearanceSmall"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:textColor="@android:color/white"
android:layout_alignParentBottom="true"
android:text="Print All Records"
android:typeface="sans"
android:layout_marginLeft="45dp"
android:layout_marginRight="45dp"
android:textSize="24sp"
android:background="@drawable/selector_for_button"
android:textStyle="bold" />
</RelativeLayout>