ios 滚动视图和键盘 Swift

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26689232/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 03:27:44  来源:igfitidea点击:

Scrollview and keyboard Swift

iosviewswiftscroll

提问by GalinhaVoadora

I'm new here and im starting with Swift for iOS.

我是新来的,我从 Swift for iOS 开始。

I started creating a simple app that does some operations. But I'm having some problems when the keyboard appears, hiding one of my textFields. I think it's a common problem and I did some research but I couldn't find anything that solved my problem. And I want to use a Scroll rather than animate the textField to make it visible.

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

Thanks!!!!! (sorry for english mistakes)

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

回答by Sudheer Kumar Palchuri

In ViewDidLoad, register the notifications:

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

Add below observer methods which does the automatic scrolling when keyboard appears.

添加以下观察者方法,当键盘出现时自动滚动。

@objc func keyboardWillShow(notification:NSNotification){

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

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

@objc func keyboardWillHide(notification:NSNotification){

    let contentInset:UIEdgeInsets = UIEdgeInsets.zero
    scrollView.contentInset = contentInset
}

回答by Daniel Jones

The top answer for swift 3:

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)

And then:

进而:

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
}

回答by Harris

Here is a complete solution, utilizing guard and concise code. Plus correct code in keyboardWillHideto only reset the bottomto 0.

这是一个完整的解决方案,利用保护和简洁的代码。加上正确的代码,keyboardWillHide只将 重置bottom为 0。

@IBOutlet private weak var scrollView: UIScrollView!

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

override func viewDidDisappear(_ animated: Bool) {
    super.viewDidDisappear(animated)
    scrollView.contentInset.bottom = 0
}

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

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

回答by Supanat Techasothon

for Swift 4.0

适用于 Swift 4.0

In ViewDidLoad

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

Add below observer methods which does the automatic scrolling when keyboard appears.

添加以下观察者方法,当键盘出现时自动滚动。

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

回答by nikans

contentInsetdoesn't work for me, because I want the scrollview move all the way up above the keyboard. So I use contentOffset:

contentInset对我不起作用,因为我希望滚动视图一直在键盘上方移动。所以我使用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
}

回答by Ivan Carosati

From the answer by Sudheer Palchuri, converted for Swift 4.

来自 Sudheer Palchuri 的回答,转换为 Swift 4。

In ViewDidLoad, register the notifications:

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

And then:

进而:

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

回答by Zachary Probst

Swift 5Only adjust ScrollView when TextField is hidden by keyboard (for multiple TextFields)

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

Add / Remove Observers:

添加/删除观察者:

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

Keep track of these values so you can return to your original position:

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

var scrollOffset : CGFloat = 0
var distance : CGFloat = 0

Adjust ScrollView contentOffset depending on TextField Location:

根据 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 { 
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()
    }
}
.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 }

Make sure to use [UIResponder.keyboardFrameEndUserInfoKey] to get the proper keyboard height the first time.

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

回答by GalinhaVoadora

Reading the links you sent to me, I found a way to make it work, thanks!:

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

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

@objc private func keyboardWillBeHidden() {
    scrollView.contentInset = .zero
    scrollView.scrollIndicatorInsets = scrollView.contentInset
}

回答by Glynbeard

You can animate your scrollview to center on your UITextField on keyboard appearance (ie. making your textfield the first responder) via a scroll offset. Here are a couple of good resources to get you started (there are a bunch on this site):

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

How programmatically move a UIScrollView to focus in a control above keyboard?

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

How to make a UIScrollView auto scroll when a UITextField becomes a first responder

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

Additionally, if you simply use a UITableView with your content in cells, when the textfield becomes first responder, the UITableViewController will automatically scroll to the textfield cell for you (though I'm not sure this is what you want to do).

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

回答by Johan Drevet

An answer for Swift 3, based on the one proposed by Daniel Jones, but safer (thanks to the guard), more concise and with consistent scroll indicator insets:

Swift 3 的答案,基于 Daniel Jones 提出的答案,但更安全(感谢守卫),更简洁且滚动指示器插入一致:

##代码##