具有不同圆角半径的卡片视图(CardView)

46

我有以下的CardView,我想为卡片的每个角设置不同的圆角半径。是否可以通过XML或编程方式更改它们?提前感谢。

<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:layout_marginRight="16dp"
    android:layout_marginLeft="16dp"
    android:layout_marginTop="5dp"
    android:layout_marginBottom="5dp"
    app:cardCornerRadius="0dp"
    app:cardElevation="0dp">
</android.support.v7.widget.CardView>

编辑 正如Avinash所建议的那样,我正在寻找此库github.com/captain-miao/OptionRoundCardview的行为方式,但是使用默认的CardView项目。如果无法单独更改它,则此库是一个不错的选择。


如果我们只需要对图像进行形状处理,请使用ShapeableImageView 材料,该材料使用提供的形状绘制位图。 - Anoop M Maddasseri
5个回答

136

这需要使用官方的 MaterialCardView(扩展自androidx.cardview.widget.CardView),以及至少版本1.1.0Material组件库

在布局中添加MaterialCardView

    <com.google.android.material.card.MaterialCardView
        style="@style/CustomCardViewStyle"
        ...>
      
    </com.google.android.material.card.MaterialCardView>

定义自定义样式继承材料卡片样式(例如Widget.MaterialComponents.CardView),并使用shapeAppearanceOverlay属性:

  <style name="CustomCardViewStyle" parent="@style/Widget.MaterialComponents.CardView">
     <item name="shapeAppearanceOverlay">@style/ShapeAppearanceOverlay_card_custom_corners</item>
  </style>


  <style name="ShapeAppearanceOverlay_card_custom_corners" parent="">
    <item name="cornerFamily">rounded</item>
    <item name="cornerSizeTopRight">4dp</item>
    <item name="cornerSizeTopLeft">8dp</item>
    <item name="cornerSizeBottomRight">16dp</item>
    <item name="cornerSizeBottomLeft">0dp</item>
  </style>

enter image description here

您也可以通过编程实现。
只需要将自定义的ShapeAppearanceModel应用于卡片的角落。
例如:

float radius = getResources().getDimension(R.dimen.my_corner_radius);
cardView.setShapeAppearanceModel(
  cardView.getShapeAppearanceModel()
      .toBuilder()
      .setTopLeftCorner(CornerFamily.ROUNDED,..)
      .setTopRightCorner(CornerFamily.ROUNDED,..)
      .setBottomRightCorner(CornerFamily.ROUNDED,radius)
      .setBottomLeftCornerSize(0)
      .build());

注意: 它需要使用库的1.1.0版本。


使用Jetpack Compose,您可以在 Card 中使用 shape 参数。

例如:

Card(
    shape = RoundedCornerShape(
        topStart = 4.dp,
        topEnd = 8.dp,
        bottomEnd = 16.dp,
        bottomStart = 2.dp,
    )
){
    Text("Content Card")
}

enter image description here


1
嗨,Gabriel,谢谢你的回答。这个例子可以不用Android x来完成吗? - Juanje
1
@VarunRaj 需要1.1.0版本(如答案所述)。目前版本为1.1.0-alpha10。 - Gabriele Mariotti
1
@GabrieleMariotti - 如果您能添加正确的 implementation ..... alpha....,那将为像我这样的人节省几分钟的时间 :) - Krzysztof Kubicki
@GabrieleMariotti,你知道如何让MaterialCardView内的ImageView遵循新的圆角并填充整个区域吗? - Krzysztof Kubicki
1
@KrzysztofKubicki 有一些解决方案。例如,您可以在材料组件库中使用 ShapableImageView查看此答案 - Gabriele Mariotti
显示剩余4条评论

3
您可以像这样创建一个自定义的 XML 文件并将其命名为 rounded_corners.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="1dp"
    android:topLeftRadius="20dp"
    android:topRightRadius="30dp"
    android:bottomLeftRadius="40dp"
    android:bottomRightRadius="50dp"/>
<solid android:color="your_background_color" />
</shape>

然后将此作为您的CardView背景:

android:background="@drawable/rounded_corners"

编辑:我刚才注意到这个方法可能适用于所有其他视图而不是CardView,因此请参考此问题以查看如何进行解决。


你说得对,这种方法对于CardViews不起作用。我已经查看了您建议的帖子,但我认为那是一个不太好的解决方案。我正在寻找更干净的解决方案,例如从代码中修改这些属性。无论如何,还是谢谢! - Juanje
是的,我注意到这是一个解决方法。似乎没有更好的方法来做到这一点。 - Vucko
它对于卡片视图无效,因此这个答案对于这个问题不再有效。 - Amir Dora.

2
如果你在 CardView 中使用 ImageView,你应该将 ImageView 更改为 ShapeableImageView。普通的 ImageView 只适用于所有角而非每个角。
这里有更详细的资料 example,请参考 material.io 文档。

themes.xml

<style name="MyCardView" parent="@style/Widget.MaterialComponents.CardView">
    <item name="shapeAppearanceOverlay">@style/MyCardViewOverlay</item>
</style>

<style name="MyCardViewOverlay">
    <item name="cornerFamily">rounded</item>
    <!-- below items does not work with normal ImageView -->
    <item name="cornerSizeTopRight">0dp</item>
    <item name="cornerSizeTopLeft">60dp</item>
    <item name="cornerSizeBottomRight">0dp</item>
    <item name="cornerSizeBottomLeft">0dp</item>
</style>

layout.xml

<com.google.android.material.card.MaterialCardView
    style="@style/MyCardView"
    android:layout_width="200dp"
    android:layout_height="200dp"
    app:cardPreventCornerOverlap="false">

    <com.google.android.material.imageview.ShapeableImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@color/orange_600"
        app:shapeAppearanceOverlay="@style/MyCardViewOverlay" />
</com.google.android.material.card.MaterialCardView>

0

注意:如果您只想在底部实现圆角而在顶部保持常规角,那么这里提供的方法是一个解决办法。但如果您想为卡片视图的四个角设置不同的半径,则需要使用 Material CardView 或某些第三方库。

以下是我尝试过的方法:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:background="#F9F9F9">

    <androidx.cardview.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="200dp"
            android:background="@drawable/profile_bg"/>

    </androidx.cardview.widget.CardView>

    <androidx.cardview.widget.CardView
        android:id="@+id/cvProfileHeader"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:cardCornerRadius="32dp">
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="280dp"
            android:orientation="vertical"
            android:background="@drawable/profile_bg"
            android:id="@+id/llProfileHeader"
            android:gravity="center_horizontal">

            <!--Enter your code here-->

        </LinearLayout>
    
    </androidx.cardview.widget.CardView>

</RelativeLayout>

总共有两个卡片视图。第二个卡片视图是将拥有圆角(通常情况下四个角都是圆角),并将在其下方容纳所有其他子视图。上面的第一个卡片视图也处于相同的高度(抬升高度),具有相同的背景,但仅约为第二个卡片视图的一半高,并且没有圆角(只有普通的尖角)。这样,我能够在底部实现部分圆角和顶部正常角。但是,对于所有四个角,您可能需要使用材料卡片视图。


-1

你可以使用以下代码通过编程或XML方式添加它。

app:cardCornerRadius="0dp"// xml
cardView.setRadius(0);

这是一个额外的人,正在寻求提升。

app:cardElevation="0.7dp"//xml
app:cardMaxElevation="1dp"//xml
cardView.setCardElevation(2.1f);//code
cardView.setMaxCardElevation(3f);//code

CardView的XML的完整Java表示。

CardView cardView = (CardView) findViewById(R.id.cardView);
cardView.setUseCompatPadding(true);
cardView.setContentPadding(30, 30, 30, 0);
cardView.setPreventCornerOverlap(true);
cardView.setCardBackgroundColor(Color.WHITE);
cardView.setCardElevation(2.1f);
cardView.setRadius(0);
cardView.setMaxCardElevation(3f);

1
这个解决方案设置了CardView的所有角落,我只想设置其中一个,例如左上角。 - Juanje
1
好的,我明白了。直接使用cardview很难实现,所以我建议您使用一些第三方库。 https://github.com/captain-miao/OptionRoundCardview 看看这个。 - Avinash Ajay Pandey
是的,你说得对,我已经检查过这个项目了。如果我在CardView上找不到任何解决方案,那么这将是我的下一步。谢谢!感谢你的帮助! - Juanje

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