仅当键盘阻止 UITextField / UITextView 时才向上移动 UIView

Posted

技术标签:

【中文标题】仅当键盘阻止 UITextField / UITextView 时才向上移动 UIView【英文标题】:Moving UIView up only when the keyboard blocks the UITextField / UITextView 【发布时间】:2021-11-30 20:11:48 【问题描述】:

这已经被问过几次了:1234

这些线程没有提供我正在寻找的解决方案,并且随着 Swift 5 的发布而变得有点过时,所以我在下面发布了我的解决方案。

【问题讨论】:

【参考方案1】:

我建议使用 IQKeyboardManagerSwift(或用 ObjC 编写的 IQKeyboardManager)库,您可以使用 cocoapods 安装该库,链接中包含所有教程。对我来说,定制解决方案效果更好。这是该库的 2 个版本,ObjC 和 Swift:

Swift 版本:https://cocoapods.org/pods/IQKeyboardManagerSwift

ObjC 版本:https://cocoapods.org/pods/IQKeyboardManager

【讨论】:

【参考方案2】:

这是我目前的解决方案:

import UIKit

// For UITextViews, exact same code, but using UITextViewDelegate
class viewController: UIViewController, UITextFieldDelegate 
    @IBOutlet weak var textField: UITextField!
    
    // Keeps track of our editing frame
    // Kept it as a CGRect so that it can work with both UITextFields and UITextViews
    var editingFrame: CGRect?

    override func viewDidLoad() 
        super.viewDidLoad()
        
        // Set the delegate for the textField(s)
        textField.delegate = self
        
        // Add notification observers for keyboard
        NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillChangeFrame(notification:)), name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
    
    
    func textFieldDidBeginEditing(_ textField: UITextField) 
        editingFrame = textField.frame
        
        // This is the bit that is important, especially if you have
        // your textfield inside another view (UIStackViews for example)
        // The loop essentially goes through each successive superview the textfield has
        // and redefines the centre in that superview's frame of reference
        var currentView: UIView? = textField.superview
        while currentView != nil 
            editingFrame?.origin.x += currentView?.frame.origin.x ?? CGFloat(0.0)
            editingFrame?.origin.y += currentView?.frame.origin.y ?? CGFloat(0.0)
            currentView = currentView?.superview
        
    
    
    func textFieldShouldEndEditing(_ textField: UITextField) -> Bool 
        editingFrame = nil
        return true
    
    
    func textFieldShouldReturn(_ textField: UITextField) -> Bool 
        view.endEditing(true)
        return true
    
    
    @objc func keyboardWillChangeFrame(notification: Notification) 
        if let editingFrame = editingFrame 
            if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect) 
                let offset = editingFrame.maxY - keyboardSize.minY
                if offset > self.view.frame.origin.y 
                    self.view.frame.origin.y -= offset
                 else 
                    if self.view.frame.origin.y != 0 
                        self.view.frame.origin.y = 0
                    
                
            
         else 
            if self.view.frame.origin.y != 0 
                self.view.frame.origin.y = 0
            
        
    
    
    @objc func endEditingTextFields() 
        view.endEditing(true)
    

【讨论】:

以上是关于仅当键盘阻止 UITextField / UITextView 时才向上移动 UIView的主要内容,如果未能解决你的问题,请参考以下文章

TextField 没有被键盘顺利推上,就像在 Whatsapp 和环聊中一样

静态表视图 - 键盘隐藏的 UITextField

如何阻止我的自定义键盘在 iPad 上“浮动”或脱离

UITextField 拒绝允许用户输入

将 UITextField 添加到 UITableViewCell

以核心数据实体作为属性的子类 UITextField