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

如何实现图片作为Toolbar背景并超出其边界的效果?

嘿,这个需求我之前也碰到过!想用标准Toolbar实现背景超出边界的半圆效果,其实核心是让Toolbar的背景Drawable突破它本身的布局边界,同时调整Toolbar的内边距来保证标题/图标不被遮挡。下面给你几个靠谱的实现思路:

方法一:自定义背景Drawable(推荐)

直接给Toolbar设置一个带有半圆的Drawable,让这个Drawable的尺寸比Toolbar本身大,再通过父布局的属性允许超出部分显示。

  1. 在res/drawable目录下创建toolbar_background.xml:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- Toolbar主体矩形背景 -->
    <item>
        <shape android:shape="rectangle">
            <solid android:color="#FF4081" /> <!-- 替换成你的Toolbar颜色 -->
        </shape>
    </item>
    <!-- 底部超出的半圆:通过负margin让它向下延伸出Toolbar边界 -->
    <item 
        android:bottom="-30dp" 
        android:left="40dp" 
        android:right="40dp">
        <shape android:shape="oval">
            <solid android:color="#FF4081" />
            <size android:height="60dp" /> <!-- 半圆直径,对应负margin的2倍 -->
        </shape>
    </item>
</layer-list>
  1. 在布局文件中配置Toolbar和父容器:
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:clipChildren="false"
    android:clipToPadding="false">

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="@drawable/toolbar_background"
        android:paddingBottom="30dp" /> <!-- 给底部加padding,避免内容被半圆遮挡 -->
</LinearLayout>

关键是父布局要开启clipChildren="false"和clipToPadding="false",不然超出的半圆会被自动裁剪掉。

方法二:自定义Toolbar类(动态场景适用)

如果需要动态调整半圆的大小、位置,可以直接继承标准Toolbar,在onDraw里手动绘制半圆:

class CustomToolbar @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = androidx.appcompat.R.attr.toolbarStyle
) : androidx.appcompat.widget.Toolbar(context, attrs, defStyleAttr) {

    private val bgPaint = Paint().apply {
        color = ContextCompat.getColor(context, R.color.toolbar_color)
        isAntiAlias = true
    }
    private val semiCircleRadius = 60f // 半圆半径

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        // 先画Toolbar的矩形背景
        canvas.drawRect(0f, 0f, width.toFloat(), height.toFloat(), bgPaint)
        // 画下半圆:中心在Toolbar底部正中间,向下延伸出半径长度
        val centerX = width / 2f
        val centerY = height + semiCircleRadius
        canvas.drawArc(
            centerX - semiCircleRadius,
            centerY - semiCircleRadius,
            centerX + semiCircleRadius,
            centerY + semiCircleRadius,
            0f,
            180f,
            true,
            bgPaint
        )
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        // 调整测量高度,把半圆的高度算进去,避免被父布局裁剪
        val newHeight = MeasureSpec.getSize(heightMeasureSpec) + semiCircleRadius.toInt()
        val newHeightSpec = MeasureSpec.makeMeasureSpec(newHeight, MeasureSpec.getMode(heightMeasureSpec))
        super.onMeasure(widthMeasureSpec, newHeightSpec)
    }
}

之后在布局里直接使用这个CustomToolbar,同样要给父布局加上clipChildren="false"和clipToPadding="false",并调整Toolbar的内边距保证内容可见。

重要注意事项
  • 如果Toolbar嵌套在AppBarLayout里,别忘了给AppBarLayout也设置clipChildren="false"和clipToPadding="false",不然AppBarLayout会裁剪超出部分。
  • 调整Toolbar的padding值时,要和半圆的半径对应,确保标题、菜单图标等内容不会被遮挡。

这样就能用标准Toolbar(或基于它的自定义扩展)实现你要的背景超出边界的效果啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 10:10:48