7

I am using material design in my android app and normally for changing the radius of the corner of card i use app:cardCornerRadius, but this will change all the four corner of card. I want to change any specific corner of the card. I dont want to use drawable only for changing the corner. Is there any way through xml or programatically.

 <com.google.android.material.card.MaterialCardView
        style="@style/Widget.MaterialComponents.CardView"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:backgroundTint="@color/colorWhite"
        app:cardCornerRadius="16dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_marginStart="16dp" android:layout_marginEnd="16dp">
    <androidx.constraintlayout.widget.ConstraintLayout
            android:visibility="visible"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
Gabriele Mariotti
  • 320,139
  • 94
  • 887
  • 841
Amit Sen
  • 177
  • 2
  • 12

3 Answers3

13

With the version 1.1.0 of the Material Component you can customize the shape of your component using the shapeAppearanceOverlay attribute.
You can use it in the view or in the style.

<com.google.android.material.card.MaterialCardView
      .....
      app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.MaterialCardView.Cut">

and then define your favorite shape:

  <style name="ShapeAppearanceOverlay.MaterialCardView.Cut" parent="">
    <item name="cornerFamily">rounded</item>
    <item name="cornerSizeTopRight">0dp</item>
    <item name="cornerSizeTopLeft">16dp</item>
    <item name="cornerSizeBottomRight">16dp</item>
    <item name="cornerSizeBottomLeft">16dp</item>
  </style>

enter image description here

With the code you can apply a custom ShapeAppearanceModel to the corner of the card using something like:

float radius = getResources().getDimension(R.dimen.my_corner_radius);
cardView.setShapeAppearanceModel(
  cardView.getShapeAppearanceModel()
      .toBuilder()
      .setAllCorners(CornerFamily.ROUNDED,radius)
      .setTopRightCornerSize(0)
      .build());
Gabriele Mariotti
  • 320,139
  • 94
  • 887
  • 841
  • Great answer! I tried it programatically and it worked great, until I placed an imageView inside of the MaterialCardView. In this case, the corners get overlapped by the image, so it seems like the cardview has no corner radius... I need a way to change the corner radius programatically without this problem, any ideas? – Tiago Nunes Mar 18 '21 at 17:00
  • @TiagoNunes try to use [`ShapeableImageView`](https://stackoverflow.com/a/59430153/2016562) – Gabriele Mariotti Mar 18 '21 at 17:13
  • 2
    Unfortunately, that won't work in my use case, as I have an horizontal recyclerview of images... – Tiago Nunes Mar 18 '21 at 18:46
  • @TiagoNunes I have the same use case. Did you find any working solution in this case? – Saket Kumar Jun 23 '22 at 02:58
  • @SaketKumar I don't remember, sorry... But at this point you can just use Compose for this, and there will be no issues. – Tiago Nunes Jun 24 '22 at 08:30
  • @TiagoNunes yeah I use compose but it's not fully migrated and still I have to use XML in this case. :( – Saket Kumar Jun 24 '22 at 12:03
4

I have a solution but it requires v21 Lollipop and above. You can do it programmatically as follows:

In your activity class have public static int radius = 20; and in your Oncreate();

CardView card = findViewById(R.id.my_card);


if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
   makeCustomOutline(card);
}

then define the function as follows:

 @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void makeCustomOutline(CardView card){

    card.setOutlineProvider(new ViewOutlineProvider() {
        @Override
        public void getOutline(View view, Outline outline) {

            outline.setRoundRect(0, 0, view.getWidth(),
                    (view.getHeight() + radius), (float)radius );
        }
    });
    card.setClipToOutline(true);

}

by using the setRoundRect() method you can control which corner of the cardview gets the radius and which doesn't. The above code will make only the top corners rounded, bottom corners will not be rounded.

References:

This answer was adapted from this article

docs on setRoundRect() method

docs on ViewOutlineProvider

Edgar
  • 472
  • 6
  • 17
-1

I am not pretty sure about Material design cardview to have that functionality or not. But I don't think that default cardview have that kind of functionality so on behalf of that material cardview you can use

This Library (click here).

It is just my opinion may be there is another good solution for that.

Manthan Patel
  • 1,784
  • 19
  • 23