`UIResponder.keyboardWillShowNotification`是否在具有曲面屏幕的iOS设备上提供不正确的高度?

kyvafyod  于 12个月前  发布在  iOS
关注(0)|答案(2)|浏览(104)

我正在使用UIResponder.keyboardWillShowNotification和它提供的用户信息来执行手动键盘避免。有趣的是,我的方法在具有方形屏幕角落的设备上工作正常(iPhone SE 3rd Generation),但在具有弯曲角落屏幕的设备上不工作(例如iPhone 15 Pro Max)。当有弯曲角落时,高度似乎有点太大了。
我也试过计算容器底部安全区域的高度,但这个高度与我看到的额外高度不完全匹配。

import SwiftUI

struct ContentView: View {
    @State private var text = ""
    
    @State private var keyboardHeight: CGFloat = .zero
    
    var body: some View {
        VStack {
            TextField("Test", text: $text)
            Color.red
                .frame(height: keyboardHeight)
        }
        .animation(.default.delay(0), value: keyboardHeight)
        .frame(maxHeight: .infinity, alignment: .bottom)
        .ignoresSafeArea(.keyboard)
        .onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardWillShowNotification)) {
            keyboardHeight = ($0.userInfo![UIResponder.keyboardFrameEndUserInfoKey] as! CGRect).height
        }
        .onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardWillHideNotification)) { _ in
            keyboardHeight = .zero
        }
    }
}

字符串
带圆角的器械(不良):

带方角的器件(良好):

y53ybaqx

y53ybaqx1#

额外的高度来自容器的安全区域,该区域包含iPhone 15和其他型号上的“主页滑动栏”。
keyboardFrameEndUserInfoKey也包括容器的安全区域,但您只忽略了.keyboard安全区域,这就是为什么红色区域显示得比您预期的要高。
一种解决方法是根据键盘是否显示而忽略所有安全区域。

// replace the existing ignoresSafeArea modifier with this:
.ignoresSafeArea(keyboardHeight == 0 ? [] : .all)

字符串
或者,你可以避免使用NotificationCenter,在纯SwiftUI中这样做。你所需要的就是读取容器的安全区域,以及总的安全区域,然后从另一个中减去一个。

GeometryReader { total in // this is the total safe area, because no safe area is ignored
    GeometryReader { container in // this is the container safe area, because we ignored the keyboard safe area
        VStack {
            TextField("Test", text: $text)
            Color.red
                // we subtract it here:
                .frame(height: total.safeAreaInsets.bottom - container.safeAreaInsets.bottom)
        }
        .frame(maxHeight: .infinity, alignment: .bottom)
    }
    .ignoresSafeArea(.keyboard)
}

k0pti3hp

k0pti3hp2#

这是因为底部的安全区域。试试这个:

GeometryReader { geo in // <- wrap inside GeometryReader
    VStack {
        TextField("Test", text: $text)
            .autocorrectionDisabled(true)
        Color.red
            .frame(height: keyboardHeight)
    }
    .animation(.default.delay(0), value: keyboardHeight)
    .frame(maxHeight: .infinity, alignment: .bottom)
    .ignoresSafeArea(.keyboard)
    .onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardWillShowNotification)) {
        let height = ($0.userInfo![UIResponder.keyboardFrameEndUserInfoKey] as! CGRect).height
        keyboardHeight = height - geo.safeAreaInsets.bottom
    }
    .onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardWillHideNotification)) { _ in
        keyboardHeight = .zero
    }
}

字符串


的数据

相关问题