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

KMM iOS场景下如何检测用户点击状态栏?

可行,解决方案如下

你的onTapGesture没触发的原因是:状态栏属于系统层级区域,不在SwiftUI视图的响应链范围内,直接给RootView加手势无法捕获状态栏的点击事件。要实现这个功能,需要借助iOS原生事件处理机制,结合通知来触发页面滚动回到顶部的逻辑,具体有两种方案:

方案一:自定义UIWindow监听状态栏点击

通过替换默认UIWindow,在事件传递时判断点击是否命中状态栏区域:

  1. 自定义UIWindow子类,拦截点击并发送通知:
class StatusBarTapWindow: UIWindow {
    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        guard let statusBarFrame = windowScene?.statusBarManager?.statusBarFrame else {
            return super.hitTest(point, with: event)
        }
        // 转换点击坐标到状态栏所在窗口的坐标系
        let statusBarWindowPoint = convert(point, to: windowScene?.statusBarManager?.statusBarWindow)
        if statusBarFrame.contains(statusBarWindowPoint) {
            NotificationCenter.default.post(name: .statusBarTapped, object: nil)
            return nil // 不拦截其他区域的事件传递
        }
        return super.hitTest(point, with: event)
    }
}

// 定义通知常量,避免拼写错误
extension NSNotification.Name {
    static let statusBarTapped = NSNotification.Name("StatusBarTapped")
}
  1. 在Scene配置中使用自定义Window:
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    guard let windowScene = scene as? UIWindowScene else { return }
    let window = StatusBarTapWindow(windowScene: windowScene)
    let rootView = RootView(root: appDelegate.root)
        .edgesIgnoringSafeArea(.all)
    window.rootViewController = UIHostingController(rootView: rootView)
    self.window = window
    window.makeKeyAndVisible()
}

方案二:通过UIApplication扩展监听

无需自定义Window,直接扩展UIApplication捕获状态栏点击:

extension UIApplication {
    open override func sendAction(_ action: Selector, to target: Any?, from sender: Any?, for event: UIEvent?) -> Bool {
        if action == #selector(handleStatusBarTap) {
            NotificationCenter.default.post(name: .statusBarTapped, object: nil)
            return true
        }
        return super.sendAction(action, to: target, from: sender, for: event)
    }
    
    @objc private func handleStatusBarTap() {}
}

extension NSNotification.Name {
    static let statusBarTapped = NSNotification.Name("StatusBarTapped")
}

页面响应通知实现滚动回到顶部

SwiftUI页面示例

结合ScrollViewProxy实现滚动:

struct ListPage: View {
    @State private var scrollProxy: ScrollViewProxy?
    
    var body: some View {
        ScrollView {
            ScrollViewReader { proxy in
                VStack {
                    // 列表内容
                }
                .onAppear {
                    scrollProxy = proxy
                }
            }
        }
        .onReceive(NotificationCenter.default.publisher(for: .statusBarTapped)) { _ in
            scrollProxy?.scrollTo(0, anchor: .top)
        }
    }
}

Kotlin Multiplatform Compose页面示例

在iOS平台代码中监听通知,通过ViewModel触发滚动:

// 在iOS平台的Compose页面初始化时添加监听
NotificationCenter.default.addObserver(
    forName = NSNotification.Name("StatusBarTapped"),
    object : NSObject() {
        @ObjCAction
        fun onStatusBarTapped() {
            viewModel.scrollToTop()
        }
    }
)

// Compose列表响应ViewModel事件
LazyColumn {
    // 列表项
}
.animateScrollToTop(viewModel.scrollToTopEvent)

注意事项

  • 确保状态栏未被自定义视图完全覆盖,否则点击事件会被拦截
  • 通知名字建议用常量定义,避免拼写错误
  • KMM项目中,可通过共享ViewModel的状态流跨平台传递滚动事件,替代通知机制

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 10:48:12