Swift修改UINavigationBar阴影时UIBarButtonItem异常及透明态问题
问题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
相关产品推荐
相关产品推荐

