是否可以在scrollview中使用pageviewcontroller?

时间:2018-03-10 21:36:02

标签: ios swift uiscrollview uipageviewcontroller

我有一个pageviewcontroller,它水平滚动,显示问题和答案。

pageviewcontroller的contentView填充了一个scrollview,其中有一些堆栈视图,其中一个有一个textView,供用户输入。

enter image description here

当用户点击textView时,键盘会弹出,有时会覆盖textView。当我尝试垂直滚动时,正如我希望滚动视图允许的那样,滚动视图没有响应,我只能水平滚动到下一页视图。

问题在于,当用户点击文本视图后弹出键盘时,文本视图可能隐藏在键盘下方,因此用户无法看到他键入的内容。我想点击键盘时向上滚动视图,这样用户就可以看到输入内容了。

3 个答案:

答案 0 :(得分:0)

这叫做“键盘管理” 你必须:

1)设置键盘的观察者显示和键盘消失动作

2)键盘出现时更新底部约束。

3)当键盘消失时再次更新。

4)当视图消失时,删除观察者。

分步说明,例如:Move view with keyboard using Swift

但我的建议是更新约束,而不是更新,就像在教学中一样。或者,也许,您可以为内容设置偏移量

答案 1 :(得分:0)

您应该在堆栈视图中设置底部约束 然后按照以下方式控制你的类:

class yourClassViewController: UIViewController {
// MARK: Properties
@IBOutlet weak var bottomConstraint: NSLayoutConstraint!

然后在你的viewDidLoad方法中写这样:

 override func viewDidLoad() {
    super.viewDidLoad()
    NotificationCenter.default.addObserver(self,
                                           selector: #selector(self.keyboardNotification(notification:)),
                                           name: NSNotification.Name.UIKeyboardWillChangeFrame,
                                           object: nil)


    // Do any additional setup after loading the view.
}

以下:

   deinit {
    NotificationCenter.default.removeObserver(self)
}

@objc func keyboardNotification(notification: NSNotification) {
    if let userInfo = notification.userInfo {
        let endFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue
        let endFrameY = endFrame?.origin.y ?? 0
        let duration:TimeInterval = (userInfo[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0
        let animationCurveRawNSN = userInfo[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber
        let animationCurveRaw = animationCurveRawNSN?.uintValue ?? UIViewAnimationOptions.curveEaseInOut.rawValue
        let animationCurve:UIViewAnimationOptions = UIViewAnimationOptions(rawValue: animationCurveRaw)
        if endFrameY >= UIScreen.main.bounds.size.height {
            self.bottomConstraint?.constant = 0.0
        } else {
            self.bottomConstraint?.constant = endFrame?.size.height ?? 0.0
        }
        UIView.animate(withDuration: duration,
                       delay: TimeInterval(0),
                       options: animationCurve,
                       animations: { self.view.layoutIfNeeded() },
                       completion: nil)
    }
}

对于touchsBegan方法中的消失键盘你应该这样写:

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

答案 2 :(得分:0)

使用通知观察者处理键盘显示和隐藏事件:

// keyboard will show
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShowAction(_:)), name: .UIKeyboardWillShow, object: nil)

// keyboard will hide
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHideAction(_:)), name: .UIKeyboardWillHide, object: nil)

键盘即将出现时,您可以执行以下操作:

// keyboard will show action
@objc private func keyboardWillShowAction(_ notification: NSNotification) {

    currentScrollViewOffset = scrollView.contentOffset

    let keyboardFrame = notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue
    let keyboardHeight = keyboardFrame?.cgRectValue.height
    let padding: CGFloat = 32

    // if text field view would be obstructed by keyboard, apply minimum-needed scroll view offset
    if activeTextFieldMaxYOnScreen! > (UIScreen.main.bounds.height - keyboardHeight! - padding) {

        let temporaryOffset = activeTextFieldMaxYOnScreen! - (UIScreen.main.bounds.height - (keyboardHeight! + padding))
        scrollView.setContentOffset(CGPoint(x: 0, y: currentScrollViewOffset.y + temporaryOffset), animated: true)

    }

    scrollView.addGestureRecognizer(tapToDismissKeyboard)
    scrollView.isScrollEnabled = false

}

然后在键盘解除时恢复:

// keyboard will hide action
@objc private func keyboardWillHideAction(_ notification: NSNotification) {

    scrollView.setContentOffset(currentScrollViewOffset, animated: true)
    scrollView.removeGestureRecognizer(tapToDismissKeyboard)
    scrollView.isScrollEnabled = true

}

deinit方法中删除观察者也是一种很好的做法:

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

请注意,currentScrollViewOffsetactiveTextFieldMaxYOnScreen是视图控制器的实例属性。要获取activeTextFieldMaxYOnScreen值,您可以从文本字段委托中获取它:

// text field should begin editing
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {

    // convert text field line's max-y to perceived max-y on the screen
    let line = textField.viewWithTag(123)
    activeTextFieldMaxYOnScreen = (line?.convert((line?.bounds.origin)!, to: nil).y)! + (line?.frame.height)!
    return true

}