iOS / SwiftUI 输入法(键盘)布局处理总结(AI版)

文章目录

📘 iOS / SwiftUI 输入法(键盘)处理总结


一、问题背景

在 iOS / SwiftUI 开发中,常见输入法问题:

  • 输入框切换时键盘闪烁
  • 键盘弹出/收起动画不自然
  • 无法像 Android WindowInsetsAnimation 一样平滑跟随

二、输入框切换闪烁问题

❌ 错误原因

swift 复制代码
focusedField = nil
focusedField = .password

解决办法

swift 复制代码
enum Field {
    case username
    case password
}

@FocusState private var focusedField: Field?

TextField("用户名", text: $username)
    .focused($focusedField, equals: .username)

SecureField("密码", text: $password)
    .focused($focusedField, equals: .password)

❗ 注意

不要先设为 nil

不要手动关闭键盘

使用系统焦点切换

键盘动画(类似 Android Insets)

uikit

swift 复制代码
@objc func keyboardWillChangeFrame(_ notification: Notification) {
    guard let userInfo = notification.userInfo else { return }
    
    let duration = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double ?? 0.25
    let curveRaw = userInfo[UIResponder.keyboardAnimationCurveUserInfoKey] as? UInt ?? 0
    let curve = UIView.AnimationOptions(rawValue: curveRaw << 16)
    
    let frame = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect ?? .zero
    let keyboardHeight = UIScreen.main.bounds.height - frame.origin.y
    
    UIView.animate(withDuration: duration, delay: 0, options: curve) {
        self.bottomConstraint.constant = keyboardHeight
        self.view.layoutIfNeeded()
    }
}

swiftUI

  1. 推荐
swift 复制代码
.safeAreaInset(edge: .bottom) {
    Color.clear.frame(height: 0)
}
  1. combine
swift 复制代码
class KeyboardObserver: ObservableObject {
    @Published var height: CGFloat = 0
    
    private var cancellables = Set<AnyCancellable>()
    
    init() {
        NotificationCenter.default.publisher(for: UIResponder.keyboardWillChangeFrameNotification)
            .map { notification -> CGFloat in
                let frame = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect ?? .zero
                return UIScreen.main.bounds.height - frame.origin.y
            }
            .assign(to: \.height, on: self)
            .store(in: &cancellables)
    }
}

struct ContentView: View {
    @StateObject var keyboard = KeyboardObserver()
    
    var body: some View {
        VStack {
            Spacer()
            
            TextField("输入", text: .constant(""))
                .textFieldStyle(.roundedBorder)
        }
        .padding(.bottom, keyboard.height)
        .animation(.easeOut(duration: 0.25), value: keyboard.height)
    }
}
相关推荐
茶底世界之下3 天前
为什么预览、录制、离线导出不能共享同一个背压策略?
ios·swift
2501_916007473 天前
苹果商店iOS应用上架费用全面解析:开发者计划与审核费用计算
android·ios·小程序·https·uni-app·iphone·webview
2501_916008893 天前
如何实现iOS App代码混淆:SwiftShield使用指南
android·ios·小程序·https·uni-app·iphone·webview
2501_915909063 天前
移动端开发工具链怎么组合比较好,iOS、Android、跨端三套配置方案
ide·vscode·ios·objective-c·个人开发·swift·敏捷流程
东坡肘子3 天前
一场关于 SwiftUI 动画的“原生”之争 -- 肘子的 Swift 周报 #154
人工智能·swiftui·swift
2501_916008893 天前
怎么用 Godot 导出 iOS 应用并上架 App Store?签名字段该填什么?
android·ios·小程序·https·uni-app·iphone·webview
2501_915918414 天前
iOS编程用什么软件好?主流工具Xcode、AppCode、CodeRunner与新兴快蝎对比
ide·vscode·ios·objective-c·个人开发·swift·敏捷流程
终端安全笔记4 天前
iOS 27 之后「策略空转」:设备升级不报错,但旧策略不再管它
android·网络·安全·ios·智能手机
9765033354 天前
iOS 上架 4.3a 被拒【uniapp专讲】
flutter·ios·objective-c·uniapp·swift
黑化旺仔5 天前
【OC】KVO
macos·ios·objective-c·cocoa