如何在Android ListView中为内容设置padding而不改变ListView的高度?

37
我有一个ListView,里面有许多项。如何使顶部和底部的项目都具有10dp的上边距和下边距?我可以在ListView上使用padding或margin来实现这一点,但结果是当您滚动时,ListView的边缘现在距离屏幕底部有10dp的距离。有什么解决办法吗?我还尝试在适配器的getView方法中设置边距,但我没有看到AbsListView.LayoutParams的任何边距选项。任何帮助将不胜感激。

谢谢


1
有一个不太好的建议,但是第一个/最后一个项目视图如何添加顶部/底部填充?您需要在getView中检查并设置所有视图... - Knickedi
3个回答

128

关键是在视图定义中包含android:clipToPadding="false",例如:

<ListView android:id="@+id/list"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingTop="16dip"
    android:paddingBottom="16dip"
    android:clipToPadding="false" />

1
这正是我在寻找的,也是一个简单的解决方案。它可以正常工作,而且我正在针对Android 2.1-update1进行构建。 - Bobbake4
1
为什么只在Android 3.0及以上版本中可用?根据Android参考文档,此功能从一开始就存在(API Level 1):http://developer.android.com/reference/android/view/ViewGroup.html#setClipToPadding(boolean)。 - jenzz
哈哈,我花了45分钟尝试使用各种填充和边距设置来使它正常工作。甚至遇到了clipToPadding,但误解了它并将其设置为true :) 谢谢。 - Andrew G
终于找到一个可行的解决方案了,之前浪费了2-3个小时来弄清楚填充为什么工作得奇怪。;_; - OMi Shah

12

您可以通过使用标题和页脚在滚动区域内获取ListView顶部和底部的空间。以下是一个快速示例:

定义您的填充视图,我将其命名为header_footer.xml:

<?xml version="1.0" encoding="utf-8"?>
<View xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="10dp"/>

现在假设你把ListView命名为listView,那么你的onCreate方法应该如下所示:

    final LayoutInflater inflater = 
        (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    final View headerFooter = inflater.inflate(R.layout.header_footer, null);
    listView.addFooterView(headerFooter);
    listView.addHeaderView(headerFooter);

然后设置您的适配器。


1
非常好用,我相信在所有的安卓版本上都能运行,而使用 clipToPadding(上面的解决方案)只适用于某些安卓版本。 - Don
非常有用的答案,谢谢!我已经编辑过了,只是为了去除不必要的复杂性。一个简单的“View”就可以了 - 没有必要在另一个“LinearLayout”内再嵌套一个“LinearLayout”。 - Mark Whitaker

5
为什么不检查物品相对于列表的位置大小:
填充:
 public View getView(int position, View convertView, ViewGroup parent)
    {
         //recycle views and whatever else you normally would do goes here..
         //...
         //...

         if (position == 0){
            convertView.setPadding(0, 10, 0, 0); //padding on top for top item
         }
         else if (position == getCount() - 1){
            convertView.setPadding(0, 0, 0, 10); //padding on bottom for bottom item
         }
         else{
            convertView.setPadding(0, 0, 0, 0); //no padding
         }
}

对于边距,请使用

LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
lp.setMargins(left, top, right, bottom);
convertView.setLayoutParams(lp);

例:

public View getView(int position, View convertView, ViewGroup parent)
    {
             //recycle views and whatever else you normally would do goes here..
             //...
             //...
             LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,        LinearLayout.LayoutParams.WRAP_CONTENT);
             if (position == 0){
                 lp.setMargins(0, 10, 0, 0); //margin on top for top item
             }
             else if (position == getCount() - 1){
                lp.setMargins(0, 10, 0, 10); //margin on bottom for bottom item
             }
             else{
                lp.setMargins(0, 0, 0, 0); //no margin
             }
             convertView.setLayoutParams(lp);
    }

只要您的适配器正确实现了 getCount() 方法,这就会被提供。

这是一个非常好的解决方案。使用 G+ 类型的标题(向下滚动时向上移动,向上滚动时向下移动)使得无法同时拥有 headerview 和对 listview 本身进行填充。 - Jonas Borggren

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接