键盘可见时更改Y原点时的奇怪UIView行为

时间:2016-09-20 21:41:10

标签: ios swift uiview

上下文

我有一个包含UITextView的UIView。我想在键盘可见时移动UIView。所以我的想法是change the Y position

问题:

有时,当键盘仍然可见时,UIView会回到其初始Y位置。即使我关注输入,它也不会再回来了。我真的不知道为什么。

插图(gif):

https://d17oy1vhnax1f7.cloudfront.net/items/2K0z3P1j1x2f0X2X1B2v/ci.gif

PS:键盘在Gif中出现3次。它循环,所以很难区分结束。

代码

我做了什么,首先我添加了通知观察员:

NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillChangeFrame), name: NSNotification.Name.UIKeyboardWillChangeFrame, object: nil)

然后我定义了键盘切换处理程序:

func keyboardWillChangeFrame(notification: NSNotification) {

    let info = notification.userInfo!
    let keyboardFrame: CGRect = (info[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue

    self.keyboardInfo["isVisible"] = self.view.frame.size.height - keyboardFrame.origin.y != 0
    self.keyboardInfo["height"] = keyboardFrame.size.height
    self.keyboardInfo["animationDuration"] = info[UIKeyboardAnimationDurationUserInfoKey] as! Double
    self.keyboardInfo["animationCurve"] = info[UIKeyboardAnimationCurveUserInfoKey] as! UInt

    if self.keyboardInfo["isVisible"] as! Bool {
        self.moveCommentInputUp()
    } else {
        self.moveCommentInputDown()
    }

}

之后,我已经定义了在评论输入视图中向上/向下移动的方法:

func moveCommentInputUp() {

    print("Moving up... ", self.commentFormView.frame.origin.y, " to ", self.view.frame.size.height - (self.keyboardInfo["height"] as! CGFloat) - self.commentFormView.frame.size.height)

    UIView.beginAnimations(nil, context: nil)
    UIView.setAnimationDuration(self.keyboardInfo["animationDuration"] as! TimeInterval)
    UIView.setAnimationCurve(UIViewAnimationCurve(rawValue: Int(self.keyboardInfo["animationCurve"] as! UInt))!)
    UIView.setAnimationBeginsFromCurrentState(true)

    ViewUtil.changeViewFrame(view: self.commentFormView, yPosition: self.view.frame.size.height - (self.keyboardInfo["height"] as! CGFloat) - self.commentFormView.frame.size.height)
    ViewUtil.removeShadowToView(self.commentFormLauncherButton)

    UIView.commitAnimations()

}

func moveCommentInputDown() {

    print("Moving down... ", self.commentFormView.frame.origin.y, " to ", self.view.frame.size.height)

    UIView.beginAnimations(nil, context: nil)
    UIView.setAnimationDuration(self.keyboardInfo["animationDuration"] as! TimeInterval)
    UIView.setAnimationCurve(UIViewAnimationCurve(rawValue: Int(self.keyboardInfo["animationCurve"] as! UInt))!)
    UIView.setAnimationBeginsFromCurrentState(true)

    ViewUtil.changeViewFrame(view: self.commentFormView, yPosition: self.view.frame.size.height)
    ViewUtil.addShadowToView(commentFormLauncherButton, position: CGSize(width: 0, height: 5))

    UIView.commitAnimations()

}

按钮的操作是

@IBAction func showCommentForm(_ sender: UIButton) {

    self.commentInput.becomeFirstResponder()

}

日志(请参阅Gif)显示视图从568 - 屏幕底部 - 再次移动到568

// The numbers show the initial and the final value of the keyboard Y position

// Click on button to focus the input
Moving up...  568.0  to  282.0
// Tap anywhere
Moving down...  282.0  to  568.0

// Click again on button to focus the input
Moving up...  568.0  to  282.0
///// Write "hhh". The view is gone, I don't know why.
// Tap anywhere
Moving down...  568.0  to  568.0    // The view seems to move from 568 to 568, hugh

// Click on button to focus the input
Moving up...  568.0  to  282.0      // This didn't work apparently
// Tap anywhere
Moving down...  568.0  to  568.0    // 568 to 568 again

我错过了什么吗?

系统:iOS 9,Xcode 8,Swift 3

2 个答案:

答案 0 :(得分:4)

好的,这是一个不需要CocoaPods的解决方案。

我的方法是在键盘出现和消失时设置textField底部约束的常量。这意味着您需要创建对textField的底部约束的引用。

@IBOutlet weak var textFieldBottomConstraint: NSLayoutConstraint!

我开始在viewDidLoad中设置NSNotification.Name.UIKeyboardWillShow和UIKeyboardWillHide上的观察者,而不是UIKeyboardWillChangeFrame:

NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotification), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotification), name: NSNotification.Name.UIKeyboardWillHide, object: nil)

接下来我设置选择器及其功能来设置textField底部约束的常量:

func handleKeyboardNotification(notification: NSNotification) {
    if let userInfo = notification.userInfo {
        let keyboardFrameValue = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)
        let keyboardFrame = keyboardFrameValue?.cgRectValue

        let isKeyboardShowing = notification.name == NSNotification.Name.UIKeyboardWillShow

        textFieldBottomConstraint.constant = isKeyboardShowing ? keyboardFrame!.height + 4 : 4
        self.view.layoutIfNeeded()
    }
}

请注意,textFieldBottomConstraint是底部约束的引用变量。

这样做会使textField在键盘出现或消失时设置它的底部约束,并且不会遇到您遇到的奇怪故障。

希望这会有所帮助,并且不要犹豫要求澄清!

致YouTuber的积分让我们构建该应用程序!通过此视频提供解决方案:

https://www.youtube.com/watch?v=p8IaS5lmhuM

答案 1 :(得分:2)

为了让您了解如何绕过键盘的任何问题以及输入字段的问题,请查看:

pod 'IQKeyboardManagerSwift'

IQKeyboardManagerSwift / Git Link

我曾经像你一样手动移动所有内容,但是使用此框架,您只需要在AppDelegate内实现一次,并且它可以100%自动完成。无论是垂直还是水平。如果在TextFields或Views中或者是什么。从那以后我就在每个应用程序中使用它。

enter image description here

要在键盘上附加UIView,您需要使用InputAccessoryView

    @IBOutlet weak var textField: UITextField!

override func viewDidLoad() {
    super.viewDidLoad()

    let customView = UIView(frame: CGRectMake(0, 0, 10, 100))
    customView.backgroundColor = UIColor.redColor()
    textField.inputAccessoryView = customView
}

如果您更喜欢使用框架安全时间,我建议您使用CHGInputAccessoryView

enter image description here

我希望这会对你有所帮助。