2

修饰符中的onFocusChange闭包focusable(_:onFocusChange:)允许我在子视图集中时为父视图设置属性,如下所示:

struct ContentView: View {
    @State var text: String
    var body: some View {
        VStack {
            Text(text)
            Text("top")
                .padding()
                .focusable(true, onFocusChange: { focused in
                    text = "top focus"
                })
            Text("bottom")
                .padding()
                .focusable(true, onFocusChange: { focused in
                    text = "bottom focus"
                })
        }
        
    }
}

但是在focusable介绍的 2020 WWDC 视频中,明确指出此包装器不打算与按钮和列表等本质上可聚焦的视图一起使用。如果我在这里使用 Button 代替 Text ,则 onFocusChange 可以工作,但是 Buttons 的正常焦点行为会中断:

struct ContentView: View {
    @State var text: String
    var body: some View {
        VStack {
            Text(text)
            Button("top") {}
                .padding()
                .focusable(true, onFocusChange: { focused in
                    text = "top focus"
                })
            Button("bottom") {}
                .padding()
                .focusable(true, onFocusChange: { focused in
                    text = "bottom focus"
                })
        }
        
    }
}

有什么通用方法可以让 onFocusChange 闭包与不破坏其正常可聚焦行为的按钮一起使用?还是有其他方法可以做到这一点?

4

1 回答 1

3

尝试在 ButtonStyle 中使用@Environment(\.isFocused)和:.onChange(of:perform:)

struct ContentView: View {
    var body: some View {
          Button("top") {
             // button action
          }
          .buttonStyle(MyButtonStyle())
    }
}

struct MyButtonStyle: ButtonStyle {
    @Environment(\.isFocused) var focused: Bool

    func makeBody(configuration: Configuration) -> some View {
        configuration.label
            .onChange(of: focused) { newValue in
                // do whatever based on focus
            }
    }
}

在 ButtonStyle 中使用的 IIRC@Environment(\.isFocused)可能仅适用于 iOS 14.5+,但您可以创建自定义视图而不是 ButtonStyle 以支持旧版本。

于 2021-04-15T02:02:26.413 回答