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

Swift修改UINavigationBar阴影时UIBarButtonItem异常及透明态问题

解决UINavigationBar阴影的两个常见问题

问题1:导航栏阴影覆盖UIBarButtonItem

直接给UINavigationBar的layer添加阴影会导致阴影层级高于BarButtonItem,回到顶部时出现覆盖。解决思路是将阴影独立到一个底层子视图中,让按钮控件保持在阴影上方:

func setCustomShadow() {
    // 移除已存在的阴影视图,避免重复添加
    self.subviews.first(where: { $0.tag == 999 })?.removeFromSuperview()
    
    let shadowView = UIView()
    shadowView.tag = 999
    shadowView.backgroundColor = .clear
    shadowView.layer.shadowColor = UIColor.red.cgColor
    shadowView.layer.shadowOpacity = 0.1
    shadowView.layer.shadowOffset = CGSize(width: 0, height: 5)
    shadowView.layer.shadowRadius = 0.25
    shadowView.translatesAutoresizingMaskIntoConstraints = false
    
    // 将阴影视图插入到导航栏子视图的最底层
    self.insertSubview(shadowView, at: 0)
    
    NSLayoutConstraint.activate([
        shadowView.leadingAnchor.constraint(equalTo: self.leadingAnchor),
        shadowView.trailingAnchor.constraint(equalTo: self.trailingAnchor),
        shadowView.topAnchor.constraint(equalTo: self.topAnchor),
        shadowView.bottomAnchor.constraint(equalTo: self.bottomAnchor)
    ])
}

这样阴影只会显示在导航栏背景层,不会覆盖顶部的按钮控件,滚动时的阴影效果保持不变。

问题2:透明导航栏下仍显示shadowImage

需要针对导航栏的透明/非透明状态,分别配置独立的UINavigationBarAppearance实例,透明状态下将shadowImage设为nil即可隐藏阴影:

// 配置非透明导航栏的外观
let nonTransparentAppearance = UINavigationBarAppearance()
nonTransparentAppearance.backgroundColor = .white
nonTransparentAppearance.shadowImage = UIImage(named: "custom_shadow_image")

// 配置透明导航栏的外观
let transparentAppearance = UINavigationBarAppearance()
transparentAppearance.configureWithTransparentBackground()
transparentAppearance.shadowImage = nil // 取消阴影显示

// 初始状态设置
if navigationBar.isTranslucent {
    navigationBar.standardAppearance = transparentAppearance
    navigationBar.scrollEdgeAppearance = transparentAppearance
    navigationBar.compactAppearance = transparentAppearance
} else {
    navigationBar.standardAppearance = nonTransparentAppearance
    navigationBar.scrollEdgeAppearance = nonTransparentAppearance
    navigationBar.compactAppearance = nonTransparentAppearance
}

// 如果需要在滚动时动态切换外观(比如滚动后导航栏从不透明变透明),在scrollView代理中更新
func scrollViewDidScroll(_ scrollView: UIScrollView) {
    let shouldBeTransparent = scrollView.contentOffset.y < 100 // 根据实际滚动阈值调整
    navigationBar.isTranslucent = shouldBeTransparent
    
    let targetAppearance = shouldBeTransparent ? transparentAppearance : nonTransparentAppearance
    navigationBar.standardAppearance = targetAppearance
    navigationBar.scrollEdgeAppearance = targetAppearance
    navigationBar.compactAppearance = targetAppearance
}

核心是为两种状态创建独立的外观配置,确保透明状态下阴影完全隐藏,非透明状态加载自定义阴影图。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 20:25:11