RecyclerView内部的CardView有额外的边距问题

37

我正在将CardView作为RecyclerView中的元素使用。这样做时,Android会自动在卡片视图与屏幕之间以及不同卡片视图之间生成边距。

<android.support.v7.widget.CardView 
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/galleryCardBGColor"
app:cardCornerRadius="2dp" >

<android.support.v7.widget.RecyclerView
    android:id="@+id/my_recycler_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:scrollbars="vertical" />

我按照链接中的指示将它们集成到我的项目中:在Eclipse ADT中使用RecyclerView和CardView

之前我一直使用LinearLayout来作为列表元素:

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical" >

这原本完全正常运作,列表元素之间毫无边距。现在我把线性布局放到卡片视图里面,结果出现了额外的边距。

原因是我想为这些元素提供精确的边距,而现在提供的任何边距都被添加到这些已有的边距上。 我尝试向cardView元素提供零/负填充/边距,但它们都无法解决问题。

有什么建议可以消除这些边距或者知道被添加了多少边距吗?

11个回答

47

你检查过它是边距还是内边距了吗?(开发者选项 / 显示布局边界)

CardView在升级到L以上版本后不需要添加额外的内边距来绘制阴影,但在之前的平台版本中需要。如果您设置了useCompatPadding=true,则L版本也会需要添加内边距。

可以通过添加负边距(虽然不太美观)来解决问题。如果没有效果,请提供一些有关如何添加边距和如何设置RecyclerView的代码。


4
这是一个填充,是的,我正在一个 L 版本之前的设备上进行测试。感谢您指出了正确的方向:我在 CardView 文档中找到了以下信息: 在 L 版本之前,CardView 会为其内容添加填充,并在该区域绘制阴影。此填充量等于侧面的 maxCardElevation +(1-cos45)* cornerRadius,并且顶部和底部的 maxCardElevation * 1.5 +(1-cos45)* cornerRadius。 根据这个信息我可以计算出填充值(并从想要提供的值中减去)。我现在没有 L 版本的设备,一旦测试完成我会更新。附注:负边距无效。 - vj9
3
更精确地说:card_view:cardUseCompatPadding="true" 的意思是使用向后兼容的填充方式来渲染卡片视图。 - Rémy DAVID
这对我有用:https://android.jlelse.eu/using-full-width-cards-to-maximize-content-f739cb863ce8 - Sagar Patel

45

这对我很有效。使用:

 card_view:cardElevation="0dp"
 card_view:cardMaxElevation="0dp"

3
除了设置 cardCornerRadius="1dp" 或者其他的任意值之外,这一点对我很有效!谢谢,@Shubham。我认为设置 cardMaxElevation 就解决了问题。 - w3bshark
14
我不想移除卡片高度,所以你的解决方案行不通。 - Toochka

18
使用下面这两个标签:
card_view:cardPreventCornerOverlap="false"
card_view:cardUseCompatPadding="true"

18

正如@yigit的回答中所描述的那样,在Android L之前,CardView会添加默认填充以绘制其阴影。填充大小在CardView的文档中有描述。

我发现清除这个填充(也可以添加内容填充)的方法是使用CardView的contentPaddingLeft(/ Right / Top / Bottom)属性。

如果您想清除默认填充,请将contentPadding设置为负值。如果您想添加内容填充,请将contentPadding设置为所需值。

在我的情况下,我使用以下代码清除默认填充:

card_view:contentPaddingLeft="-3dp"
card_view:contentPaddingRight="-3dp"
card_view:contentPaddingTop="-3dp"
card_view:contentPaddingBottom="-3dp"

我尝试了@Shubham的答案,但在RadialGradient.java中抛出了一个IllegalStateException异常,错误消息是“半径必须大于0”。


5

card_view:cardPreventCornerOverlap="false"添加到你的card中,仅在你的图片有圆角时起作用。


4

我知道现在有点晚了,但是我希望这篇翻译能对某些人有所帮助。

app:cardPreventCornerOverlap="false"

将app:cardPreventCornerOverlap设置为false就可以解决问题 :)

这实际上是我的问题。看起来,拥有更多的圆角半径会向CardView的内容添加更多的填充。这作为默认值是有道理的,以避免剪切内容,但大多数情况下,内容实际上并没有被剪切。 - Sotti

2
好的,似乎有一种更简单的方法来做到这一点,而无需猜测填充和其他内容:
card_view:cardPreventCornerOverlap="false"

或者使用Java:

cardView.setPreventCornerOverlap(false)

1

@vj9在被采纳的问题下的评论帮助我计算偏移量。在这里分享它,因为它可能会帮助到其他人:

public static int getVerticalCardViewOffset(Context context) {
    Resources res = context.getResources();
    int elevation = res.getDimensionPixelSize(R.dimen.cardview_default_elevation);
    int radius = res.getDimensionPixelSize(R.dimen.cardview_default_radius);
    return (int) (elevation * 1.5 + (1 - Math.cos(45)) * radius);
}

public static int getHorizontalCardViewOffset(Context context) {
    Resources res = context.getResources();
    int elevation = res.getDimensionPixelSize(R.dimen.cardview_default_elevation);
    int radius = res.getDimensionPixelSize(R.dimen.cardview_default_radius);
    return (int) (elevation + (1 - Math.cos(45)) * radius);
} 

获取卡片的实际海拔高度不是假设使用默认高度更好吗?例如 float elevation = cardView.getCardElevation(); - Micky
同样适用于半径:float radius = cardView.getRadius(); - Micky
如果您不使用默认的卡片视图样式,当然可以更改它为您自己的尺寸。 - Markus Rubey

0
如果不需要圆角或elevation向下兼容性,可以考虑在Lollipop版本之前使用FrameLayout<include layout="@layout/card_view_compat" /> layout/card_view_compat
<merge
    xmlns:android="http://schemas.android.com/apk/res/android"
    >
    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        >
        <include layout="@layout/content" />
    </FrameLayout>
</merge>

layout-v21/card_view_compat

<merge
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    >
    <android.support.v7.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:cardCornerRadius="3dp"
        app:cardElevation="4dp"
        >
        <include layout="@layout/content" />
    </android.support.v7.widget.CardView>
</merge>

0

使用

android:adjustViewBounds="true"

在你想要用CardView包装的视图上


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