Search code examples
androidandroid-drawableandroid-cardviewmaterial-components-androidcardview

CardView Radius and Drawable Shape Radius are not same


I have below layout that has a CardView

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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="match_parent"
    android:background="@color/white"
    android:padding="50dp"
    >
  <androidx.cardview.widget.CardView
      android:layout_width="match_parent"
      android:layout_height="200dp"
      app:cardBackgroundColor="@android:color/holo_red_light"
      app:cardCornerRadius="50dp"
      app:cardElevation="0dp"
      app:layout_constraintTop_toTopOf="parent"
      >
    <View
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/outline"
        />
  </androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>

And my @drawable/outline is just a stroke with corner radius same as cardCornerRadius

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
  <corners android:radius="50dp" />
  <stroke
      android:width="3dp"
      android:color="@color/white" />
</shape>

So, I was expecting a CardView that has an outline. But this is what I get

enter image description here

Why does the radius of my stoke and radius of CardView are not the same and how to fix it?


Solution

  • Check this issue on MaterialCardView (but it is the same with the androidx.cardview.widget.CardView)

    It is due to Anti aliasing. The background and the stroke are drawn on the same pixels but depending on the color of the stroke the transparent pixels added by the AA can cause the bleed through. That's why you won't see it if you invert the colors here.

    You can achieve the same view just using

       <com.google.android.material.card.MaterialCardView
            app:cardBackgroundColor="@color/...."
            app:strokeWidth="3dp"
            app:strokeColor="@color/white />
    

    enter image description here

    As you can see:

    enter image description here

    You have another option.
    You can apply the same ShapeAppearanceModel (provided by default by the MaterialCardView) to a simple View (or Layout) inverting the colors and applying the margin to the inner view.

       <com.google.android.material.card.MaterialCardView
            app:cardCornerRadius="@dimen/corner_radius_16"
            app:cardBackgroundColor="@color/white">
    
            <View
                android:layout_margin="3dp"   
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:id="@+id/view_rounded"/>
    
        </com.google.android.material.card.MaterialCardView>
    

    And then:

    float size = getResources().getDimension(R.dimen.cutout_size);
    
    View viewRounded = findViewById(R.id.view_rounded);
    ShapeAppearanceModel shapeAppearanceModelView = new ShapeAppearanceModel()
            .toBuilder()
            .setAllCorners(CornerFamily.ROUNDED,radius16)
            .build();
    MaterialShapeDrawable shapeDrawableView = new MaterialShapeDrawable(shapeAppearanceModelView);
    shapeDrawableView.setFillColor(ContextCompat.getColorStateList(this,R.color.xxx));
    ViewCompat.setBackground(viewRounded,shapeDrawableView);
    

    enter image description here

    enter image description here