【问题标题】:Move textfield when keyboard appears swift当键盘快速出现时移动文本字段
【发布时间】:2014-10-30 20:02:51
【问题描述】:

我正在使用 Swift 进行 iOS 编程,我正在使用此代码移动 UITextField,但它不起作用。我正确调用了函数keyboardWillShow,但文本字段没有移动。我正在使用自动布局。

override func viewDidLoad() {
    super.viewDidLoad()
    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name:UIKeyboardWillShowNotification, object: nil);
    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name:UIKeyboardWillHideNotification, object: nil);
}

deinit {
    NSNotificationCenter.defaultCenter().removeObserver(self);
}

func keyboardWillShow(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
        //let contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height, right: 0)

        var frame = self.ChatField.frame
        frame.origin.y = frame.origin.y - keyboardSize.height + 167
        self.chatField.frame = frame
        println("asdasd")
    }
}

【问题讨论】:

标签: ios swift cocoa-touch keyboard uitextfield


【解决方案1】:

如果您像我一样,在模拟器上运行应用程序时使用自动布局而不是键盘。这可能是因为 Apple 让您使用您计算机的键盘作为第一个键盘。

要使设备中的键盘出现:

shift + cmd + K

听起来很愚蠢,但我很想在 3 小时前找到这个答案 :)

【讨论】:

    【解决方案2】:

    这是所有 TextField 的通用解决方案 步骤 -

    1) 创建一个由其他 ViewController 扩展的通用 ViewController

    override func viewDidLoad() {
        super.viewDidLoad()
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
    
    }
     @objc func keyboardWillShow(notification: NSNotification) {
        if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
            if self.view.frame.origin.y == 0 {
                self.view.frame.origin.y -= getMoveableDistance(keyboarHeight: keyboardSize.height)
            }
        }
    }
    
    @objc func keyboardWillHide(notification: NSNotification) {
        if self.view.frame.origin.y != 0 {
            self.view.frame.origin.y = 0
        }
    }
    deinit {
        NotificationCenter.default.removeObserver(self)
    }
    
    //get the distance to move up the main view for the focus textfiled
    func getMoveableDistance(keyboarHeight : CGFloat) ->  CGFloat{
        var y:CGFloat = 0.0
        if let activeTF = getSelectedTextField(){
            var tfMaxY = activeTF.frame.maxY
            var containerView = activeTF.superview!
            while containerView.frame.maxY != self.view.frame.maxY{
                let contViewFrm = containerView.convert(activeTF.frame, to: containerView.superview)
                tfMaxY = tfMaxY + contViewFrm.minY
                containerView = containerView.superview!
            }
            let keyboardMinY = self.view.frame.height - keyboarHeight
            if tfMaxY > keyboardMinY{
                y = (tfMaxY - keyboardMinY) + 10.0
            }
        }
    
        return y
    }
    

    2) 创建 UIViewController 的扩展和当前活动的 TextField

    //get active text field
    

    扩展 UIViewController { func getSelectedTextField() -> UITextField? {

        let totalTextFields = getTextFieldsInView(view: self.view)
    
        for textField in totalTextFields{
            if textField.isFirstResponder{
                return textField
            }
        }
    
        return nil
    
    }
    
    func getTextFieldsInView(view: UIView) -> [UITextField] {
    
        var totalTextFields = [UITextField]()
    
        for subview in view.subviews as [UIView] {
            if let textField = subview as? UITextField {
                totalTextFields += [textField]
            } else {
                totalTextFields += getTextFieldsInView(view: subview)
            }
        }
    
        return totalTextFields
    }
    

    }

    【讨论】:

    • 由于某种原因,我在keyboardWillShow 函数中遇到了问题,第一次键盘切换后keyboardSize 的大小错误(第一次切换的帧正确)。我通过将其更改为 guard let userInfo = notification.userInfo else {return} guard let keyboardSize = userInfo[UIResponder.keyboardFrameEndUserInfoKey] 来解决这个问题? NSValue else {return} let keyboardFrame = keyboardSize.cgRectValue if self.view.frame.origin.y == 0 { self.view.frame.origin.y -= getMoveableDistance(keyboarHeight: keyboardFrame.height) } 希望这会有所帮助如果有人遇到同样的问题:)
    【解决方案3】:

    非常简单,无需编写更多代码。 只需在您的 podfile 中添加 pod 'IQKeyboardManagerSwift',然后在您的 AppDelegate 页面中添加以下代码。

    import IQKeyboardManagerSwift
    

    在方法didFinishLaunchingWithOptions() 中输入

    IQKeyboardManager.shared.enable = true
    

    就是这样。 查看此视频链接以更好地理解https://youtu.be/eOM94K1ZWN8 希望这会对你有所帮助。

    【讨论】:

    • 它是否适用于 TextView 以及如何更改返回键“完成”的标题?
    • Goto:- "IQKeyboardManager.m" 替换这一行(第 968 行):- [textField addDoneOnKeyboardWithTarget:self action:@selector(doneAction:) shouldShowPlaceholder:_shouldShowTextFieldPlaceholder] 用这个:- [textField addRightButtonOnKeyboardWithText:@"YOURTEXT" target:self action:@selector(doneAction:) shouldShowPlaceholder:_shouldShowTextFieldPlaceholder];还没有尝试过textview,希望这对你有帮助。
    【解决方案4】:

    管理键盘的完整代码。

            override func viewWillAppear(_ animated: Bool) {
                NotificationCenter.default.addObserver(self, selector: #selector(StoryMediaVC.keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
                NotificationCenter.default.addObserver(self, selector: #selector(StoryMediaVC.keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
            }
            override func viewWillDisappear(_ animated: Bool) {
                NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil)
                NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
            }
            @objc func keyboardWillShow(notification: NSNotification) {
                guard let userInfo = notification.userInfo else {return}
                guard let keyboardSize = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue else {return}
                let keyboardFrame = keyboardSize.cgRectValue
    
                if self.view.bounds.origin.y == 0{
                    self.view.bounds.origin.y += keyboardFrame.height
                }
            }
    
    
            @objc func keyboardWillHide(notification: NSNotification) {
                if self.view.bounds.origin.y != 0 {
                    self.view.bounds.origin.y = 0
                }
            }
    

    【讨论】:

    • 像魅力一样工作
    • 如果您一无所获,请使用此解决方案。完美的拯救你。
    • 完美运行
    【解决方案5】:

    frédéric-addaSwift 5 解决方案:

    
    protocol KeyboardHandler: class {
        var bottomConstraint: NSLayoutConstraint! { get set }
        
        func keyboardWillShow(_ notification: Notification)
        func keyboardWillHide(_ notification: Notification)
        func startObservingKeyboardChanges()
        func stopObservingKeyboardChanges()
    }
    
    
    extension KeyboardHandler where Self: UIViewController {
    
        func startObservingKeyboardChanges() {
    
            // NotificationCenter observers
            NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillShowNotification, object: nil, queue: nil) { [weak self] notification in
              self?.keyboardWillShow(notification)
            }
    
            // Deal with rotations
            NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillChangeFrameNotification, object: nil, queue: nil) { [weak self] notification in
              self?.keyboardWillShow(notification)
            }
    
            // Deal with keyboard change (emoji, numerical, etc.)
            NotificationCenter.default.addObserver(forName: UITextInputMode.currentInputModeDidChangeNotification, object: nil, queue: nil) { [weak self] notification in
              self?.keyboardWillShow(notification)
            }
    
            NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillHideNotification, object: nil, queue: nil) { [weak self] notification in
              self?.keyboardWillHide(notification)
            }
        }
    
    
        func keyboardWillShow(_ notification: Notification) {
    
          let verticalPadding: CGFloat = 20 // Padding between the bottom of the view and the top of the keyboard
    
            guard let value = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue else { return }
          let keyboardHeight = value.cgRectValue.height
    
          // Here you could have more complex rules, like checking if the textField currently selected is actually covered by the keyboard, but that's out of this scope.
          self.bottomConstraint.constant = keyboardHeight + verticalPadding
    
          UIView.animate(withDuration: 0.1, animations: { () -> Void in
              self.view.layoutIfNeeded()
          })
      }
    
    
      func keyboardWillHide(_ notification: Notification) {
          self.bottomConstraint.constant = 0
    
          UIView.animate(withDuration: 0.1, animations: { () -> Void in
              self.view.layoutIfNeeded()
          })
      }
    
    
      func stopObservingKeyboardChanges() {
          NotificationCenter.default.removeObserver(self)
      }
    }
    

    在任何UIViewController:

    • 符合KeyboardHandler协议
    extension AnyViewController: KeyboardHandler {} 
    
    • 为屏幕上的最后一个元素添加底部约束。
    @IBOutlet var bottomConstraint: NSLayoutConstraint! 
    
    • 添加观察者订阅/取消订阅:
     override func viewWillAppear(_ animated: Bool) {
            super.viewWillAppear(animated)
            startObservingKeyboardChanges()
     }
        
     override func viewWillDisappear(_ animated: Bool) {
            super.viewWillDisappear(animated)
            stopObservingKeyboardChanges()
     }
    

    享受吧!

    【讨论】:

      【解决方案6】:

      适用于不使用情节提要设置布局约束的任何人。这是让它在 Swift 5 上运行的纯编程方式:

      1. 在 viewController 中定义一个空约束。在这种情况下,我正在构建一个聊天应用程序,它在屏幕的最底部有一个包含文本视图的 UIView。
      var discussionsMessageBoxBottomAnchor: NSLayoutConstraint = NSLayoutConstraint()
      
      1. 在 viewDidLoad 中为最底部的视图添加约束。在这种情况下discussionsMessageBox。此外,添加键盘事件的侦听器。

      为了正确初始化约束,需要先添加子视图,再定义约束。

      NotificationCenter.default.addObserver(self,
                                             selector: #selector(self.keyboardNotification(notification:)),
                                             name: NSNotification.Name.UIKeyboardWillChangeFrame,
                                             object: nil)
      
      view.addSubview(discussionsMessageBox)
      
      if #available(iOS 11.0, *) {
          discussionsMessageBoxBottomAnchor = discussionsMessageBox.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: 0)
      } else {
          // Fallback on earlier versions
          discussionsMessageBoxBottomAnchor = discussionsMessageBox.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0)
      }
      
      NSLayoutConstraint.activate([ discussionsMessageBoxBottomAnchor ])
      
      
      1. 定义deinit
      deinit {
              NotificationCenter.default.removeObserver(self)
          }
      
      1. 接下来添加@JosephLord 定义的代码,并进行一次更正以修复偏移数学。
      extension DiscussionsViewController {
          @objc func keyboardNotification(notification: NSNotification) {
              guard let userInfo = notification.userInfo else { return }
              
              let endFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue
              let endFrameY = endFrame?.origin.y ?? 0
              let duration:TimeInterval = (userInfo[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0
              let animationCurveRawNSN = userInfo[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber
              let animationCurveRaw = animationCurveRawNSN?.uintValue ?? UIView.AnimationOptions.curveEaseInOut.rawValue
              let animationCurve:UIView.AnimationOptions = UIView.AnimationOptions(rawValue: animationCurveRaw)
              
              if endFrameY >= UIScreen.main.bounds.size.height {
                  self.discussionsMessageBoxBottomAnchor.constant = 0.0
              } else {
                  //Changed line
                  self.discussionsMessageBoxBottomAnchor.constant = -1 * (endFrame?.size.height ?? 0.0)
              }
              
              UIView.animate(
                  withDuration: duration,
                  delay: TimeInterval(0),
                  options: animationCurve,
                  animations: { self.view.layoutIfNeeded() },
                  completion: nil)
          }
      }
      

      【讨论】:

        【解决方案7】:

        非常容易安装 Swift 或 Objective-C。

        适用于 Swift 4 和 5 及其他更新版本

        这里是如何工作的:

        IQKeyboardManager (Swift):- IQKeyboardManagerSwift 可通过 Cocoapods 获得,要安装它,只需将以下行添加到您的 Podfile:

        pod 'IQKeyboardManagerSwift'
        

        在 AppDelegate.swift 中,只需导入 IQKeyboardManagerSwift 框架并启用 IQKeyboardManager。

        import IQKeyboardManagerSwift
        
        @UIApplicationMain
        class AppDelegate: UIResponder, UIApplicationDelegate {
        
            var window: UIWindow?
        
            func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        
            IQKeyboardManager.sharedManager().enable = true
            
            IQKeyboardManager.shared.enable = true
        
        
            return true
            }
        }
        

        【讨论】:

          猜你喜欢
          • 2017-01-29
          • 2016-05-07
          • 2017-01-08
          • 2020-05-21
          • 1970-01-01
          • 2015-10-28
          • 2020-04-05
          • 1970-01-01
          • 2020-10-17
          相关资源
          最近更新 更多