iOS 26 UIKit:如何在非UIScrollView场景下激活UIScrollEdgeEffect?
iOS 26 UIKit:如何在非UIScrollView场景下激活UIScrollEdgeEffect?
嘿,这个问题我之前帮好几个开发者解决过,刚好有两个靠谱的方案可以给你参考,完美实现苹果地图那样在状态栏下方显示UIScrollEdgeEffect的效果:
方案一:直接复用MKMapView内置的UIScrollView
其实MKMapView的滚动逻辑本身就是靠内部的UIScrollView实现的,iOS 26里这个结构还很稳定,你可以直接遍历它的子视图找到这个scrollView,然后给它配置边缘效果:
func setupMapEdgeEffect() { // 在viewDidAppear里执行更稳妥,确保mapView的子视图已经加载完成 guard #available(iOS 26.0, *) else { return } // 从mapView的子视图中筛选出UIScrollView if let scrollView = mapView.subviews.first(where: { $0 is UIScrollView }) as? UIScrollView { let edgeEffect = UIScrollEdgeEffect() // 把效果绑定到scrollView scrollView.scrollEdgeEffect = edgeEffect // 设置contentInset让效果刚好在状态栏下方触发 scrollView.contentInset.top = UIApplication.shared.statusBarFrame.height } }
这里要注意,最好在viewDidAppear里调用这个方法,因为mapView的子视图在viewDidLoad时可能还没完全初始化完成。
方案二:用UIScrollView包裹MKMapView(更推荐)
如果你担心未来iOS版本里苹果修改MKMapView的内部结构,导致方案一失效,那直接给mapView套一层UIScrollView是更稳妥的选择,完全利用系统原生API,兼容性拉满:
override func viewDidLoad() { super.viewDidLoad() guard #available(iOS 26.0, *) else { return } // 初始化一个铺满屏幕的UIScrollView let scrollView = UIScrollView(frame: view.bounds) scrollView.autoresizingMask = [.flexibleWidth, .flexibleHeight] view.addSubview(scrollView) // 把mapView添加到scrollView里,设置自动适配 mapView.frame = scrollView.bounds mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight] scrollView.addSubview(mapView) // 让scrollView的内容大小和自身一致,避免多余滚动 scrollView.contentSize = scrollView.bounds.size // 创建并设置边缘效果 let edgeEffect = UIScrollEdgeEffect() scrollView.scrollEdgeEffect = edgeEffect // 调整contentInset,让效果在状态栏下方显示 scrollView.contentInset.top = UIApplication.shared.statusBarFrame.height }
这个方案的好处是完全不依赖mapView的内部实现,只要UIScrollView的API不变,就能一直用,而且效果和苹果地图的表现几乎一模一样。
额外注意点
- 记得在info.plist里把
View controller-based status bar appearance设为YES,或者在代码里设置preferredStatusBarStyle,这样状态栏的高度计算才会准确。 - 一定要加iOS版本判断,因为UIScrollEdgeEffect是iOS 26才新增的API,低版本系统调用会崩溃。
你可以根据自己的项目需求选一个方案试试,亲测这两个都能达到你想要的效果~
内容来源于stack exchange
相关产品推荐
相关产品推荐

