You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Android中实现Bottom Sheet弧形背景?支持自定义View/XML方案

实现Bottom Sheet弧形顶部的三种实用方案

方案一:Shape Drawable XML(最简方案)

无需自定义View,直接通过XML绘制弧形背景,适合固定弧度的场景。

1. 定义弧形背景Drawable

在res/drawable下创建bottom_sheet_curved_bg.xml:

  • 若仅需顶部左右圆角:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <solid android:color="@color/white" />
    <corners
        android:topLeftRadius="32dp"
        android:topRightRadius="32dp"
        android:bottomLeftRadius="0dp"
        android:bottomRightRadius="0dp" />
</shape>
  • 若需顶部中间凸起/凹陷的弧形(用二次贝塞尔曲线):
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <solid android:color="@color/white" />
    <path
        android:fillColor="@color/white"
        android:pathData="M0,32 
        L0,0 
        L360,0 
        L360,32 
        Q180,0 180,32 
        Z" />
    <!-- Q为二次贝塞尔曲线,参数依次是控制点坐标、终点坐标,可按需调整数值 -->
</shape>

2. 应用到Bottom Sheet

将该Drawable设置为Bottom Sheet根布局的背景:

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/bottom_sheet_curved_bg">

    <!-- 此处放置Bottom Sheet的内容 -->
</androidx.constraintlayout.widget.ConstraintLayout>

方案二:自定义View(灵活可控)

如果需要动态调整弧度、颜色或添加交互,自定义View是最佳选择。

1. 编写自定义View类

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.View;

public class CurvedSheetHeader extends View {
    private Paint mFillPaint;
    private Path mCurvePath;
    private int mCurveHeight = 32; // 弧形高度,可通过方法动态修改

    public CurvedSheetHeader(Context context) {
        super(context);
        init();
    }

    public CurvedSheetHeader(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        mFillPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mFillPaint.setColor(getResources().getColor(R.color.white));
        mFillPaint.setStyle(Paint.Style.FILL);
        mCurvePath = new Path();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int viewWidth = getWidth();
        int viewHeight = getHeight();

        mCurvePath.reset();
        // 绘制顶部中间凸起的弧形
        mCurvePath.moveTo(0, viewHeight);
        mCurvePath.lineTo(0, mCurveHeight);
        // 二次贝塞尔曲线:起点(0, mCurveHeight),控制点(viewWidth/2, 0),终点(viewWidth, mCurveHeight)
        mCurvePath.quadTo(viewWidth / 2, 0, viewWidth, mCurveHeight);
        mCurvePath.lineTo(viewWidth, viewHeight);
        mCurvePath.close();

        canvas.drawPath(mCurvePath, mFillPaint);
    }

    // 动态调整弧形高度的方法
    public void setCurveHeight(int height) {
        mCurveHeight = height;
        invalidate();
    }
}

2. 在布局中使用

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <com.yourpackage.CurvedSheetHeader
        android:layout_width="match_parent"
        android:layout_height="32dp" />

    <!-- Bottom Sheet内容区域 -->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/white">
        <!-- 内容控件 -->
    </LinearLayout>
</LinearLayout>

方案三:Material Components 内置属性(适配MD风格)

如果你使用BottomSheetDialogFragment,可以直接利用Material Design的Shape属性快速实现。

1. 定义Shape样式

在res/values/styles.xml添加:

<style name="BottomSheetShapeStyle" parent="ShapeAppearance.MaterialComponents.LargeComponent">
    <item name="cornerFamily">rounded</item>
    <item name="cornerSizeTopLeft">32dp</item>
    <item name="cornerSizeTopRight">32dp</item>
    <item name="cornerSizeBottomLeft">0dp</item>
    <item name="cornerSizeBottomRight">0dp</item>
</style>

2. 应用到Bottom Sheet

方式一:代码中设置

在BottomSheetDialogFragment的onCreateDialog方法中修改:

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    BottomSheetDialog dialog = (BottomSheetDialog) super.onCreateDialog(savedInstanceState);
    dialog.setOnShowListener(dialogInterface -> {
        BottomSheetDialog bottomSheetDialog = (BottomSheetDialog) dialogInterface;
        FrameLayout bottomSheet = bottomSheetDialog.findViewById(com.google.android.material.R.id.design_bottom_sheet);
        if (bottomSheet != null) {
            MaterialShapeDrawable shapeDrawable = (MaterialShapeDrawable) bottomSheet.getBackground();
            shapeDrawable.setShapeAppearanceModel(shapeDrawable.getShapeAppearanceModel()
                    .toBuilder()
                    .setTopLeftCorner(CornerFamily.ROUNDED, 32)
                    .setTopRightCorner(CornerFamily.ROUNDED, 32)
                    .build());
        }
    });
    return dialog;
}

方式二:布局中直接引用

给Bottom Sheet根布局添加shapeAppearanceOverlay属性:

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/white"
    app:shapeAppearanceOverlay="@style/BottomSheetShapeStyle">

    <!-- 内容控件 -->
</LinearLayout>

内容的提问来源于stack exchange,提问作者Weylar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 08:27:08