Scrollview和键盘Swift

时间:2014-11-01 12:18:46

标签: ios view swift scroll

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

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

感谢!!!!! (对不起英语错误)

14 个答案:

答案 0 :(得分:105)

在ViewDidLoad中,注册通知:

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

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

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
}

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

答案 1 :(得分: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)

然后:

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
}

答案 2 :(得分:17)

这是一个完整的Swift 4解决方案,使用保护和简洁的代码。加上bottom中的正确代码,只能将@IBOutlet weak var scrollView: UIScrollView! override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) registerNotifications() } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(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) } @objc 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 func keyboardWillHide(notification: NSNotification){ scrollView.contentInset.bottom = 0 } 重置为0.

items = pd.DataFrame({'event':['A','B','B','A','C','C','C'],
                  'transaction_ID':[1,2,3,4,5,6,7],
                  'previous_trans':[2,3,5,7,4,1,6]})
items["Same_Event_in_prev_trans"]=0

答案 3 :(得分:11)

适用于Swift 4.0

在ViewDidLoad

// setup keyboard event
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillShow), name:UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillHide), name:UIResponder.keyboardWillHideNotification, object: nil)

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

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

答案 4 :(得分:6)

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
}

答案 5 :(得分:4)

阅读你发给我的链接,我找到了一种让它工作的方法,谢谢!:

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

答案 6 :(得分:4)

来自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)

然后:

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

答案 7 :(得分:3)

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

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

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

根据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
}

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

答案 8 :(得分:2)

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

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

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

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

答案 9 :(得分:1)

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

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

答案 10 :(得分:1)

在Swift4中,只需添加以下扩展名。

www.website.com/search?q=wow

答案 11 :(得分:0)

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    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)

}

func keyboardWillShow(_ notification:Notification) {

    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
        tableView.contentInset = UIEdgeInsetsMake(0, 0, keyboardSize.height, 0)
    }
}
func keyboardWillHide(_ notification:Notification) {

    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
        tableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0)
    }
}

答案 12 :(得分:0)

万一有人在寻找此解决方案的Objective-C代码:

- (void)keyboardWasShown:(NSNotification *)notification {
        NSDictionary* info = [notification userInfo];
        CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
        UIEdgeInsets contentInsets = baseScrollView.contentInset;
        contentInsets.bottom = kbSize.height;
        baseScrollView.contentInset = contentInsets;
    }

    - (void)keyboardWillBeHidden:(NSNotification *)notification {
        UIEdgeInsets contentInsets = UIEdgeInsetsZero;
        baseScrollView.contentInset = contentInsets;
        [baseScrollView endEditing:YES];
    }

答案 13 :(得分:0)

在我的情况下是

ScrollView  -> 表格检视  -> TableViewCell

所以我必须相对于键盘框架获得y位置,并检查键盘y位置和我的活动字段y位置是否相交

   @objc func keyboardWillShow(_ notification: Foundation.Notification) {

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

        var contentInset:UIEdgeInsets = self.scrollView!.contentInset
        contentInset.bottom = keyboardFrame.size.height
        let loc = self.activeTextField?.convert(activeTextField!.bounds, to: self.view)

        if keyboardFrame.origin.y <  loc!.origin.y {
            self.scrollView?.contentOffset = CGPoint.init(x: (self.scrollView?.contentOffset.x)!, y: loc!.origin.y)
        }

        if self.scrollView?.contentInset.bottom == 0 {
            self.scrollView?.contentInset = contentInset
        }

    }