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

SwiftUI中如何将父视图onHover事件传递给子视图?

解决SwiftUI中父视图Hover事件传递给子视图的问题

问题场景

我有两个独立视图(Checkbox和Card),各自带有onHover监听器。当Card内部包含Checkbox时,希望父视图的hover事件能传递给子视图——目前只有直接悬停在Checkbox上时,它的hover事件才会触发。同时不想使用Binding,因为Checkbox作为独立视图使用时不需要绑定值。

原代码如下:

struct Checkbox: View {
    @State private var isHovered = false

    var body: some View {
        Circle()
            .background(isHovered ? .red : .blue)
            .onHover { isHovered in
                self.isHovered = isHovered
            }
    }
}

struct Card: View {
    @State private var isHovered = false

    var body: some View {
        HStack {
            Text("Label")
            Checkbox()
        }
        .onHover(perform: { isHovered in
            self.isHovered = isHovered
        })
        .background(isHovered ? .red : .blue)
    }
}

解决方案一:可选参数传递状态

给Checkbox添加一个可选的外部hover状态参数,默认使用自身的@State变量,兼顾独立使用和被包含时的需求:

struct Checkbox: View {
    // 可选外部hover状态,默认nil时使用内部状态
    var externalHovered: Bool? = nil
    @State private var internalHovered = false
    
    // 合并内部与外部的hover状态
    private var isHovered: Bool {
        externalHovered ?? internalHovered
    }

    var body: some View {
        Circle()
            .background(isHovered ? .red : .blue)
            .onHover { isHovered in
                internalHovered = isHovered
            }
    }
}

struct Card: View {
    @State private var isHovered = false

    var body: some View {
        HStack {
            Text("Label")
            // 将父视图的hover状态传递给子视图
            Checkbox(externalHovered: isHovered)
        }
        .onHover(perform: { isHovered in
            self.isHovered = isHovered
        })
        .background(isHovered ? .red : .blue)
    }
}

说明

  • Checkbox独立使用时,externalHovered保持默认nil,完全依赖自身的internalHovered状态,无需额外配置。
  • 被Card包含时,传递父视图的isHovered状态,实现父视图hover时子视图同步响应。

解决方案二:环境变量传递(适合复杂层级)

如果视图层级较深,使用环境变量可以避免逐个传递参数的繁琐:

// 自定义环境键
private struct ParentHoveredKey: EnvironmentKey {
    static let defaultValue: Bool = false
}

// 扩展环境值,添加父视图hover状态属性
extension EnvironmentValues {
    var parentHovered: Bool {
        get { self[ParentHoveredKey.self] }
        set { self[ParentHoveredKey.self] = newValue }
    }
}

struct Checkbox: View {
    @State private var internalHovered = false
    // 读取环境中的父视图hover状态
    @Environment(\.parentHovered) private var parentHovered
    
    private var isHovered: Bool {
        parentHovered || internalHovered
    }

    var body: some View {
        Circle()
            .background(isHovered ? .red : .blue)
            .onHover { isHovered in
                internalHovered = isHovered
            }
    }
}

struct Card: View {
    @State private var isHovered = false

    var body: some View {
        HStack {
            Text("Label")
            Checkbox()
        }
        .onHover(perform: { isHovered in
            self.isHovered = isHovered
        })
        .background(isHovered ? .red : .blue)
        // 设置环境中的父视图hover状态
        .environment(\.parentHovered, isHovered)
    }
}

说明

  • 通过自定义环境键,Card将自身的hover状态注入环境,所有子视图都可以读取该状态。
  • Checkbox合并自身内部hover状态与环境中的父视图状态,实现同步响应。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 05:12:20