Добавьте поле над верхним элементом ListView (и ниже последнего) в Android

147

Это довольно хороший вопрос о расположении элементов в ListView в Android.

У меня есть активность с заголовком вверху и ListView, занимающим остальную часть экрана. Я хочу, чтобы мой ListView отображался с отступом 10dp слева, справа и сверху, но когда вы прокручиваете ListView вверх, я хочу, чтобы он покрывал верхний отступ 10dp, прежде чем исчезнуть под выцветшим краем. Точно так же, когда вы прокручиваете до конца, последний элемент списка должен отображаться с 10dp между нижней частью последнего элемента списка и фактической нижней частью экрана (если вам интересно, почему, это потому, что мне нужно красивое фоновое изображение) ковыряться вокруг ListView).

Я попытался добавить заполнение к самому ListView, но затем, когда вы прокручиваете список, он исчезает под краем заполнения.

Я из сети веб-разработчиков, и аналогия была бы в том, чтобы добавить поле выше первого элемента списка (и ниже последнего элемента списка).

Мик Бирн
источник
укажите только левый и правый поля ... попробуйте вставить свой xml здесь, чтобы я мог увидеть проблему edit: подождите, вы имеете в виду .... Вы хотите, чтобы верхний и нижний отступы тоже прокручивались?
Тек Инь
Я не могу указать левое и правое поле - в макете Android нет «поля», только отступы. Но да, я хочу, чтобы верхний и нижний отступы прокручивались - это хороший способ описать это.
Мик Бирн
Я уже попробовал несколько методов, но все еще не смог .. У меня есть некоторые уловки, но это будет труднее сделать, хотя ... вы помещаете 2 пользовательских объекта в элемент списка в первой и последней позиции ... и используете пользовательский адаптер для обнаружить предмет и нарисовать его по-другому (узкая высота и прозрачность)
Tek Yin
Да ... это то, к чему я тоже хотел вернуться. Но с этим есть много разных сложностей, так как мне нужно будет установить цвет фона в элементах списка, а не в представлении, а это значит, что мне нужно будет вручную взломать какой-то эффект, чтобы показать, когда вы нажали , В любом случае, спасибо за вашу помощь ...
Мик Бирн
Хорошие новости ... У меня есть решение ... вы можете использовать addHeaderView (View v) в ListActivity .. просто позвоните getListView(). addHeaderView(capView)и getListView(). addHeaderView(botView) убедитесь, что он вызывается , прежде чем инициализировать содержимое списка, например. setListAdapter (адаптер);
Тек Инь

Ответы:

397

Вы написали:

Я попытался добавить заполнение к самому ListView, но затем, когда вы прокручиваете список, он исчезает под краем заполнения.

Установить ListView's clipToPaddingатрибут в false. Это включит заполнение вокруг ListView и прокрутку до конца макета (а не только до края отступа).

Пример:

<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:clipToPaddingявляется атрибутом XML ViewGroupбазового класса для контейнеров макетов и представлений.

Связанный вызов метода :

public void setClipToPadding (boolean clipToPadding)
Гуннар Карлссон
источник
4
Кроме того, это может быть сделано в стиле или теме через<item name="android:clipToPadding">false</item>
pjco
2
О, это относится и к ScrollView
pjco
4
Немного опоздал к обсуждению, но учтите, что на старых устройствах (я заметил это на некоторых устройствах 2.3.x) представления элементов списка перезапускаются слишком рано. В то время как фаза рисования знает, что она может рисовать там, а фаза макета - нет, поэтому она думает, что элемент уже за кадром. См. Stackoverflow.com/questions/15915226/… .
Джеффри Кларди
@JeffreyKlardie Я сталкиваюсь с проблемой, когда предметы перерабатываются слишком рано на старом устройстве, и это даже заставляет полосу прокрутки изменять размер на лету, что выглядит действительно странно. @pjco Я не уверен, почему, но настройка clipToPaddingчерез стиль не работает для меня, это как если бы он не применялся. Хотя, если я установлю это непосредственно на ListView, это работает.
ForceMagic
5
Не забывайте, android:scrollbarStyle="outsideOverlay"что полоса прокрутки проходит и через отступы
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);

Приведенный выше ListView будет иметь отступ верхнего и нижнего колонтитула 20 пикселей.

Джейк Уилсон
источник
4
Спасибо за ответ! Прекрасно работает!! Если вы хотите float mDensity = getResources().getDisplayMetrics().density; int height = (int) (50 * mDensity + 0.5f); padding.setHeight(height);
указать
3
Или, что еще лучше, получить измерения в dp на уровне Java с помощью getResources (). GetDimensionPixelOffset (R.dimen.some_value);
greg7gkb
1
По-настоящему удивлен тем, сколько Android-материалов я изучаю в StackOverflow против тех, которые я изучаю на сайте разработчиков
TrueCoke,
1
Или еще лучше(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 100, getResources().getDisplayMetrics());
Евгений Печанец,
1
Не существует метода "setHeight ()" для View в API 23. Вместо этого мы можем использовать "setMinimumHeight ()".
KWA
10

Приложение к ответу @ Якобуда ...

Мой listView уже использовал android:divider/android:dividerHeightсвойства для создания прозрачных промежутков между элементами listView. Это позволило мне просто добавить android:headerDividersEnabledи android:footerDividersEnabledсвойства и установить точку заголовка и нижнего колонтитула new View(Activity.this).

Небольшое упрощение для случаев, когда у вас уже есть настройка делителей в listView.

greg7gkb
источник
1
Я бы посоветовал всем, где это возможно, использовать разделители вместо полей элементов и отступов. Отличный ответ
дзсонни
2

Мое решение, использующее a ListFragment, основано на решениях @Jakobud и @ 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
источник
1

Ответ @Gunnar Karlsson хорош, но есть проблема преждевременной переработки видов ячеек, когда они полностью находятся за отступом, но еще не полностью за кадром. За это отвечает параметр clipToPadding = false, который может быть исправлен или не исправлен в будущей версии Android. ( При использовании clipToPadding в ListView элементы преждевременно перерабатываются )

У меня есть хорошее простое решение без побочных эффектов:

  1. Добавьте внешний (линейный или относительный) макет в свой cell_design.xml
  2. На этом внешнем макете добавьте отступ (т.е. 10dip), чтобы создать «поле» вокруг всей ячейки. (NB будет работать только отступ, а не отступ на внешнем макете)
  3. На множестве ListView android:dividerHeight="-10dip", противоположное тому, что находится вокруг ячейки

По сравнению с другим ответом нет необходимости устанавливать цвет делителя. Будет присутствовать заполнение в самой верхней и самой нижней ячейках, а отрицательный делитель предотвратит двойные делители высоты между ними.

Джеймс
источник
«без побочных эффектов», это не совсем так. Добавление еще одного слоя в иерархию представлений, особенно в элемент списка, означает снижение производительности.
Теовальд