使用Swift使用键盘移动视图


278

我有一个应用程序,该应用程序在视图的下半部分具有文本字段。这意味着当我输入文本字段时,键盘将覆盖文本字段。

如何在键入时向上移动视图,以便可以看到正在键入的内容,然后在键盘消失时将其向下移动到原始位置?

我到处都看过,但是所有解决方案似乎都在Obj-C中,我还不能完全转换。

任何帮助将不胜感激。


最好的方法是将您的内容放在UIScrollView内,然后在显示时通过键盘的高度调整滚动视图的contentInset属性。绝对不要假设键盘的高度-使用“键盘将显示”通知中的值。
nielsbot

1
实际上,Apple文档在“管理键盘”下告诉您如何执行此操作:developer.apple.com/library/ios/documentation/StringsTextFonts/…–
nielsbot

11
我认为下面的所有答案都没有考虑一种情况:如果您有多个文本字段,其中一些位于屏幕顶部,该怎么办?每当用户点击该文本字段时,它就会超出屏幕,我很确定正确答案应该能够检测到it is actually needed to scroll view up when keyboard appears
–DC DC

通过查看当前正在编辑的文本字段是否与键盘占用相同的空间,此答案能够检测实际上是否需要向上滚动视图以显示键盘:stackoverflow.com/a/28813720/6749410
HirdayGupta

Answers:


710

这是一个解决方案,无需处理从一个textField到另一个的切换:

 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)            
    }   

func keyboardWillShow(notification: NSNotification) {            
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue() {
        self.view.frame.origin.y -= keyboardSize.height
    }            
}

func keyboardWillHide(notification: NSNotification) {
    self.view.frame.origin.y = 0
}

要解决此问题,请用以下两个函数keyboardWillShow/Hide替换它们:

func keyboardWillShow(notification: NSNotification) {        
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue() {
        if view.frame.origin.y == 0 {
            self.view.frame.origin.y -= keyboardSize.height
        }
    }        
}

func keyboardWillHide(notification: NSNotification) {
    if view.frame.origin.y != 0 {
        self.view.frame.origin.y = 0
    }
}

编辑SWIFT 3.0:

override func viewDidLoad() {
    super.viewDidLoad()            
    NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)    
}

@objc func keyboardWillShow(notification: NSNotification) {        
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
        if self.view.frame.origin.y == 0 {
            self.view.frame.origin.y -= keyboardSize.height
        }
    }        
}

@objc func keyboardWillHide(notification: NSNotification) {
    if self.view.frame.origin.y != 0 {
        self.view.frame.origin.y = 0
    }
}

编辑SWIFT 4.0:

override func viewDidLoad() {
    super.viewDidLoad()            
    NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)    
}

@objc func keyboardWillShow(notification: NSNotification) {        
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
        if self.view.frame.origin.y == 0 {
            self.view.frame.origin.y -= keyboardSize.height
        }
    }        
}

@objc func keyboardWillHide(notification: NSNotification) {
    if self.view.frame.origin.y != 0 {
        self.view.frame.origin.y = 0
    }
}

编辑SWIFT 4.2:

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.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
        if self.view.frame.origin.y == 0 {
            self.view.frame.origin.y -= keyboardSize.height
        }
    }
}

@objc func keyboardWillHide(notification: NSNotification) {
    if self.view.frame.origin.y != 0 {
        self.view.frame.origin.y = 0
    }
}

56
如果用户在使用键盘时触摸另一个文本字段,则视图将被进一步上推,从而导致黑色区域(键盘大小)-我们需要通过跟踪键盘是否存在的变量来解决此问题。例如,如果keyboardPresent == true,则不要移动视图原点等,等等
jonprasetyo 2015年

3
@Matthew Lin使用布尔值,因此功能keyboardWillShow和hide只能使用一次
iluvatar_GR

11
只是一个建议,这样您就不必像我一样进行很多调试了。如果您在同一屏幕上有多个uitextfield,则键盘大小可能会有所不同(根据您的设置不会显示某些输入的建议),因此建议每次设置self.view.frame.origin.y = 0您关闭键盘。例如,它将为您的电子邮件文本字段显示提示,因此键盘大小将增加,而对于密码字段将不显示建议,因此键盘大小将减小。
Vandan Patel'Dec 21'16

36
获取键盘大小时,您需要使用UIKeyboardFrameEndUserInfoKey而不是UIKeyboardFrameBeginUserInfoKey。我目前不知道为什么,但是前者会产生更一致的结果。
jshapy8

3
请替换UIKeyboardFrameBeginUserInfoKeyUIKeyboardFrameEndUserInfoKey。第一个给出键盘的开始帧,有时为零,而第二个给出键盘的结束帧。
阿纳卜

90

甚至不需要任何代码的最简单方法:

  1. 如果尚未使用Spring动画框架,请下载KeyboardLayoutConstraint.swift并将文件添加(拖放)到您的项目中。
  2. 在情节提要中,为“视图”或“文本字段”创建底部约束,选择约束(双击它),然后在Identity Inspector中,将其类从NSLayoutConstraint更改为KeyboardLayoutConstraint。
  3. 做完了!

该对象将与键盘同步自动上移。


4
要选择底部约束,您还可以转到Size Inspector,然后双击列表中的约束-raywenderlich.com/wp-content/uploads/2015/09/…–
gammachill

3
这对我来说很完美。这实际上是一个两步过程。1.添加KeyboardLayoutConstraint.swift,2.在情节提要中,为视图或文本字段创建底部约束。注意:我删除了约束,仅在视图或文本字段的底部添加了1个约束,并将其类从NSLayoutConstraint更改为KeyboardLayoutConstraint。然后,上面的所有视图/文本字段等都只是通过单个KeyboardLayoutConstraint将约束与该项连接到该项,结果是当键盘出现/消失时,视图中的所有项都向上/向下移动
Brian

4
这是最好的解决方案,所提供的代码不会对任何值进行硬编码,例如动画的长度或曲线或键盘的大小。这也很容易理解。
miguelSantirso

3
这对我有用,但是我在键盘顶部和scrollView底部之间留出了50px的额外空间。我想知道是否是由于我使用的安全区域底部限制。有人碰到这个吗?
Clifton Labrum '18

1
这是一个了不起的答案。也很酷的设计。一个建议:如果您的textviews / textfields在表视图单元格上,您可能会注意到,每次用户单击Enter并转到下一个文本字段时,具有此约束的视图都会尴尬地跳转。您可以包装动画以DispatchQueue.main.async {}进行修复。干得好!竖起大拇指!
ScottyBlades

68

此线程上的流行解答之一使用以下代码:

func keyboardWillShow(sender: NSNotification) {
    self.view.frame.origin.y -= 150
}
func keyboardWillHide(sender: NSNotification) {
    self.view.frame.origin.y += 150
}

将视图偏移静态量存在一个明显的问题。它在一台设备上看起来不错,但在其他任何尺寸的配置上都不好看。您需要获取键盘高度,并将其用作偏移值。

这是一个适用于所有设备的解决方案,可以处理用户在键入时隐藏预测性文本字段的极端情况。

以下需要注意的重要事项是,我们将self.view.window作为对象参数传入。这将为我们提供来自键盘的数据,例如其高度!

@IBOutlet weak var messageField: UITextField!

override func viewDidLoad() {
    super.viewDidLoad()

    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name:UIKeyboardWillShowNotification, object: self.view.window)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name:UIKeyboardWillHideNotification, object: self.view.window)
}

func keyboardWillHide(sender: NSNotification) {
    let userInfo: [NSObject : AnyObject] = sender.userInfo!
    let keyboardSize: CGSize = userInfo[UIKeyboardFrameBeginUserInfoKey]!.CGRectValue.size
    self.view.frame.origin.y += keyboardSize.height
}

我们将使其在所有设备上看起来都不错,并处理用户添加或删除预测性文本字段的情况。

func keyboardWillShow(sender: NSNotification) {
    let userInfo: [NSObject : AnyObject] = sender.userInfo!
    let keyboardSize: CGSize = userInfo[UIKeyboardFrameBeginUserInfoKey]!.CGRectValue.size
    let offset: CGSize = userInfo[UIKeyboardFrameEndUserInfoKey]!.CGRectValue.size

    if keyboardSize.height == offset.height {
        UIView.animateWithDuration(0.1, animations: { () -> Void in
            self.view.frame.origin.y -= keyboardSize.height
        })
    } else {
        UIView.animateWithDuration(0.1, animations: { () -> Void in
            self.view.frame.origin.y += keyboardSize.height - offset.height
        })
    }
}

删除观察者

在离开视图之前,请不要忘记删除观察者,以防止不必要的消息被传输。

override func viewWillDisappear(animated: Bool) {
    NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: self.view.window)
    NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: self.view.window)
}

根据评论中的问题进行更新:

如果您有两个或多个文本字段,则可以检查view.frame.origin.y是否为零。

func keyboardWillShow(sender: NSNotification) {
    let userInfo: [NSObject : AnyObject] = sender.userInfo!

    let keyboardSize: CGSize = userInfo[UIKeyboardFrameBeginUserInfoKey]!.CGRectValue.size
    let offset: CGSize = userInfo[UIKeyboardFrameEndUserInfoKey]!.CGRectValue.size

    if keyboardSize.height == offset.height {
        if self.view.frame.origin.y == 0 {
            UIView.animateWithDuration(0.1, animations: { () -> Void in
                self.view.frame.origin.y -= keyboardSize.height
            })
        }
    } else {
        UIView.animateWithDuration(0.1, animations: { () -> Void in
            self.view.frame.origin.y += keyboardSize.height - offset.height
        })
    }
     print(self.view.frame.origin.y)
}

1
当处理多个文本字段时,视图会继续向上移动,而不会下移
Mugunthan Balakrishnan 2015年

您将必须更改您的条件才能考虑文本字段
Dan Beaulieu


@MugunthanBalakrishnan感谢您提出来,我添加了一个解决方案。
Dan Beaulieu

大家好,有个错误。在viewWillDisappear中调用观察者后,不会将其从视图中移除。将该行“ NSNotificationCenter.defaultCenter()。removeObserver(自身,名称:UIKeyboardWillHideNotification,对象:self.view.window)”替换为“ NSNotificationCenter.defaultCenter()。removeObserver(self,名称:UIKeyboardWillHideNotification,对象:nil)”,然后改为观察者被移除
rudald

29

将此添加到您的viewcontroller。奇迹般有效。只需调整值即可。

override func viewDidLoad() {
    super.viewDidLoad()        
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name:NSNotification.Name.UIKeyboardWillShow, object: nil);
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name:NSNotification.Name.UIKeyboardWillHide, object: nil);
}

@objc func keyboardWillShow(sender: NSNotification) {
    self.view.frame.origin.y -= 150
}
@objc func keyboardWillHide(sender: NSNotification) {
    self.view.frame.origin.y += 150
}

这对我有用。但是,这有点生涩。我怎样才能使它平滑发展?还有一种方法可以将其仅应用于当前的所有文本字段之一。:(
DannieCoderBoi 2015年

2
它可能不适用于“自动布局”,因此请考虑停用它。
Teodor Ciuraru'3

1
它会导致自动布局@Josh出现一些时髦的行为,您会误解
Mike

5
不要这样!您不能假设键盘的尺寸一定。
nielsbot

2
应该使用keyboardSize。当您在设备上有配件视图和不同的键盘高度时会发生什么?分离的键盘?
xtrinch '16

25

我对其中一个答案做了一些改进,使其可以在一页上使用不同的键盘和不同的textviews / fields:

添加观察者:

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillChange(notification:)), name: UIResponder.keyboardWillChangeFrameNotification, object: nil)

    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
}

func keyboardWillHide() {
    self.view.frame.origin.y = 0
}

func keyboardWillChange(notification: NSNotification) {

    if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
        if YOURTEXTVIEW.isFirstResponder {
            self.view.frame.origin.y = -keyboardSize.height
        }
    }
}

删除观察者:

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)

    NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
    NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
}

3
该解决方案比公认的答案更好。接受的答案仅显示键盘一次,这对我来说是个bug :)
Masih

这适用于Xcode 10.1和iOS12。接受的答案不再有效。
zeeshan

这是一个很好的答案,我唯一要添加的就是跟踪较新设备(X,XS等)的底部安全区域,以便对此进行解释。
穆尼卜

@Munib请参阅stackoverflow.com/a/54993623/1485230其他问题包括视图未设置动画,以及未遵循键盘高度更改。
Antzi

如果我的textField在视图的顶部,该怎么办?我的意思是如果有原点Y = 0的文本字段。然后textField上升了,我看不到
Saifan Nadaf

18

不是广告,促销或垃圾邮件,只是一个好的解决方案。我知道这个问题有将近30个答案,我非常震惊,以至于没有人提到这个美丽的GitHub项目,它可以为您做得更好,甚至做得更好。所有的答案只是将视图向上移动。我刚刚使用此IQKeyboardManager解决了所有问题。它拥有13000多颗星。
如果使用swift,只需将其添加到您的podfile中

pod 'IQKeyboardManagerSwift'

然后在您的AppDelegate.swift中执行 import IQKeyboardManagerSwift

import IQKeyboardManagerSwift

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

      IQKeyboardManager.shared.enable = true // just add this line

      return true
    }
}

添加该行IQKeyboardManager.shared.enable = true以启用它。
如果要进行生产,则必须使用此解决方案。


这是非常好的,但最新的版本不工作对我来说,我已经使用了6.2.1,并为进口import IQKeyboardManager和使用IQKeyboardManager.shared().isEnabled = true中的AppDelegate
Dhanuķ

2
这在使用多个编辑文本时非常有效,这节省了我的时间
Dhanu K

1
非常感谢您指出这个奇妙的图书馆。该库最终是Apple从未提供过解决方案的所有与键盘相关的废话的最终答案。现在,我将在所有新老项目中使用它,并节省时间,使该键盘出现,消失或不消失,如何隐藏它以及为什么重叠的原因和麻烦,自从那天我正在为iPhone编程。
zeeshan

1
我已经编写了自己的代码来移动文本字段,就像这里的其他解决方案一样。我发现IQKeyboardManager非常好,我将从现在开始将其合并。以防我的代码不及时更新,以方便使用。
TM Lynch

@ DhanuK,Just找到了这个库,可以完美运行,而且很轻松。应用程序委托代码已更新为IQKeyboardManager.shared.enable = true
令人怀疑

15

对于黑屏错误 (Swift 4和4.2)

我解决了黑屏问题。在经过验证的解决方案中,敲击后键盘高度发生变化,这会导致黑屏。

必须使用UIKeyboardFrameEndUserInfoKey而不是UIKeyboardFrameBeginUserInfoKey

var isKeyboardAppear = false

override func viewDidLoad() {
    super.viewDidLoad() 
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}

@objc func keyboardWillShow(notification: NSNotification) {
    if !isKeyboardAppear {
        if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
            if self.view.frame.origin.y == 0{
                self.view.frame.origin.y -= keyboardSize.height
            }
        }
        isKeyboardAppear = true
    }
}

@objc func keyboardWillHide(notification: NSNotification) {
    if isKeyboardAppear {
        if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
            if self.view.frame.origin.y != 0{
                self.view.frame.origin.y += keyboardSize.height
            }
        }
         isKeyboardAppear = false
    }
}

如果没有标签栏,则无法使用。您必须计算标签栏的高度,否则键盘和视图之间将出现黑屏间隙。
安库·拉希尔

这不能解决iPhone X及更高版本上键盘所在的黑色区域。每次键盘出现和消失时,主视图都会向下滑动。
爱迪生

14

我看到所有答案都通过键盘高度的值移动了视图本身。好吧,我有一个详尽的答案,如果您使用约束,这可能会很有用,例如autolayout通过将视图的约束值(例如,底部约束或顶部约束)更改为预定义值来移动视图,或者您可以使用键盘大小值。

在此示例中,我使用从文本字段到底部布局视图的底部约束,初始值为175。

@IBOutlet weak var bottomConstraint: NSLayoutConstraint!

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);
}

func keyboardWillShow(notification: NSNotification) {
    //To retrieve keyboard size, uncomment following line
    //let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue()
    bottomConstraint.constant = 260
    UIView.animateWithDuration(0.3) {
        self.view.layoutIfNeeded()
    }
}

func keyboardWillHide(notification: NSNotification) {
    //To retrieve keyboard size, uncomment following line
    //let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue()
    bottomConstraint.constant = 175
    UIView.animateWithDuration(0.3) {
        self.view.layoutIfNeeded()
    }
}

嗨,先生,您能告诉我为什么当放置在还包含TableView的视图中时,这种方法不起作用吗?当它包含CollectionView时,在相同的情况下可以正常工作。
elarcoiris

9

我们定义KeyboardWillHideNotification的方式已经发生了一些变化。

此解决方案适用于Swift 4.2

NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)


@objc func keyboardWillShow(_ notification:Notification) {
    if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
        self.view.frame.origin.y -= keyboardSize.height
    }
}

@objc func keyboardWillHide(_ notification:Notification) {
    if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
        self.view.frame.origin.y += keyboardSize.height
    }
}

2
如果我的textField在视图的顶部,该怎么办?我的意思是如果有原点Y = 0的文本字段。然后textField上升了,我看不到
Saifan Nadaf

7

Swift 5.0:

经过4-5个小时的奋战,我带来了UIViewController的简单扩展,并带有简单的代码,就像魅力一样

*当TextField位于键盘上方时,视图不应移动

*无需为NSLayoutConstraint设置常数

*无需第三方库

*无需动画代码

*也适用于tableview

*这适用于自动布局/自动调整大小

extension UIViewController {
    func addKeyboardObserver() {
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardNotifications(notification:)),
                                               name: UIResponder.keyboardWillChangeFrameNotification,
                                               object: nil)
    }

    func removeKeyboardObserver(){
        NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
    }

    // This method will notify when keyboard appears/ dissapears
    @objc func keyboardNotifications(notification: NSNotification) {

        var txtFieldY : CGFloat = 0.0  //Using this we will calculate the selected textFields Y Position
        let spaceBetweenTxtFieldAndKeyboard : CGFloat = 5.0 //Specify the space between textfield and keyboard


        var frame = CGRect(x: 0, y: 0, width: 0, height: 0)
        if let activeTextField = UIResponder.currentFirst() as? UITextField ?? UIResponder.currentFirst() as? UITextView {
            // Here we will get accurate frame of textField which is selected if there are multiple textfields
            frame = self.view.convert(activeTextField.frame, from:activeTextField.superview)
            txtFieldY = frame.origin.y + frame.size.height
        }

        if let userInfo = notification.userInfo {
            // here we will get frame of keyBoard (i.e. x, y, width, height)
            let keyBoardFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue
            let keyBoardFrameY = keyBoardFrame!.origin.y
            let keyBoardFrameHeight = keyBoardFrame!.size.height

            var viewOriginY: CGFloat = 0.0
            //Check keyboards Y position and according to that move view up and down
            if keyBoardFrameY >= UIScreen.main.bounds.size.height {
                viewOriginY = 0.0
            } else {
                // if textfields y is greater than keyboards y then only move View to up
                if txtFieldY >= keyBoardFrameY {

                    viewOriginY = (txtFieldY - keyBoardFrameY) + spaceBetweenTxtFieldAndKeyboard

                    //This condition is just to check viewOriginY should not be greator than keyboard height
                    // if its more than keyboard height then there will be black space on the top of keyboard.
                    if viewOriginY > keyBoardFrameHeight { viewOriginY = keyBoardFrameHeight }
                }
            }

            //set the Y position of view
            self.view.frame.origin.y = -viewOriginY
        }
    }
}

添加此扩展UIResponder以获取选择哪个TextField

extension UIResponder {

    static weak var responder: UIResponder?

    static func currentFirst() -> UIResponder? {
        responder = nil
        UIApplication.shared.sendAction(#selector(trap), to: nil, from: nil, for: nil)
        return responder
    }

    @objc private func trap() {
        UIResponder.responder = self
    }
}

然后在您的任何ViewController中使用它

   override func viewWillAppear(_ animated: Bool) {
        self.addKeyboardObserver()
    }

    override func viewWillDisappear(_ animated: Bool) {
        self.removeKeyboardObserver()
    }

  • 在此注册通知 func viewWillAppear(_ animated: Bool)

  • 取消注册此通知 func viewWillDisappear(_ animated:Bool)

    在此处下载演示


这看起来是最好的解决方案,但是存在一些错误。1,文本字段向上移动,但是当我开始输入文本字段时,它又跳了一点。2,在横向输入文本字段时,有时会跳到左侧。
达伦

@Darren我正在尝试找出这些错误,但是我还没有找到,请问您是从哪里得到这些错误的?我的意思是哪个版本/设备...?
塞凡·纳达夫

6

对于Swift 3,我制作了UIViewController子类,因为我需要在所有View Controller中保持不变的行为。

class SomeClassVC: UIViewController {

  //MARK: - Lifecycle
  override func viewDidLoad() {
    super.viewDidLoad()

    addKeyboardObservers()
  }

  override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)

    removeKeyboardObservers()
  }

  //MARK: - Overrides
  override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    view.endEditing(true)
  }

  //MARK: - Help
  func addKeyboardObservers() {
    NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
  }

  func removeKeyboardObservers() {
    NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: self.view.window)
    NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: self.view.window)
  }

  func keyboardWillShow(notification: NSNotification) {
    let keyboardHeight = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.height
    UIView.animate(withDuration: 0.1, animations: { () -> Void in
      self.view.window?.frame.origin.y = -1 * keyboardHeight!
      self.view.layoutIfNeeded()
    })
  }

  func keyboardWillHide(notification: NSNotification) {
    UIView.animate(withDuration: 0.1, animations: { () -> Void in
      self.view.window?.frame.origin.y = 0
      self.view.layoutIfNeeded()
    })
  }

  func resignTextFieldFirstResponders() {
    for textField in self.view.subviews where textField is UITextField {
      textField.resignFirstResponder()
    }
  }

  func resignAllFirstResponders() {
      view.endEditing(true)
  }
}

受到Pavle解决方案的启发,我对其进行了升级,以自动将键盘按剩余可用空间的一定比例升高,并且还递归地找到了聚焦区域以进行正确布局。在这里获取:gist.github.com/noordawod/24d32b2ce8363627ea73d7e5991009a0
Noor Dawod

我的标签栏也随着窗口向上移动!:(
Alfi

6

经过验证的答案未考虑文本字段的位置,并且存在一些错误(双位移,永远不会回到主要位置,即使texfield位于视图顶部也不会位移...)

这个想法是:

  • 获取焦点TextField的绝对Y位置
  • 获取键盘高度
  • 获得ScreenHeight
  • 然后计算键盘位置和文本字段之间的距离(如果<0->向上移动视图)
  • 使用UIView.transform而不是UIView.frame.origin.y-= ..,因为使用UIView.transform = .identity可以更轻松地返回到原始位置

那么我们将能够仅在必要时移动视图,并在特定位置移动视图,以使聚焦的texField恰好位于键盘上方

这是代码:

斯威夫特4

class ViewController: UIViewController, UITextFieldDelegate {

var textFieldRealYPosition: CGFloat = 0.0

override func viewDidLoad() {
    super.viewDidLoad()

    NotificationCenter.default.addObserver(self, selector: #selector(VehiculeViewController.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(VehiculeViewController.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)

  // Delegate all textfields

}


@objc func keyboardWillShow(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
        let distanceBetweenTextfielAndKeyboard = self.view.frame.height - textFieldRealYPosition - keyboardSize.height
        if distanceBetweenTextfielAndKeyboard < 0 {
            UIView.animate(withDuration: 0.4) {
                self.view.transform = CGAffineTransform(translationX: 0.0, y: distanceBetweenTextfielAndKeyboard)
            }
        }
    }
}


@objc func keyboardWillHide(notification: NSNotification) {
    UIView.animate(withDuration: 0.4) {
        self.view.transform = .identity
    }
}


func textFieldDidBeginEditing(_ textField: UITextField) {
  textFieldRealYPosition = textField.frame.origin.y + textField.frame.height
  //take in account all superviews from textfield and potential contentOffset if you are using tableview to calculate the real position
}

}


很好!(在viewDidLoad中,您具有“ VehiculeViewController”,而不仅仅是“ ViewController”)。
rene

一个更完整和有用的答案。谢谢!我建议按以下方式调用键盘检查,因为它将提供一致的键盘大小.........如果让keyboardSize =(notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as?NSValue)?. cgRectValue .size

4

我注意到其他答案涉及从视图中裁剪一些顶部。如果您只想调整视图大小而不削减任何内容,请尝试以下方法:)

func keyboardWillShow(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
        self.view.setTranslatesAutoresizingMaskIntoConstraints(true)
        self.view.frame = CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y, self.view.frame.size.width, self.view.frame.height - keyboardSize.height)
    }
}

func keyboardWillHide(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
        self.collectionView.setTranslatesAutoresizingMaskIntoConstraints(false)
        self.view.frame = CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y, self.view.frame.size.width, self.view.frame.height + keyboardSize.height)
    }
}

4

我给初学者的两分钱:在上面的示例中,有人更改了坐标,其他人使用了“自动调整蒙版”,以及其他限制:

正如苹果所说,不要混用这三种逻辑。如果您在Storyboard中有约束,请不要尝试更改x / y。它绝对行不通。


4

因此,其他答案似乎都不对。

iOS上的良好行为键盘应:

  • 键盘更改大小时自动调整大小(可以)
  • 以与键盘相同的速度进行动画处理
  • 使用与键盘相同的曲线进行动画处理
  • 如果相关,请遵守安全区域。
  • 也适用于iPad / Undocked模式

我的代码使用一个NSLayoutConstraint声明为@IBOutlet

@IBOutlet private var bottomLayoutConstraint: NSLayoutConstraint!

您也可以使用变换,查看偏移量....我认为使用约束tho更容易。它通过在底部设置约束来工作,如果常量不为0 / Not到底部,则可能需要更改代码。

这是代码:

// In ViewDidLoad
    NotificationCenter.default.addObserver(self, selector: #selector(?MyViewController.keyboardDidChange), name: UIResponder.keyboardWillChangeFrameNotification, object: nil)


@objc func keyboardDidChange(notification: Notification) {
    let userInfo = notification.userInfo! as [AnyHashable: Any]
    let endFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
    let animationDuration = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as! NSNumber
    let animationCurve = userInfo[UIResponder.keyboardAnimationCurveUserInfoKey] as! NSNumber
    bottomLayoutConstraint.constant = view.frame.height - endFrame.origin.y - view.safeAreaInsets.bottom // If your constraint is not defined as a safeArea constraint you might want to skip the last part.
    // Prevents iPad undocked keyboard.
    guard endFrame.height != 0, view.frame.height == endFrame.height + endFrame.origin.y else {
        bottomLayoutConstraint.constant = 0
        return
    }
    UIView.setAnimationCurve(UIView.AnimationCurve(rawValue: animationCurve.intValue)!)
    UIView.animate(withDuration: animationDuration.doubleValue) {
        self.view.layoutIfNeeded()
        // Do additional tasks such as scrolling in a UICollectionView
    }
}

3

打开键盘时对所有Guy更新Tableview高度的100%完美答案

对于Swift4.2

   override func viewDidLoad() {
      super.viewDidLoad()
      NotificationCenter.default.addObserver(self, selector: #selector(RecipeVC.keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)

      NotificationCenter.default.addObserver(self, selector: #selector(RecipeVC.keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
   }

   @objc func keyboardWillShow(notification: NSNotification) {
    if ((notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue) != nil {

        var userInfo = notification.userInfo!
        var keyboardFrame:CGRect = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
        keyboardFrame = self.view.convert(keyboardFrame, from: nil)

        var contentInset:UIEdgeInsets = self.tbl.contentInset
          contentInset.bottom = keyboardFrame.size.height
          self.tbl.contentInset = contentInset
    }
}

   @objc func keyboardWillHide(notification: NSNotification) {
    if ((notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue) != nil {
        let contentInset:UIEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
        self.tbl.contentInset = contentInset
    }
}

迅捷3.2

    override func viewDidLoad() {
          super.viewDidLoad()

           NotificationCenter.default.addObserver(self, selector: #selector(RecipeVC.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)

           NotificationCenter.default.addObserver(self, selector: #selector(RecipeVC.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
    }
    func keyboardWillShow(notification: NSNotification) {
         if ((notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue) != nil {
         //self.view.frame.origin.y -= keyboardSize.height
         var userInfo = notification.userInfo!
         var keyboardFrame:CGRect = (userInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
          keyboardFrame = self.view.convert(keyboardFrame, from: nil)

          var contentInset:UIEdgeInsets = self.tbl.contentInset
          contentInset.bottom = keyboardFrame.size.height
          self.tbl.contentInset = contentInset

       }
    }

    func keyboardWillHide(notification: NSNotification) {
         if ((notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue) != nil {
         let contentInset:UIEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
         self.tbl.contentInset = contentInset
         }
    }

这是最好的答案。tbl应该是tableView,我添加了一些填充:contentInset.bottom = keyboardFrame.size.height + 10
iphaaw

2

对于Swift 3

func textFieldDidBeginEditing(_ textField: UITextField) { // became first responder

    //move textfields up
    let myScreenRect: CGRect = UIScreen.main.bounds
    let keyboardHeight : CGFloat = 216

    UIView.beginAnimations( "animateView", context: nil)
    var movementDuration:TimeInterval = 0.35
    var needToMove: CGFloat = 0

    var frame : CGRect = self.view.frame
    if (textField.frame.origin.y + textField.frame.size.height + UIApplication.shared.statusBarFrame.size.height > (myScreenRect.size.height - keyboardHeight - 30)) {
        needToMove = (textField.frame.origin.y + textField.frame.size.height + UIApplication.shared.statusBarFrame.size.height) - (myScreenRect.size.height - keyboardHeight - 30);
    }

    frame.origin.y = -needToMove
    self.view.frame = frame
    UIView.commitAnimations()
}

func textFieldDidEndEditing(_ textField: UITextField) {
    //move textfields back down
    UIView.beginAnimations( "animateView", context: nil)
    var movementDuration:TimeInterval = 0.35
    var frame : CGRect = self.view.frame
    frame.origin.y = 0
    self.view.frame = frame
    UIView.commitAnimations()
}

2

斯威夫特4:

我遇到了一个最被接受的答案的问题,其中隐藏键盘并没有将视图一直返回到页面底部(仅部分返回)。这对我有用(对Swift 4进行了更新)。

override func viewDidLoad() {
    super.viewDidLoad()
    self.hideKeyboardWhenTappedAround()
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}

@objc func keyboardWillShow(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
        if self.view.frame.origin.y == 0{
            self.view.frame.origin.y -= keyboardSize.height
        }
    }
}

@objc func keyboardWillHide(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
        if self.view.frame.origin.y != 0{
            self.view.frame.origin.y = 0
        }
    }
}

如果我的textField在视图的顶部,该怎么办?我的意思是如果有原点Y = 0的文本字段。然后textField上升了,我看不到
Saifan Nadaf

2

与@Boris答案类似,但在Swift 5中

override func 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)
}

@IBAction 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 -= keyboardSize.height
        }
    }
}

@IBAction func keyboardWillHide(notification: NSNotification) {
    if self.view.frame.origin.y != 0 {
        self.view.frame.origin.y = 0
    }
}

1

这是我的解决方案(实际上,此代码适用于视图中没有几个文本字段的情况,也适用于只有一个文本字段的情况)

class MyViewController: UIViewController, UITextFieldDelegate {

@IBOutlet weak var firstTextField: UITextField!
@IBOutlet weak var secondTextField: UITextField!

var activeTextField: UITextField!
var viewWasMoved: Bool = false


override func viewDidLoad() {
    super.viewDidLoad()
    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(PrintViewController.keyboardWillShow(_:)), name: UIKeyboardWillShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(PrintViewController.keyboardWillHide(_:)), name: UIKeyboardWillHideNotification, object: nil)
}

override func viewDidDisappear(animated: Bool) {
    super.viewWillDisappear(animated)
    NSNotificationCenter.defaultCenter().removeObserver(self)
}

func textFieldDidBeginEditing(textField: UITextField) {
    self.activeTextField = textField
}

func textFieldDidEndEditing(textField: UITextField) {
    self.activeTextField = nil
}

func textFieldShouldReturn(textField: UITextField) -> Bool {
    textField.resignFirstResponder()
    return true
}


func keyboardWillShow(notification: NSNotification) {

    let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue()

    var aRect: CGRect = self.view.frame
    aRect.size.height -= keyboardSize!.height

    let activeTextFieldRect: CGRect? = activeTextField?.frame
    let activeTextFieldOrigin: CGPoint? = activeTextFieldRect?.origin

    if (!CGRectContainsPoint(aRect, activeTextFieldOrigin!)) {
        self.viewWasMoved = true
        self.view.frame.origin.y -= keyboardSize!.height
    } else {
        self.viewWasMoved = false
    }
}

func keyboardWillHide(notification: NSNotification) {
    if (self.viewWasMoved) {
        if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
            self.view.frame.origin.y += keyboardSize.height
        }
    }
}

不要忘记将Delegate设置为textFields
SwingerDinger

更改键盘显示的条件,如果(!CGRectContainsPoint(aRect,newOrgin!)&&!
self.viewWasMoved

重置框架时添加self.viewWasMoved = false
KingofBliss

1

已为Swift 3更新...

正如其他人所说,您需要在控制器的viewDidLoad()方法中添加通知观察者,如下所示:

NotificationCenter.default.addObserver(forName: .UIKeyboardWillShow, object: nil, queue: nil)
    { notification in
    self.keyboardWillShow(notification)
    }

NotificationCenter.default.addObserver(forName: .UIKeyboardWillHide, object: nil, queue: nil)
    { notification in
    self.keyboardWillHide(notification)
    }

NotificationCenter.default.addObserver(forName: .UIKeyboardDidShow, object: nil, queue: nil)
    { _ in
    self.enableUserInteraction()
    }

NotificationCenter.default.addObserver(forName: .UIKeyboardDidHide, object: nil, queue: nil)
    { _ in
    self.enableUserInteraction()
    }

记住要在适当的地方删除观察者(我在viewWillDisappear()方法中做到了)

NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillShow, object: nil)
NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillHide, object: nil)
NotificationCenter.default.removeObserver(self, name: .UIKeyboardDidShow, object: nil)
NotificationCenter.default.removeObserver(self, name: .UIKeyboardDidHide, object: nil)

然后,实现您的show和hide方法-注意,该行告诉应用程序忽略交互事件(beginIgnoringInteractionEvents)。这一点很重要,因为如果没有它,用户可能会点击一个字段甚至滚动视图,并导致第二次发生切换,从而导致严重的UI故障。在键盘显示和隐藏之前忽略交互事件将防止此情况:

func keyboardWillShow(notification: Notification)
    {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue
        {
        UIApplication.shared.beginIgnoringInteractionEvents()
        self.view.frame.origin.y -= keyboardSize.height
        // add this line if you are shifting a scrollView, as in a chat application
        self.timelineCollectionView.contentInset.top += keyboardSize.height
        }
    }

func keyboardWillHide(notification: Notification)
    {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue
        {
        UIApplication.shared.beginIgnoringInteractionEvents()
        self.view.frame.origin.y += keyboardSize.height
        // add this line if you are shifting a scrollView, as in a chat application
        self.timelineCollectionView.contentInset.top -= keyboardSize.height
        }
    }

最后,重新启用用户交互(请记住,此方法在键盘didShow或didHide之后触发):

func enableUserInteraction()
    {
    UIApplication.shared.endIgnoringInteractionEvents()
    }

1

Swift 3代码

var activeField: UITextField?

override func viewDidLoad() {
    super.viewDidLoad()

    NotificationCenter.default.addObserver(self, selector: #selector(ProfileViewController.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(ProfileViewController.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}

func textFieldDidBeginEditing(_ textField: UITextField){
    activeField = textField
}

func textFieldDidEndEditing(_ textField: UITextField){
    activeField = nil
}

func keyboardWillShow(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
        if (self.activeField?.frame.origin.y)! >= keyboardSize.height {
            self.view.frame.origin.y = keyboardSize.height - (self.activeField?.frame.origin.y)!
        } else {
            self.view.frame.origin.y = 0
        }
    }
}

func keyboardWillHide(notification: NSNotification) {
    self.view.frame.origin.y = 0
}

1

如果您在同一VC上有2个或更多文本字段,并且用户点击其中一个,然后又点击另一个,而无需调用keyboardWillHide函数,则视图将再向上移动一次,这是不必要的,因为使用我编辑的答案中的代码,您将拥有一个键盘,一个具有键盘高度的空白区域和一个视图,然后是:

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)
}

func keyboardWillShow(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
        self.view.frame.origin.y -= keyboardSize.height
    }
}

func keyboardWillHide(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
        self.view.frame.origin.y += keyboardSize.height
    }
}

要解决此问题,请将以下两个功能“ KeyboardWillShow / Hide”替换为:

func keyboardWillShow(notification: NSNotification) {
 if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
    if view.frame.origin.y == 0{
        self.view.frame.origin.y -= keyboardSize.height
        }
    }
}

func keyboardWillHide(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
        if view.frame.origin.y != 0 {
            self.view.frame.origin.y += keyboardSize.height
        }
    }
}

如果我的textField在视图的顶部,该怎么办?我的意思是如果有原点Y = 0的文本字段。然后textField上升了,我看不到
Saifan Nadaf

1

@Boris的解决方案非常好,但是视图有时可能会损坏。

为了完美对齐,请使用以下代码

override func viewDidLoad() {
super.viewDidLoad()            
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)}

功能:

@objc func keyboardWillShow(notification: NSNotification) {        
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
    if self.view.frame.origin.y == 0{
        self.view.frame.origin.y -= keyboardSize.height
    }
}}    

和,

@objc func keyboardWillHide(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
    if self.view.frame.origin.y != 0{
        self.view.frame.origin.y = 0 
    }
} }

0

这个视频教程是最好的。7分钟长,这非常有意义。当您有多个文本字段并希望在点击特定文本字段时滚动视图移动“ x”个像素时,这种简单的解决方案。

https://youtu.be/VuiPGJOEBH4

只需执行以下步骤:

-将所有文本字段放置在受视图边缘限制的滚动视图内。

-将所有文本字段和滚动视图作为委托连接到视图控制器。

-连接所有文本字段并使用IBOutlet滚动视图。

class ViewController: UIViewController, UITextFieldDelegate {

-将UITextFieldDelegate协议添加到您的类

@IBOutlet var stateAddress: UITextField!
@IBOutlet var zipAddress: UITextField!
@IBOutlet var phoneNumber: UITextField!
@IBOutlet var vetEmailAddress: UITextField!    
@IBOutlet weak var scrollView: UIScrollView!

-在您的swift文件中添加UITextFieldDelegate方法:

func textFieldShouldReturn(textField: UITextField) -> Bool {

    textField.resignFirstResponder()
    return true
}


func textFieldDidBeginEditing(textField: UITextField) {

    if (textField == self.stateAddress) {
        scrollView.setContentOffset(CGPointMake(0, 25), animated: true)
    }
    else if (textField == self.zipAddress) {
        scrollView.setContentOffset(CGPointMake(0, 57), animated: true)
    }
    else if (textField == self.phoneNumber) {
        scrollView.setContentOffset(CGPointMake(0, 112), animated: true)
    }
    else if (textField == self.vetEmailAddress) {
        scrollView.setContentOffset(CGPointMake(0, 142), animated: true)
    }
}

func textFieldDidEndEditing(textField: UITextField) {

    scrollView.setContentOffset(CGPointMake(0, 0), animated: true)
}

第一种方法只是激活键盘上的返回按钮以关闭键盘。第二个是当您点击任何特定的文本字段,然后设置滚动视图滚动的y偏移量(我的视图基于我的视图控制器25,57,112,142的y位置)。最后一个说,当您从键盘上轻按时,滚动视图将返回到原始位置。

我用这种方法使我的视点完美!


0

这个功能包已经内置在Ios中,但是我们需要在外部做。
插入下面的代码
*若要在textField在键盘下方时移动视图,
* 在textField在键盘上方时不移动视图
*必要时根据键盘高度移动View。
这在所有情况下均有效并经过测试。

import UIKit

class NamVcc: UIViewController, UITextFieldDelegate
{
    @IBOutlet weak var NamTxtBoxVid: UITextField!

    var VydTxtBoxVar: UITextField!
    var ChkKeyPadDspVar: Bool = false
    var KeyPadHytVal: CGFloat!

    override func viewDidLoad()
    {
        super.viewDidLoad()

        NamTxtBoxVid.delegate = self
    }

    override func viewWillAppear(animated: Bool)
    {
        NSNotificationCenter.defaultCenter().addObserver(self,
            selector: #selector(TdoWenKeyPadVyd(_:)),
            name:UIKeyboardWillShowNotification,
            object: nil);
        NSNotificationCenter.defaultCenter().addObserver(self,
            selector: #selector(TdoWenKeyPadHyd(_:)),
            name:UIKeyboardWillHideNotification,
            object: nil);
    }

    func textFieldDidBeginEditing(TxtBoxPsgVar: UITextField)
    {
        self.VydTxtBoxVar = TxtBoxPsgVar
    }

    func textFieldDidEndEditing(TxtBoxPsgVar: UITextField)
    {
        self.VydTxtBoxVar = nil
    }

    func textFieldShouldReturn(TxtBoxPsgVar: UITextField) -> Bool
    {
        self.VydTxtBoxVar.resignFirstResponder()
        return true
    }

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?)
    {
        view.endEditing(true)
        super.touchesBegan(touches, withEvent: event)
    }

    func TdoWenKeyPadVyd(NfnPsgVar: NSNotification)
    {
        if(!self.ChkKeyPadDspVar)
        {
            self.KeyPadHytVal = (NfnPsgVar.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue().height

            var NonKeyPadAraVar: CGRect = self.view.frame
            NonKeyPadAraVar.size.height -= self.KeyPadHytVal

            let VydTxtBoxCenVal: CGPoint? = VydTxtBoxVar?.frame.origin

            if (!CGRectContainsPoint(NonKeyPadAraVar, VydTxtBoxCenVal!))
            {
                self.ChkKeyPadDspVar = true
                UIView.animateWithDuration(1.0,
                    animations:
                    { self.view.frame.origin.y -= (self.KeyPadHytVal)},
                    completion: nil)
            }
            else
            {
                self.ChkKeyPadDspVar = false
            }
        }

    }

    func TdoWenKeyPadHyd(NfnPsgVar: NSNotification)
    {
        if (self.ChkKeyPadDspVar)
        {
            self.ChkKeyPadDspVar = false
            UIView.animateWithDuration(1.0,
                animations:
                { self.view.frame.origin.y += (self.KeyPadHytVal)},
                completion: nil)
        }
    }

    override func viewDidDisappear(animated: Bool)
    {
        super.viewWillDisappear(animated)
        NSNotificationCenter.defaultCenter().removeObserver(self)
        view.endEditing(true)
        ChkKeyPadDspVar = false
    }
}

| :: | 有时,视图会下降,在这种情况下,请使用+/- 150的高度:

    NonKeyPadAraVar.size.height -= self.KeyPadHytVal + 150

    { self.view.frame.origin.y -= self.KeyPadHytVal  - 150},
                    completion: nil)

    { self.view.frame.origin.y += self.KeyPadHytVal  - 150},
                completion: nil)

0
func keyboardWillShow(notification: NSNotification) {

    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
        self.view.frame.origin.y = self.view.frame.height - (self.view.frame.height + keyboardSize.height)
    }

}

func keyboardWillHide(notification: NSNotification) {
        self.view.frame.origin.y = 0
}

它必须更稳定


0
 override func viewWillAppear(animated: Bool)
 {
 super.viewWillAppear(animated)

 NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillShow:", name: UIKeyboardWillShowNotification, object: nil)
 NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillHide:", name: UIKeyboardWillHideNotification, object: nil)

 }

 // MARK: - keyboard
 func keyboardWillShow(notification: NSNotification) 
{

if let userInfo = notification.userInfo {
if let keyboardSize = (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
let contentInsets = self.tblView.contentInset as UIEdgeInsets
self.tblView.contentInset = UIEdgeInsets(top: contentInsets.top, left: contentInsets.left, bottom: keyboardSize.height, right:contentInsets.right)
                    // ...
                } else {
                    // no UIKeyboardFrameBeginUserInfoKey entry in userInfo
                }
            } else {
                // no userInfo dictionary in notification
            }
        }

func keyboardWillHide(notification: NSNotification) 
{
let contentInsets = self.tblView.contentInset as UIEdgeInsets
self.tblView.contentInset = UIEdgeInsets(top: contentInsets.top, left: contentInsets.left, bottom: 0, right:contentInsets.right)
 }

0

使用以下代码在UITextField上单击查看

func textFieldDidBeginEditing(textField: UITextField) {
    ViewUpanimateMoving(true, upValue: 100)
}
func textFieldDidEndEditing(textField: UITextField) {
    ViewUpanimateMoving(false, upValue: 100)
}
func ViewUpanimateMoving (up:Bool, upValue :CGFloat){
    var durationMovement:NSTimeInterval = 0.3
    var movement:CGFloat = ( up ? -upValue : upValue)
    UIView.beginAnimations( "animateView", context: nil)
    UIView.setAnimationBeginsFromCurrentState(true)
    UIView.setAnimationDuration(durationMovement)
    self.view.frame = CGRectOffset(self.view.frame, 0,  movement)
    UIView.commitAnimations()
}

0

我做了一个cocoapod来简化事情:

https://github.com/xtrinch/KeyboardLayoutHelper

如何使用它:

设置一个自动布局底部约束,在KeyboardLayoutHelper模块中为它提供一个KeyboardLayoutConstraint类,然后窗格将进行必要的工作以增加它以适应出现和消失的键盘。请参阅示例项目中有关如何使用它的示例项目(我做了两个:scrollView内的textFields和具有两个基本视图(登录和注册)的垂直居中的textFields。

底部布局约束可以是容器视图,textField本身,任何名称的名称。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.