Home » Android » android – How can I set view shadow only on sides for view with elevation

android – How can I set view shadow only on sides for view with elevation

Posted by: admin May 14, 2020 Leave a comment

Questions:

I have a RecyclerView with various view types. Each view has own background with top, bottom or no rounded corners. Each use the same view elevation.
This is one of the backgrounds in XML

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:color="@color/card_background_pressed"
    tools:targetApi="lollipop">
    <item>
        <shape>
            <size
                android:width="1dp"
                android:height="1dp" />
            <solid android:color="@color/card_background_normal" />
        </shape>
    </item>
</ripple>

When views are laid out next to each other without any margin it looks like having the same background. This is my way for creating dynamic card background. In other words I can create single looking card from multiple items in RecyclerView

Problem

As you can see below, when 2 views are laid out next to each other their shadows are overlapping each other in the corners, even when corner background radius is 0.

So does anyone know how to fix it? I care only for API 21+ so need to worry about older versions support. Thanks in advance!

enter image description here

How to&Answers:

I have not tried with RippleDrawable but I think the idea is the same. So let’s start with a simple case:

Android provides a class called ViewOutlineProvider. You can use this class to create your own shadow. For your problem you can set offset for your bottom view’s shadow so the overlapping area is drawn by the shadow of top view.

Some code please:

First I am trying to create your problem with this layout:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context=".MainActivity">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay" />

    </android.support.design.widget.AppBarLayout>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">


        <LinearLayout
            android:layout_width="300dp"
            android:layout_height="400dp"
            android:layout_centerInParent="true"
            android:orientation="vertical">

            <TextView
                android:id="@+id/top"
                android:layout_width="100dp"
                android:layout_height="50dp"
                android:layout_marginLeft="50dp"
                android:layout_marginTop="50dp"
                android:background="@android:color/holo_blue_dark"
                android:elevation="25dp"
                android:gravity="center"
                android:text="Top" />

            <TextView
                android:id="@+id/bottom"
                android:layout_width="100dp"
                android:layout_height="50dp"
                android:layout_below="@id/top"
                android:layout_marginLeft="50dp"
                android:layout_marginTop="2dp"
                android:background="@android:color/holo_orange_light"
                android:elevation="25dp"
                android:gravity="center"
                android:text="Bottom" />
        </LinearLayout>
    </RelativeLayout>
</android.support.design.widget.CoordinatorLayout>

it is a little hard to recognize overlapping shadows:

enter image description here

Now I add some arbitrary y offset by this code:

public class MainActivity extends AppCompatActivity {

    TextView mTopTv,mBottomTv;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        mTopTv = (TextView)findViewById(R.id.top);
        mBottomTv = (TextView)findViewById(R.id.bottom);
        mBottomTv.setOutlineProvider(new ViewOutlineProvider() {
            @Override
            public void getOutline(View view, Outline outline) {
                outline.setRect(0, 50, view.getWidth(), view.getHeight());
            }
        });
    }

}

and the result is:

enter image description here

As comparing two images it is clear that the overlapping area is eliminated.