如何使用 SwiftUI 在多个屏幕上获取键盘高度并移动按钮

Ika*_*Ika 9 iphone ios swift swiftui xcode11

以下代码获取键盘显示时的键盘高度,并按键盘高度移动按钮。

此移动在转换源 (ContentView) 和转换目标 (SecibdContentView) 处以相同方式执行,但按钮在转换目标处不移动。

如何使按钮在多个屏幕上移动相同?

import SwiftUI

struct ContentView: View {
    @ObservedObject private var keyboard = KeyboardResponder()

    var body: some View {
        NavigationView {
            VStack {
                Text("ContentView")

                Spacer()

                NavigationLink(destination: SecondContentView()) {
                    Text("Next")
                }
                .offset(x: 0, y: -keyboard.currentHeight)
            }
        }
    }
}

import SwiftUI

struct SecondContentView: View {
    @ObservedObject private var keyboard = KeyboardResponder()

    var body: some View {
        VStack {
            Text("SubContentView")

            Spacer()

            NavigationLink(destination: ThirdContentView()) {
                Text("Next")
            }
            .offset(x: 0, y: -keyboard.currentHeight)
        }
    }
}

class KeyboardResponder: ObservableObject {
    private var _center: NotificationCenter
    @Published var currentHeight: CGFloat = 0

    init(center: NotificationCenter = .default) {
        _center = center
        _center.addObserver(self, selector: #selector(keyBoardWillShow(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
        _center.addObserver(self, selector: #selector(keyBoardWillHide(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil)
    }

    deinit {
        _center.removeObserver(self)
    }

    @objc func keyBoardWillShow(notification: Notification) {
        if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
            currentHeight = keyboardSize.height
        }
    }

    @objc func keyBoardWillHide(notification: Notification) {
        currentHeight = 0
    }
}
Run Code Online (Sandbox Code Playgroud)

Nic*_*uez 19

使用 ViewModifier

你可以使用 swiftui 的 ViewModifier 就简单多了

import SwiftUI
import Combine

struct KeyboardAwareModifier: ViewModifier {
    @State private var keyboardHeight: CGFloat = 0

    private var keyboardHeightPublisher: AnyPublisher<CGFloat, Never> {
        Publishers.Merge(
            NotificationCenter.default
                .publisher(for: UIResponder.keyboardWillShowNotification)
                .compactMap { $0.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue }
                .map { $0.cgRectValue.height },
            NotificationCenter.default
                .publisher(for: UIResponder.keyboardWillHideNotification)
                .map { _ in CGFloat(0) }
       ).eraseToAnyPublisher()
    }

    func body(content: Content) -> some View {
        content
            .padding(.bottom, keyboardHeight)
            .onReceive(keyboardHeightPublisher) { self.keyboardHeight = $0 }
    }
}

extension View {
    func KeyboardAwarePadding() -> some View {
        ModifiedContent(content: self, modifier: KeyboardAwareModifier())
    }
}
Run Code Online (Sandbox Code Playgroud)

在你看来

struct SomeView: View {
    @State private var someText: String = ""

    var body: some View {
        VStack {
            Spacer()
            TextField("some text", text: $someText)
        }.KeyboardAwarePadding()
    }
}
Run Code Online (Sandbox Code Playgroud)

KeyboardAwarePadding() 将自动在您的视图中添加一个填充,它更优雅。