如何在Android L中为CardView小部件设置填充(padding)

82

我正在使用 android:paddingLeftandroid:paddingTop 来设置新的 CardView 控件的填充,但它不起作用。

我可以为 CardView 内所有控件设置边距来解决问题,但如果有太多的控件,这将是一种痛苦的方式。

如何为新的cardview小部件设置填充?

<android.support.v7.widget.CardView
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:id="@+id/card_view"
    android:layout_gravity="center"
    android:layout_width="match_parent"
    android:layout_height="200dp"
    android:paddingLeft="20dp"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="20dp"
    android:paddingBottom="@dimen/activity_vertical_margin"
    card_view:cardCornerRadius="2dp">

    <TextView
        android:id="@+id/info_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Hello World!"/>
</android.support.v7.widget.CardView>

你是在L预览版上测试还是其他操作系统版本? - alanv
测试在Kitkat 4.4.4上进行。CardView显示正常,除了填充之外一切看起来都很好。 - nomongo
5个回答

217

CardView 应该使用其自带的 contentPadding 属性来处理这个问题:

<android.support.v7.widget.CardView
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:id="@+id/card_view"
    android:layout_gravity="center"
    android:layout_width="match_parent"
    android:layout_height="200dp"
    card_view:cardCornerRadius="2dp"
    card_view:contentPaddingLeft="20dp"
    card_view:contentPaddingRight="@dimen/activity_horizontal_margin"
    card_view:contentPaddingTop="20dp"
    card_view:contentPaddingBottom="@dimen/activity_vertical_margin">

    <TextView
        android:id="@+id/info_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Hello World!"/>
</android.support.v7.widget.CardView>

1
既然在CardView上定义“padding”属性没有意义,为什么不能将该属性复制到其内部的contentPadding中呢?我们只是应该记住/知道CardView有一个叫做contentPadding的东西,而不是使用padding吗?@MichelJung - Greg Ennis
1
@GregEnnis 因为为 CardView 定义 padding 是有意义的。实际上,Android 系统就是这样做的: "在 L 版本之前,CardView 会为其内容添加填充,并在该区域绘制阴影。这个填充量等于侧面的 maxCardElevation +(1-cos45)* cornerRadius,顶部和底部的填充量是 maxCardElevation * 1.5 +(1-cos45)* cornerRadius." 这是区分应用于卡片背景的填充和内部内容填充的问题。 - yarian
6
@yarian 并没有回答我的问题,实际上只是让情况变得更糟。不确定如何能指望刚开始学习 Android 开发的人解决这个问题。 - Greg Ennis
1
@yarian 你有没有想法如何在自定义样式(styles.xml)中指定 card_view:contentPadding - Gautam
这对于我在运行Android 7.1的手机上完美地工作了。然而,在我另一个运行Android 4.1.2的手机上没有任何影响。 - Sam
@Gautam contentPaddingX 对我有用(其中 X 可以是 Left、Top、Bottom、Right 或为空)。例如: <item name="contentPadding">20dp</item> - O-9

74

在L-preview之前,CardView使用RoundRectDrawableWithShadow来绘制其背景,该绘制方式会覆盖Drawable.getPadding()以添加阴影填充。视图的背景是在膨胀后通过代码设置的,这会覆盖XML中指定的任何填充。

你有两个选择:

  1. 在运行时使用View.setPadding()设置填充,并小心调整阴影(但仅限于L-preview之前!)。
  2. 将所有内容放入指定填充的布局中。

后者是最安全的选择。

<android.support.v7.widget.CardView
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:id="@+id/card_view"
    android:layout_gravity="center"
    android:layout_width="match_parent"
    android:layout_height="200dp"
    card_view:cardCornerRadius="2dp">

    <FrameLayout
        android:paddingLeft="20dp"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="20dp"
        android:paddingBottom="@dimen/activity_vertical_margin">

        <TextView
            android:id="@+id/info_text"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Hello World!"/>
    </FrameLayout>
</android.support.v7.widget.CardView>

18
楼主至少有第三种选择:接受yarian的回答。 - Michel Jung
@MichelJung,yarian的答案在我的Android 4.1.2上不起作用,因此使用建议中提到的包装器可能是更安全的选择。 - Sam
它有效了,谢谢! - neo

37
如果您想在早于L版本的设备上使用CardView padding,并希望在Lollipop+设备上看起来相同,则需要使用setUseCompatPadding(true)或XML变量cardUseCompatPadding="true"
这是因为“CardView在L之前的平台上添加额外的填充以绘制阴影。”[1] 因此,默认实现使不同API版本看起来不同,视图可能无法正确对齐。因此,解决此问题的最简单方法是使用上述方式,或者改用边距。

示例代码

<android.support.v7.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_context"
    card_view:cardUseCompatPadding="true"
    card_view:contentPadding="8dp"
    card_view:cardCornerRadius="4dp" >

    ...

</android.support.v7.widget.CardView>

来源

[1] CardView.setUseCompatPadding(boolean)

[2] android.support.v7.cardview:cardUseCompatPadding


这正是我所需要的。谢谢! - Aci89
即使我设置了 card_view:cardUseCompatPadding="true",在运行 Android 4.1.2 的手机上仍然没有填充。 - Sam
完美。谢谢。 - Gerson C Filho

1
这是对我有效的方法 - 将每个项目放在帧布局中。
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
 android:layout_marginBottom="-4dp">

   <android.support.v7.widget.CardView   
            xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:card_view="http://schemas.android.com/apk/res-auto"

            android:background="@color/white_three"
            android:orientation="vertical"
            card_view:cardCornerRadius="2dp"
            card_view:cardElevation="@dimen/card_elevation"
            card_view:cardMaxElevation="0dp"
            card_view:cardPreventCornerOverlap="false"
            card_view:cardUseCompatPadding="true"
   </android.support.v7.widget.CardView>

请务必确认card_view的命名空间为"http://schemas.android.com/apk/res-auto"而非tools,并在框架视图上设置负边距以保持阴影 - 这样就可以正常工作了。


0

只需添加以下两行

<androidx.cardview.widget.CardView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="24dp"
            android:layout_marginRight="16dp"
            android:layout_marginBottom="24dp"
            android:layout_marginLeft="16dp"
            app:cardUseCompatPadding="true" // add this line
            app:contentPadding="16dp" // add this line`enter code here`
            app:cardCornerRadius="8dp"
           >
        </androidx.cardview.widget.CardView>

那就这样吧...愉快地编码吧...

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