UIScrollView停止在键盘关闭时滚动

时间:2017-01-07 07:34:28

标签: ios uiscrollview swift3

我目前正在使用Swift 3为iPhone开发应用程序但是我遇到了一个滚动视图的问题。 在选择文本字段并显示键盘之前,滚动视图正常工作(即:我可以向上和向下滚动),但是在解除键盘之后,滚动视图不允许我再滚动这是我的问题。 注意:如果我再次选择一个文本字段并使键盘显示它可以正常工作,并在再次被解除后停止工作。

我检查了scrollview的isScrollEnabled属性,似乎已启用。不幸的是,我仍然不太熟悉scrollview的所有细节,似乎无法弄清楚它为何停止工作。

非常感谢任何有关我可以看到的地方的帮助或指示。

编辑:有相当多的代码,但这里是与滚动视图和键盘相关的缩小部分:

class ScrollViewController: UIViewController, UITextViewDelegate, UITextFieldDelegate {
//Scroll view
    @IBOutlet weak var scrollView: UIScrollView!
    //UIView inside the scroll view
    @IBOutlet weak var contentView: UIView!
    //Save button on the top right corner
    @IBOutlet weak var saveButton: UIBarButtonItem!
    //Text field being editted
    var activeTextField:UITextField?

    fileprivate var contentInset:CGFloat?
    fileprivate var indicatorInset:CGFloat?

override func viewDidLoad() {
        contentInset = scrollView.contentInset.bottom
        indicatorInset = scrollView.scrollIndicatorInsets.bottom

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

func adjustInsetForKeyboardShow(_ show: Bool, notification: Notification) {
        let userInfo = notification.userInfo ?? [:]
        let keyboardFrame = (userInfo[UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
        let adjustmentHeight = (keyboardFrame.height + 20) * (show ? 1 : -1)

        scrollView.contentInset.bottom = (contentInset! + adjustmentHeight)
        scrollView.scrollIndicatorInsets.bottom = (indicatorInset! + adjustmentHeight)
    }

    func keyboardWillShow(_ notification: Notification) {
        adjustInsetForKeyboardShow(true, notification: notification)
    }

    func keyboardWillHide(_ notification: Notification) {
        adjustInsetForKeyboardShow(false, notification: notification)
    }

    //Tap gesture to dismiss the keyboard
    @IBAction func hideKeyboard(_ sender: AnyObject) {
        self.view.endEditing(false)
    }

       deinit {
        NotificationCenter.default.removeObserver(self);
    }
}

3 个答案:

答案 0 :(得分:2)

我已经创建了UIViewController的扩展并为scrollView创建了方法。只需要从viewWillAppear()和viewDidDisappear()

调用
extension UIViewController  {

    func registerForKeyboradDidShowWithBlock (scrollview:UIScrollView ,block: ((CGSize?)  -> Void)? = nil ){
        NotificationCenter.default.addObserver(forName: NSNotification.Name.UIKeyboardDidShow, object: nil, queue: nil) { (notification) in
            if let userInfo = (notification as NSNotification).userInfo {
                if let keyboarRect = (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
                    if self.view.findFirstResponder() != nil {
                        let  keyboarRectNew = self.view .convert(keyboarRect, to: self.view)
                        let scrollViewSpace = scrollview.frame.origin.y + scrollview.contentOffset.y
                        let textFieldRect:CGRect =  self.view.findFirstResponder()!.convert(self.view.findFirstResponder()!.bounds, to: self.view)
                        let textFieldSpace = textFieldRect.origin.y + textFieldRect.size.height
                        let remainingSpace =  self.view.frame.size.height - keyboarRectNew.size.height

                        if  scrollViewSpace + textFieldSpace > remainingSpace {
                            let gap =  scrollViewSpace + textFieldSpace - remainingSpace
                            scrollview .setContentOffset(CGPoint(x: scrollview.contentOffset.x, y: gap), animated: true)
                        }
                    }
                }
            }
            block?(CGSize.zero)

        }
    }

    func registerForKeyboardWillHideNotificationWithBlock ( scrollview:UIScrollView ,block: ((Void) -> Void)? = nil) {
        NotificationCenter.default.addObserver(forName: NSNotification.Name.UIKeyboardWillHide, object: nil, queue: nil, using: { (notification) -> Void in
            scrollview.scrollRectToVisible(CGRect(x: 0, y: 0, width: 0, height: 0), animated: true)
            scrollview.contentOffset = CGPoint(x: 0, y: 0)
            scrollview.contentInset =  UIEdgeInsetsMake(0.0, 0.0, 0.0, 0.0)
            scrollview.scrollIndicatorInsets = UIEdgeInsetsMake(0.0, 0.0, 0.0, 0.0);

            block?()
        })
    }

    func deregisterKeyboardShowAndHideNotification (){

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

        self.view.findFirstResponder()?.resignFirstResponder()
    }
}

我创建了UIView的扩展名来创建查找第一响应者方法。

extension UIView {
    func findFirstResponder() -> UIView? {
        if self.isFirstResponder {
            return self
        }
        for subview: UIView in self.subviews {
            let firstResponder = subview.findFirstResponder()
            if nil != firstResponder {
                return firstResponder
            }
        }
        return nil
    }   
}

答案 1 :(得分:2)

创建UIView的扩展并记下此方法。

extension UIView {
    func findFirstResponder() -> UIView? {
        if self.isFirstResponder {
            return self
        }
        for subview: UIView in self.subviews {
            let firstResponder = subview.findFirstResponder()
            if nil != firstResponder {
                return firstResponder
            }
        }
        return nil
    }   
}

答案 2 :(得分:-2)

它们是Objective C中的第三方库,用于处理具有滚动视图,集合视图和表视图的键盘。库的名称是tpkeyboardavoidingscrollview。如果可能的话,尝试嵌入它。