SwiftUI 去掉右键选择的 Focus的默认边框

10 min read

在SwiftUI中,你可以使用.focusable()修饰符为可聚焦的视图添加聚焦和选择行为。默认情况下,当你右键点击一个已聚焦的视图时,会显示一个边框。你可以通过以下步骤去掉这个边框:

  1. 在视图上添加一个.onTapGesture {}处理程序,以确保视图已聚焦。

  2. 在处理程序中使用.resignFirstResponder()方法撤销第一响应者状态,这将取消显示边框。

以下是一个示例代码:

struct ContentView: View {
    @State private var isFocused = false
    
    var body: some View {
        VStack {
            Text("Hello, World!")
                .focusable(true) { isFocused = $0 }
                .onTapGesture { isFocused = true }
                .onAppear { isFocused = true }
                .resignKeyboardOnTap()
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(Color.white)
        .gesture(TapGesture().onEnded { isFocused = false })
    }
}

private struct ResignKeyboardOnTap: ViewModifier {
    var isFirstResponder: Binding<Bool>?
    let gesture = TapGesture().onEnded { UIApplication.shared.endEditing() }

    func body(content: Content) -> some View {
        content
            .gesture(gesture) .onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardWillShowNotification)) {_ in
                isFirstResponder?.wrappedValue = true
            }
            .onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardWillHideNotification)) {_ in
                isFirstResponder?.wrappedValue = false
            }
    }
}


extension View {

    func resignFirstResponder(isFirstResponder: Binding<Bool>? = nil) -> some View {
        let binding = isFirstResponder ?? Binding.constant(false)
        return modifier(ResignKeyboardOnTap(isFirstResponder: binding))
    }
}

在此示例中,我们在文本视图上添加了一个.onTapGesture {}处理程序,要求它在聚焦时调用。然后,我们使用.resignFirstResponder()方法来处理这个处理程序,并在视图被点击时取消第一响应者状态。我还添加了一个.onAppear {}处理程序来确保这个视图聚焦,并一个.gesture {} 修改器来确保当用户从视图中提出手指时取消聚焦状态。

希望这能帮到你。