musooff
musooff

Reputation: 6882

CardView elevation shadow not centered?

I have a CardView defined as

<androidx.cardview.widget.CardView
    android:layout_width="70dp"
    android:layout_height="70dp"
    app:cardCornerRadius="35dp"
    app:cardElevation="10dp">
    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="fitXY"
        android:src="@drawable/ic_user_default"/>
</androidx.cardview.widget.CardView>

But somehow I am getting this weird shadow, which I am not able to figure out why? enter image description here

I wanted to have a circular CardView with a circular shadow around it, but instead I am getting a shadow in the right bottom corner.

What am I missing out?

I tried few things and this is what I concluded.

CardView is inside a RelativeLayout which has wrap_content as layout_height. Which I guess is wrapping the CardView only, without it's shadow. Take a look at below example.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center">
    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
        <androidx.cardview.widget.CardView
            android:layout_width="70dp"
            android:layout_height="70dp"
            app:cardCornerRadius="35dp"
            app:cardElevation="10dp">
        </androidx.cardview.widget.CardView>
    </RelativeLayout>

    <androidx.cardview.widget.CardView
        android:layout_width="70dp"
        android:layout_height="70dp"
        app:cardCornerRadius="35dp"
        app:cardElevation="10dp">
    </androidx.cardview.widget.CardView>

</LinearLayout>

Which will show like enter image description here

So that leads to a question why it's wrapping around the CardView but not CardView with its shadows? And one side question. How do you center the shadow of CardView? If you look closely to the second CardView, the shadow is has a gravity to bottom.

Upvotes: 2

Views: 8467

Answers (2)

aminography
aminography

Reputation: 22832

The deviation of CardView's shadow depends on its location in screen. As you can see in below picture, when the CardView is placed in left or right side of the screen, its shadow is deviated to left or right side too.

enter image description here

However, AFAIK, we have no control on the CardView's shadow perspective since there is no attribute for it to change. If you want to have a custom direction shadow, you should do it yourself.

Upvotes: 2

Ishita Sinha
Ishita Sinha

Reputation: 2294

I suggest you take a look at android documentation for shadows.

You said:

CardView is inside a RelativeLayout which has wrap_content as layout_height. Which I guess is wrapping the CardView only, without it's shadow. So that leads to a question why it's wrapping around the CardView but not CardView with its shadows?

The following answers why:

Shadows are drawn by the parent of the elevated view, and thus subject to standard view clipping, clipped by the parent by default.

Also:

The bounds of a view's background drawable determine the default shape of its shadow. Consider this view, defined with a background drawable:

<TextView
    android:id="@+id/myview"
    ...
    android:elevation="2dp"
    android:background="@drawable/myrect" />

The background drawable is defined as a rectangle with rounded corners:

<!-- res/drawable/myrect.xml -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:shape="rectangle">
    <solid android:color="#42000000" />
    <corners android:radius="5dp" />
</shape>

The view casts a shadow with rounded corners, since the background drawable defines the view's outline. Providing a custom outline overrides the default shape of a view's shadow.

This you have already achieved with app:cardCornerRadius="35dp" rather than a custom background drawable (which is equally acceptable, although I thought adding this bit of info might be of some additional help if you need it for other views in the future).

To answer the question How do you center the shadow of CardView? you may take a look at the material design guidelines. According to Material Design, shadows should come from both ambient light (front light source) and a key light (top light source):

enter image description here

The elevation of these light sources are by default 90 degrees and 45 degrees respectively in the android framework, and cannot be changed because that would be inconsistent with material design. However, if you want to create a custom shadow with a custom angle, you could use a gradient drawable and set that as a shadow as described here under the head Using Shape Drawable (New way to implement shadow).

Basically, you need to use the setShadowLayer method from the android.graphics.Paint class.

Hope this helps!

Upvotes: 4

Related Questions