如何为Android布局添加100%圆角的彩色平滑阴影(兼容Android 4.3)
Hey there! I totally get the frustration with android:elevation not working on older Android versions, and third-party libraries not giving you the exact smooth, fully rounded, colored shadow you want. Let’s walk through a few solid, library-free approaches that work great on API 18 (Android 4.3) and up:
1. Use a LayerList Drawable (Simplest Static Solution)
This is the go-to method for static layouts. We’ll stack two rounded shapes: a shadow layer at the bottom, and your content layer on top. The key is matching corner radii and using padding to simulate shadow spread.
Create a new drawable file (res/drawable/layout_with_colored_shadow.xml):
<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <!-- Shadow layer: adjust color and padding for desired effect --> <item> <shape android:shape="rectangle"> <!-- Colored shadow with alpha (e.g., semi-transparent orange) --> <solid android:color="#40FF5722" /> <!-- Match corner radius of your content --> <corners android:radius="24dp" /> <!-- Padding = shadow size (pushes content layer up/away) --> <padding android:bottom="4dp" android:left="4dp" android:right="4dp" android:top="4dp" /> </shape> </item> <!-- Content layer: your actual layout background --> <item> <shape android:shape="rectangle"> <solid android:color="#FFFFFF" /> <!-- Same corner radius as shadow to avoid gaps --> <corners android:radius="24dp" /> <!-- Padding for your content inside the layout --> <padding android:bottom="16dp" android:left="16dp" android:right="16dp" android:top="16dp" /> </shape> </item> </layer-list>
Apply it to your layout:
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/layout_with_colored_shadow" android:orientation="vertical"> <!-- Add your text, buttons, etc., here --> </LinearLayout>
2. Dynamic LayerDrawable (For Runtime Changes)
If you need to adjust shadow color, radius, or size programmatically, build the LayerDrawable in code:
// Initialize shadow drawable GradientDrawable shadowDrawable = new GradientDrawable(); shadowDrawable.setShape(GradientDrawable.RECTANGLE); shadowDrawable.setColor(Color.parseColor("#402196F3")); // Blue shadow with alpha shadowDrawable.setCornerRadius(getResources().getDimension(R.dimen.corner_radius_24dp)); // Initialize content drawable GradientDrawable contentDrawable = new GradientDrawable(); contentDrawable.setShape(GradientDrawable.RECTANGLE); contentDrawable.setColor(Color.WHITE); contentDrawable.setCornerRadius(getResources().getDimension(R.dimen.corner_radius_24dp)); contentDrawable.setPadding( (int) getResources().getDimension(R.dimen.padding_16dp), (int) getResources().getDimension(R.dimen.padding_16dp), (int) getResources().getDimension(R.dimen.padding_16dp), (int) getResources().getDimension(R.dimen.padding_16dp) ); // Combine into LayerList and set insets LayerDrawable layerDrawable = new LayerDrawable(new Drawable[]{shadowDrawable, contentDrawable}); int shadowInset = (int) getResources().getDimension(R.dimen.shadow_size_4dp); layerDrawable.setLayerInset(1, shadowInset, shadowInset, shadowInset, shadowInset); // Apply to your view yourTargetView.setBackground(layerDrawable);
3. Custom View (For Full Control)
For more advanced scenarios (like dynamic shadow position or gradient shadows), create a custom view that draws the shadow directly on the canvas:
First, define custom attributes in res/values/attrs.xml:
<declare-styleable name="RoundedShadowView"> <attr name="cornerRadius" format="dimension" /> <attr name="shadowColor" format="color" /> <attr name="shadowSize" format="dimension" /> </declare-styleable>
Then create the custom view class:
public class RoundedShadowView extends FrameLayout { private Paint shadowPaint; private RectF shadowBounds; private float cornerRadius; private int shadowColor; private float shadowSize; public RoundedShadowView(Context context) { super(context); init(null); } public RoundedShadowView(Context context, AttributeSet attrs) { super(context, attrs); init(attrs); } private void init(AttributeSet attrs) { setLayerType(LAYER_TYPE_HARDWARE, null); // Enable hardware acceleration for smoothness // Load attributes from XML TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.RoundedShadowView); cornerRadius = ta.getDimension(R.styleable.RoundedShadowView_cornerRadius, 24); shadowColor = ta.getColor(R.styleable.RoundedShadowView_shadowColor, Color.parseColor("#40000000")); shadowSize = ta.getDimension(R.styleable.RoundedShadowView_shadowSize, 4); ta.recycle(); // Set up shadow paint shadowPaint = new Paint(Paint.ANTI_ALIAS_FLAG); shadowPaint.setColor(shadowColor); shadowPaint.setStyle(Paint.Style.FILL); shadowPaint.setShadowLayer(shadowSize, 0, shadowSize/2, shadowColor); // Blur, dx, dy, color // Add padding to make space for the shadow setPadding((int) shadowSize, (int) shadowSize, (int) shadowSize, (int) shadowSize); shadowBounds = new RectF(); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); // Adjust shadow bounds to account for padding shadowBounds.set(shadowSize, shadowSize, w - shadowSize, h - shadowSize); } @Override protected void onDraw(Canvas canvas) { // Draw shadow first, then the content canvas.drawRoundRect(shadowBounds, cornerRadius, cornerRadius, shadowPaint); super.onDraw(canvas); } }
Use it in your layout:
<com.yourpackage.RoundedShadowView android:layout_width="match_parent" android:layout_height="wrap_content" app:cornerRadius="24dp" app:shadowColor="#40FF9800" app:shadowSize="5dp"> <!-- Your content layout (match the corner radius!) --> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#FFFFFF" android:padding="16dp" android:orientation="vertical"> <!-- Your content here --> </LinearLayout> </com.yourpackage.RoundedShadowView>
Quick Tips
- Always match the corner radius between the shadow and content layers to avoid ugly gaps.
- Use semi-transparent colors (alpha values like
#40= 64/255) for shadows to keep them smooth and natural. - For extra softness, stack multiple shadow layers with varying opacity and sizes in the LayerList.
内容的提问来源于stack exchange,提问作者Abar New

