I used the material design library for Android to make the tab strip as follows.

At the bottom of the screen, I added a view.

Now I'm trying to add a shadow effect from the top widget to the bottom view.
I found a solution in the form of an answer to this question .
The only way I created the top shadow is to change the source part of the AndroidView v7 CardView project for Android. This project brings the CardView class to older versions of Android and therefore also includes shadow heights. The resulting shadow is very close to the "real" shadow.
I followed the instructions and I ended up with the following result to use the illustration

I added these colors to res/values/values.xml
<color name="cardview_shadow_end_color">#03000000</color>
<color name="cardview_shadow_start_color">#47000000</color>
<dimen name="cardview_compat_inset_shadow">1dp</dimen>
RoundRectDrawableWithShadow Android v7 CardView Android,
float elevation = 200;
float density = 0.1f;
View bottomView = (View) rootView.findViewById(R.id.bottomView);
bottomView.setBackgroundDrawable(new RoundRectDrawableWithShadow(
getResources(), Color.BLACK, 0,
elevation * density, ((elevation + 1) * density) + 1
));
CardView RoundRectDrawableWithShadow class
import android.graphics.RectF;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.RadialGradient;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
public class RoundRectDrawableWithShadow extends Drawable {
final static double COS_45 = Math.cos(Math.toRadians(45));
final static float SHADOW_MULTIPLIER = 1.5f;
final int mInsetShadow;
static RoundRectHelper sRoundRectHelper;
Paint mPaint;
Paint mCornerShadowPaint;
Paint mEdgeShadowPaint;
final RectF mCardBounds;
float mCornerRadius;
Path mCornerShadowPath;
float mMaxShadowSize;
float mRawMaxShadowSize;
float mShadowSize;
float mRawShadowSize;
private boolean mDirty = true;
private final int mShadowStartColor;
private final int mShadowEndColor;
private boolean mAddPaddingForCorners = true;
private boolean mPrintedShadowClipWarning = false;
public RoundRectDrawableWithShadow(
Resources resources, int backgroundColor, float radius,
float shadowSize, float maxShadowSize
) {
mShadowStartColor = resources.getColor(R.color.cardview_shadow_start_color);
mShadowEndColor = resources.getColor(R.color.cardview_shadow_end_color);
mInsetShadow = resources.getDimensionPixelSize(R.dimen.cardview_compat_inset_shadow);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
mPaint.setColor(backgroundColor);
mCornerShadowPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
mCornerShadowPaint.setStyle(Paint.Style.FILL);
mCornerRadius = (int) (radius + .5f);
mCardBounds = new RectF();
mEdgeShadowPaint = new Paint(mCornerShadowPaint);
mEdgeShadowPaint.setAntiAlias(false);
setShadowSize(shadowSize, maxShadowSize);
RoundRectDrawableWithShadow.sRoundRectHelper
= new RoundRectDrawableWithShadow.RoundRectHelper() {
@Override
public void drawRoundRect(Canvas canvas, RectF bounds, float cornerRadius,
Paint paint) {
canvas.drawRoundRect(bounds, cornerRadius, cornerRadius, paint);
}
};
}
private int toEven(float value) {
int i = (int) (value + .5f);
if (i % 2 == 1) {
return i - 1;
}
return i;
}
public void setAddPaddingForCorners(boolean addPaddingForCorners) {
mAddPaddingForCorners = addPaddingForCorners;
invalidateSelf();
}
@Override
public void setAlpha(int alpha) {
mPaint.setAlpha(alpha);
mCornerShadowPaint.setAlpha(alpha);
mEdgeShadowPaint.setAlpha(alpha);
}
@Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
mDirty = true;
}
void setShadowSize(float shadowSize, float maxShadowSize) {
if (shadowSize < 0 || maxShadowSize < 0) {
throw new IllegalArgumentException("invalid shadow size");
}
shadowSize = toEven(shadowSize);
maxShadowSize = toEven(maxShadowSize);
if (shadowSize > maxShadowSize) {
shadowSize = maxShadowSize;
if (!mPrintedShadowClipWarning) {
mPrintedShadowClipWarning = true;
}
}
if (mRawShadowSize == shadowSize && mRawMaxShadowSize == maxShadowSize) {
return;
}
mRawShadowSize = shadowSize;
mRawMaxShadowSize = maxShadowSize;
mShadowSize = (int)(shadowSize * SHADOW_MULTIPLIER + mInsetShadow + .5f);
mMaxShadowSize = maxShadowSize + mInsetShadow;
mDirty = true;
invalidateSelf();
}
@Override
public boolean getPadding(Rect padding) {
int vOffset = (int) Math.ceil(calculateVerticalPadding(mRawMaxShadowSize, mCornerRadius,
mAddPaddingForCorners));
padding.set(0, vOffset, 0, 0);
return true;
}
static float calculateVerticalPadding(float maxShadowSize, float cornerRadius,
boolean addPaddingForCorners) {
if (addPaddingForCorners) {
return (float) (maxShadowSize * SHADOW_MULTIPLIER + (1 - COS_45) * cornerRadius);
} else {
return maxShadowSize * SHADOW_MULTIPLIER;
}
}
static float calculateHorizontalPadding(float maxShadowSize, float cornerRadius,
boolean addPaddingForCorners) {
if (addPaddingForCorners) {
return (float) (maxShadowSize + (1 - COS_45) * cornerRadius);
} else {
return maxShadowSize;
}
}
@Override
public void setColorFilter(ColorFilter cf) {
mPaint.setColorFilter(cf);
mCornerShadowPaint.setColorFilter(cf);
mEdgeShadowPaint.setColorFilter(cf);
}
@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
void setCornerRadius(float radius) {
radius = (int) (radius + .5f);
if (mCornerRadius == radius) {
return;
}
mCornerRadius = radius;
mDirty = true;
invalidateSelf();
}
@Override
public void draw(Canvas canvas) {
if (mDirty) {
buildComponents(getBounds());
mDirty = false;
}
canvas.translate(0, -mRawShadowSize / 2);
drawShadow(canvas);
canvas.translate(0, +mRawShadowSize / 2);
sRoundRectHelper.drawRoundRect(canvas, mCardBounds, mCornerRadius, mPaint);
}
private void drawShadow(Canvas canvas) {
final float edgeShadowTop = -mCornerRadius - mShadowSize;
final float insetVertical = mCornerRadius + mInsetShadow + mRawShadowSize / 2;
final float insetHorizontal = -mInsetShadow;
int saved = canvas.save();
canvas.translate(mCardBounds.left + insetHorizontal, mCardBounds.top + insetVertical);
canvas.drawPath(mCornerShadowPath, mCornerShadowPaint);
canvas.drawRect(0, edgeShadowTop,
mCardBounds.width() - 2 * insetHorizontal, -mCornerRadius + mShadowSize,
mEdgeShadowPaint);
canvas.restoreToCount(saved);
saved = canvas.save();
canvas.translate(mCardBounds.right - insetHorizontal, mCardBounds.top + insetVertical);
canvas.rotate(90f);
canvas.drawPath(mCornerShadowPath, mCornerShadowPaint);
canvas.restoreToCount(saved);
}
private void buildShadowCorners() {
RectF innerBounds = new RectF(-mCornerRadius, -mCornerRadius, mCornerRadius, mCornerRadius);
RectF outerBounds = new RectF(innerBounds);
outerBounds.inset(-mShadowSize, -mShadowSize);
if (mCornerShadowPath == null) {
mCornerShadowPath = new Path();
} else {
mCornerShadowPath.reset();
}
mCornerShadowPath.setFillType(Path.FillType.EVEN_ODD);
mCornerShadowPath.moveTo(-mCornerRadius, 0);
mCornerShadowPath.rLineTo(-mShadowSize, 0);
mCornerShadowPath.arcTo(outerBounds, 180f, 90f, false);
mCornerShadowPath.arcTo(innerBounds, 270f, -90f, false);
mCornerShadowPath.close();
float startRatio = mCornerRadius / (mCornerRadius + mShadowSize);
mCornerShadowPaint.setShader(new RadialGradient(0, 0, mCornerRadius + mShadowSize,
new int[]{mShadowStartColor, mShadowStartColor, mShadowEndColor},
new float[]{0f, startRatio, 1f}
, Shader.TileMode.CLAMP));
mEdgeShadowPaint.setShader(new LinearGradient(0, -mCornerRadius + mShadowSize, 0,
-mCornerRadius - mShadowSize,
new int[]{mShadowStartColor, mShadowStartColor, mShadowEndColor},
new float[]{0f, .5f, 1f}, Shader.TileMode.CLAMP));
mEdgeShadowPaint.setAntiAlias(false);
}
private void buildComponents(Rect bounds) {
final float verticalOffset = mRawMaxShadowSize * SHADOW_MULTIPLIER;
mCardBounds.set(bounds.left + mRawMaxShadowSize, bounds.top + verticalOffset,
bounds.right - mRawMaxShadowSize, bounds.bottom - verticalOffset);
buildShadowCorners();
}
float getCornerRadius() {
return mCornerRadius;
}
void getMaxShadowAndCornerPadding(Rect into) {
getPadding(into);
}
void setShadowSize(float size) {
setShadowSize(size, mRawMaxShadowSize);
}
void setMaxShadowSize(float size) {
setShadowSize(mRawShadowSize, size);
}
float getShadowSize() {
return mRawShadowSize;
}
float getMaxShadowSize() {
return mRawMaxShadowSize;
}
float getMinWidth() {
final float content = 2 *
Math.max(mRawMaxShadowSize, mCornerRadius + mInsetShadow + mRawMaxShadowSize / 2);
return content + (mRawMaxShadowSize + mInsetShadow) * 2;
}
float getMinHeight() {
final float content = 2 * Math.max(mRawMaxShadowSize, mCornerRadius + mInsetShadow
+ mRawMaxShadowSize * SHADOW_MULTIPLIER / 2);
return content + (mRawMaxShadowSize * SHADOW_MULTIPLIER + mInsetShadow) * 2;
}
public void setColor(int color) {
mPaint.setColor(color);
invalidateSelf();
}
static interface RoundRectHelper {
void drawRoundRect(Canvas canvas, RectF bounds, float cornerRadius, Paint paint);
}
}