如何实现图片作为Toolbar背景并超出其边界的效果?
嘿,这个需求我之前也碰到过!想用标准Toolbar实现背景超出边界的半圆效果,其实核心是让Toolbar的背景Drawable突破它本身的布局边界,同时调整Toolbar的内边距来保证标题/图标不被遮挡。下面给你几个靠谱的实现思路:
方法一:自定义背景Drawable(推荐)
直接给Toolbar设置一个带有半圆的Drawable,让这个Drawable的尺寸比Toolbar本身大,再通过父布局的属性允许超出部分显示。
- 在
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>
- 在布局文件中配置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
相关产品推荐
相关产品推荐

