You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android带阴影的弧形Toolbar/CardView实现问题

实现Toolbar/CardView底部弧形并保留正确阴影效果

我来帮你搞定这个问题——自定义弧形背景后丢失阴影或者阴影不贴合的情况确实很常见,咱们分两种控件分别解决:

一、Toolbar 底部弧形 + 保留阴影

你之前用layer-list作为背景导致elevation失效,是因为自定义背景会覆盖Toolbar默认的阴影实现。这里给你两种可行方案:

方案1:用AppBarLayout包裹(快速实现)

这种方法最简单,把Toolbar放在AppBarLayout里,让AppBarLayout负责显示阴影,Toolbar只专注于展示弧形背景:

<com.google.android.material.appbar.AppBarLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:elevation="8dp">

    <androidx.appcompat.widget.Toolbar
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="@drawable/bg_toolbar" />

</com.google.android.material.appbar.AppBarLayout>

方案2:自定义OutlineProvider(阴影精准贴合弧形)

如果想要阴影完全跟着弧形轮廓走,就给Toolbar设置自定义轮廓提供者:

  1. 保留你原来的bg_toolbar.xml背景不变
  2. 在代码中添加如下逻辑:
val toolbar = findViewById<Toolbar>(R.id.toolbar)
toolbar.outlineProvider = object : ViewOutlineProvider() {
    override fun getOutline(view: View, outline: Outline) {
        // 这里的参数要和你layer-list里的椭圆参数对应
        val dp100 = 100.dpToPx(view.context)
        val dp80 = 80.dpToPx(view.context)
        outline.setRoundRect(
            -dp100,
            -dp80,
            view.width + dp100,
            view.height,
            (view.height + dp80).toFloat()
        )
    }
}
toolbar.clipToOutline = true
toolbar.elevation = 8.dpToPx(view.context).toFloat()

// 辅助扩展函数:dp转px
fun Int.dpToPx(context: Context): Int {
    return (this * context.resources.displayMetrics.density).toInt()
}

二、CardView 底部弧形 + 阴影贴合

CardView的阴影是基于自身形状生成的,默认矩形圆角的阴影自然不会贴合自定义弧形。推荐用MaterialCardView配合自定义形状实现:

  1. 创建自定义弧形形状资源shape_card_bottom_arc.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" />
    <!-- pathData定义底部弧形,可调整A后面的两个数值改变弧形大小 -->
    <path
        android:fillColor="@color/white"
        android:pathData="M0,0 L0,H LW,H LW,0 A120,120 0 0 1 0,0 Z" />
</shape>
  1. 在布局中使用MaterialCardView并关联自定义形状:
<com.google.android.material.card.MaterialCardView
    android:layout_width="match_parent"
    android:layout_height="220dp"
    app:cardElevation="8dp"
    app:shapeAppearance="@style/CardBottomArcStyle">

    <!-- 这里放CardView的内部内容 -->

</com.google.android.material.card.MaterialCardView>
  1. 在styles.xml中定义对应的形状样式:
<style name="CardBottomArcStyle" parent="ShapeAppearance.MaterialComponents.CardView">
    <item name="android:background">@drawable/shape_card_bottom_arc</item>
</style>

这样设置后,CardView的阴影就会完全贴合底部弧形的轮廓了。

内容的提问来源于stack exchange,提问作者Hamza Ahmed Khan

火山引擎 最新活动