Scrollview和键盘Swift

Gal*_*ora 48 scroll view ios swift

我是新来的,我开始使用Swift for iOS.

我开始创建一个执行某些操作的简单应用程序.但是当键盘出现时我遇到了一些问题,隐藏了我的一个textFields.我认为这是一个常见的问题,我做了一些研究,但我找不到任何解决我问题的方法.我想使用Scroll而不是动画textField使其可见.

谢谢!!!!!(抱歉英语错误)

Sud*_*uri 111

在ViewDidLoad中,注册通知:

NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(keyboardWillShow), name:UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(keyboardWillHide), name:UIKeyboardWillHideNotification, object: nil)
Run Code Online (Sandbox Code Playgroud)

添加下面的观察者方法,当键盘出现时自动滚动.

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

func keyboardWillShow(notification:NSNotification){

    var userInfo = notification.userInfo!
    var keyboardFrame:CGRect = (userInfo[UIKeyboardFrameBeginUserInfoKey] as! NSValue).CGRectValue()
    keyboardFrame = self.view.convertRect(keyboardFrame, fromView: nil)

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

func keyboardWillHide(notification:NSNotification){

    let contentInset:UIEdgeInsets = UIEdgeInsetsZero
    scrollView.contentInset = contentInset
}
Run Code Online (Sandbox Code Playgroud)

编辑:此帖子已更新,以反映Swift 2.2 for Objective C选择器的最佳实践.

  • 使用这些代码和scrollView节省了我的生命.只需添加20个contentInset.bottom即可正确滚动它.contentInset.bottom = keyboardFrame.size.height + 20 (2认同)
  • 第一个 KeyboardWillShow 返回正确的键盘高度 (260)。接下来的所有keyboardWillShow返回键盘高度216。为什么? (2认同)

Dan*_*nes 64

swift 3的最佳答案:

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)
Run Code Online (Sandbox Code Playgroud)

然后:

func keyboardWillShow(notification:NSNotification){
    //give room at the bottom of the scroll view, so it doesn't cover up anything the user needs to tap
    var userInfo = notification.userInfo!
    var keyboardFrame:CGRect = (userInfo[UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
    keyboardFrame = self.view.convert(keyboardFrame, from: nil)

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

func keyboardWillHide(notification:NSNotification){
    let contentInset:UIEdgeInsets = UIEdgeInsets.zero
    theScrollView.contentInset = contentInset
}
Run Code Online (Sandbox Code Playgroud)

  • @nikans用于`NotificationCenter`的Apple文档:`如果您的应用程序面向iOS 9.0及更高版本或macOS 10.11及更高版本,则无需在其解除分配方法中注销观察者. (9认同)
  • 不要忘记`NotificationCenter.default.removeObserver(self)` (3认同)
  • 我认为您需要在答案中将“UIKeyboardFrameBeginUserInfoKey”替换为“UIKeyboardFrameEndUserInfoKey”。因为你需要在 willShow 方法中结束帧。 (3认同)
  • 无法在UIView nib文件中使用UITextView。 (2认同)

Har*_*ris 24

这是一个完整的Swift 4解决方案,使用保护和简洁的代码.加上正确的代码keyboardWillHide只能重置bottom为0.

@IBOutlet weak var scrollView: UIScrollView!

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

override func viewDidDisappear(_ animated: Bool) {
    super.viewDidDisappear(animated)
    unregisterNotifications()
}

private func registerNotifications() {
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
}

private func unregisterNotifications() {
    NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil)
    NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
    scrollView.contentInset.bottom = 0
}

@objc private func keyboardWillShow(notification: NSNotification){
    guard let keyboardFrame = notification.userInfo![UIResponder.keyboardFrameEndUserInfoKey] as? NSValue else { return }
    scrollView.contentInset.bottom = view.convert(keyboardFrame.cgRectValue, from: nil).size.height
}

@objc private func keyboardWillHide(notification: NSNotification){
    scrollView.contentInset.bottom = 0
}
Run Code Online (Sandbox Code Playgroud)


Sup*_*hon 12

对于Swift 4.0

在ViewDidLoad中

// setup keyboard event
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)
Run Code Online (Sandbox Code Playgroud)

添加下面的观察者方法,当键盘出现时自动滚动.

@objc func keyboardWillShow(notification:NSNotification){
    var userInfo = notification.userInfo!
    var keyboardFrame:CGRect = (userInfo[UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
    keyboardFrame = self.view.convert(keyboardFrame, from: nil)

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

@objc func keyboardWillHide(notification:NSNotification){

    let contentInset:UIEdgeInsets = UIEdgeInsets.zero
    ui_scrollView.contentInset = contentInset
}
Run Code Online (Sandbox Code Playgroud)


小智 9

Swift 5仅在 TextField 被键盘隐藏时调整 ScrollView(对于多个 TextField)

添加/删除观察者:

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    NotificationCenter.default.removeObserver(self)
}
Run Code Online (Sandbox Code Playgroud)

跟踪这些值,以便您可以返回到原来的位置:

var scrollOffset : CGFloat = 0
var distance : CGFloat = 0
Run Code Online (Sandbox Code Playgroud)

根据 TextField 位置调整 ScrollView contentOffset:

@objc func keyboardWillShow(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {

        var safeArea = self.view.frame
        safeArea.size.height += scrollView.contentOffset.y
        safeArea.size.height -= keyboardSize.height + (UIScreen.main.bounds.height*0.04) // Adjust buffer to your liking

        // determine which UIView was selected and if it is covered by keyboard

        let activeField: UIView? = [textFieldA, textViewB, textFieldC].first { $0.isFirstResponder }
        if let activeField = activeField {
            if safeArea.contains(CGPoint(x: 0, y: activeField.frame.maxY)) {
                print("No need to Scroll")
                return
            } else {
                distance = activeField.frame.maxY - safeArea.size.height
                scrollOffset = scrollView.contentOffset.y
                self.scrollView.setContentOffset(CGPoint(x: 0, y: scrollOffset + distance), animated: true)
            }
        }
        // prevent scrolling while typing

        scrollView.isScrollEnabled = false
    }
}
@objc func keyboardWillHide(notification: NSNotification) {
        if distance == 0 {
            return
        }
        // return to origin scrollOffset
        self.scrollView.setContentOffset(CGPoint(x: 0, y: scrollOffset), animated: true)
        scrollOffset = 0
        distance = 0
        scrollView.isScrollEnabled = true
}
Run Code Online (Sandbox Code Playgroud)

确保第一次使用 [UIResponder.keyboardFrameEndUserInfoKey] 来获得正确的键盘高度。


nik*_*ans 8

contentInset对我来说不起作用,因为我希望scrollview一直向上移动到键盘上方.所以我使用contentOffset:

func keyboardWillShow(notification:NSNotification) {
    guard let keyboardFrameValue = notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue else {
        return
    }
    let keyboardFrame = view.convert(keyboardFrameValue.cgRectValue, from: nil)
    scrollView.contentOffset = CGPoint(x:0, y:keyboardFrame.size.height)
}

func keyboardWillHide(notification:NSNotification) {
    scrollView.contentOffset = .zero
}
Run Code Online (Sandbox Code Playgroud)


Iva*_*ati 6

根据Sudheer Palchuri的回答,将其转换为Swift 4。

在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)
Run Code Online (Sandbox Code Playgroud)

然后:

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

@objc func keyboardWillShow(notification:NSNotification){

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

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

@objc func keyboardWillHide(notification:NSNotification){

    let contentInset:UIEdgeInsets = UIEdgeInsets.zero
    self.scrollView.contentInset = contentInset
}
Run Code Online (Sandbox Code Playgroud)


Gal*_*ora 5

阅读您发送给我的链接,我找到了一种使其工作的方法,谢谢!:

func textFieldDidBeginEditing(textField: UITextField) {            
    if (textField == //your_field) {
        scrollView.setContentOffset(CGPointMake(0, field_extra.center.y-280), animated: true)
        callAnimation()
        viewDidLayoutSubviews()
    }
}

func textFieldDidEndEditing(textField: UITextField) {    
    if (textField == //your_field){
        scrollView .setContentOffset(CGPointMake(0, 0), animated: true)
        viewDidLayoutSubviews()
    }
}
Run Code Online (Sandbox Code Playgroud)


Gly*_*ard 2

您可以通过滚动偏移将滚动视图设置为动画,使其在键盘外观上以 UITextField 为中心(即,使文本字段成为第一响应者)。这里有一些可以帮助您入门的好资源(该网站上有很多):

如何以编程方式将 UIScrollView 移动到键盘上方的控件中?

当 UITextField 成为第一响应者时,如何使 UIScrollView 自动滚动

此外,如果您只是将 UITableView 与单元格中的内容一起使用,则当文本字段成为第一响应者时,UITableViewController 将自动滚动到您的文本字段单元格(尽管我不确定这是否是您想要做的)。