14

Is is possible to have different values for each corner radius of a MaterialCardView? And if so how?

I tried something like the code below but it doesn't seem to have any effect

    float radius = getContext().getResources().getDimension(R.dimen.default_corner_radius);
    ShapePathModel leftShapePathModel = new ShapePathModel();
    leftShapePathModel.setTopLeftCorner(new RoundedCornerTreatment(radius));
    leftShapePathModel.setTopRightCorner(new RoundedCornerTreatment(radius));
    MaterialShapeDrawable bg = new MaterialShapeDrawable(leftShapePathModel);
    container.setBackground(bg);

where container is

@BindView(R.id.container) MaterialCardView container;
Gabriele Mariotti
  • 320,139
  • 94
  • 887
  • 841
Tudor S.
  • 809
  • 2
  • 12
  • 29
  • 2
    instead of posting the link, post relative code that you have tried. – karan Feb 14 '19 at 11:13
  • Done, sorry! :) – Tudor S. Feb 14 '19 at 11:43
  • 1
    First, always post your code in a question. Second, have you checked all the solutions on Stackoverflow? Have you tried this: https://stackoverflow.com/questions/29342633/cardview-corner-radius – Douglas Cunha Feb 14 '19 at 11:49
  • I've seen that post however I was hoping there's a better solution than nesting two cardviews. I found this issue https://issuetracker.google.com/issues/117662587 which seems to address my problem but I'm not too sure how to make use of it and I've not found much documentation around it. – Tudor S. Feb 14 '19 at 12:05

4 Answers4

21

You can use a custom style and the shapeAppearanceOverlay attribute.

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


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

or 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()
      .setTopLeftCorner(CornerFamily.ROUNDED,radius)
      .setTopRightCorner(CornerFamily.ROUNDED,radius)
      .setBottomRightCornerSize(0)
      .setBottomLeftCornerSize(0)
      .build());

enter image description here

Gabriele Mariotti
  • 320,139
  • 94
  • 887
  • 841
  • Shows rounded corners on android studio but on the device, it's all rectangular! – OhhhThatVarun Sep 13 '19 at 17:30
  • @VarunRaj are you using 1.1.0-alpha10 ? Just tried and both with ShapeAppearanceModel and shapeAppearanceOverlay with the values in the example on Android P/Q the result is the same screenshot attached in the answer. – Gabriele Mariotti Sep 13 '19 at 17:34
  • `implementation 'com.google.android.material:material:1.1.0-alpha10'` line from straight from the app. Will work on only P and Q? – OhhhThatVarun Sep 13 '19 at 17:42
  • I just saw it from very close the rounded corners are there but only visible when dragging my bottom sheet. – OhhhThatVarun Sep 13 '19 at 17:46
  • Are you trying to have a bottomSheet with round corners? – Gabriele Mariotti Sep 13 '19 at 18:08
  • Yep! But I want shadows as well so I thought CardView will be easy and perfect for the job. – OhhhThatVarun Sep 13 '19 at 18:09
  • @VarunRaj You can also have roundCorners in the bottomSheet with the same `shapeAppearanceOverlay` attribute without using a card. You can also have the elevation using `xxdp` in the style. For the persistent BottomSheet you can check [this answer](https://stackoverflow.com/a/57626774/2016562), for the modal [this one](https://stackoverflow.com/a/57627229/2016562). – Gabriele Mariotti Sep 13 '19 at 18:18
  • 3
    this does not crop content, so rectangular content flows outside on these corners – Jemshit Dec 25 '19 at 09:12
  • custom ShapeAppearanceModel solution worked for me! – Ahmed Nabil Jul 26 '23 at 08:07
5

Try This Also

     <style name="TopCornerCardview" parent="Widget.MaterialComponents.CardView">
        <item name="cornerFamily">rounded</item>
        <item name="cornerSizeTopRight">@dimen/dp25</item>
        <item name="cornerSizeTopLeft">@dimen/dp25</item>
        <item name="cornerSizeBottomRight">0dp</item>
        <item name="cornerSizeBottomLeft">0dp</item>
        <item name="contentPadding">0dp</item>
    </style>

    <com.google.android.material.card.MaterialCardView
            style="@style/TopCornerCardview"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:theme="@style/TopCornerCardview"
            app:cardBackgroundColor="@color/colorAccent"
            app:cardUseCompatPadding="true">

>
<!--views here-->
</com.google.android.material.card.MaterialCardView>
Mujahid Khan
  • 1,712
  • 1
  • 18
  • 24
3

My initial solution was correct but it was missing one line:

float radius = getContext().getResources().getDimension(R.dimen.default_corner_radius);
ShapePathModel leftShapePathModel = new ShapePathModel();
leftShapePathModel.setTopLeftCorner(new RoundedCornerTreatment(radius));
leftShapePathModel.setTopRightCorner(new RoundedCornerTreatment(radius));
MaterialShapeDrawable bg = new MaterialShapeDrawable(leftShapePathModel);
container.setBackground(bg);

If you add

container.invalidate()

as suggested by Cameron above it seems to work.

Tudor S.
  • 809
  • 2
  • 12
  • 29
2

I think you should be able to call ShapeAppearanceModel shape = ((MaterialShapeDrawable)container.getBackground()).getShapeAppearanceModel() on your MaterialCardView. From there you could call setTopLeftCorner() or the other methods to set corner treatments with different values. You may need to call container.invalidate() after you set the corners.

Cameron Ketcham
  • 7,966
  • 2
  • 28
  • 27
  • Thanks for that but unfortunately the background returned by the MatericalCardView cannot be cast to MaterialShapeDrawable. However, invalidating the container using the code I posted initially seems to have fixed the issue. – Tudor S. Feb 18 '19 at 14:38
  • 1
    I think it might use a LayerDrawable to wrap it with other things. Unfortunately for now it looks like it's not that easy to get access to. We're working to make it easier for each component. – Cameron Ketcham Feb 19 '19 at 17:16