【问题标题】:Strange UIView behaviour when changing Y origin when Keyboard is visible键盘可见时更改 Y 原点时的奇怪 UIView 行为
【发布时间】:2017-01-28 23:21:51
【问题描述】:

上下文:

我有一个包含 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

【问题讨论】:

    标签: ios swift uiview


    【解决方案1】:

    要让您对如何绕过任何类型的键盘问题和输入字段问题有不同的想法,请查看:

    pod 'IQKeyboardManagerSwift'

    IQKeyboardManagerSwift/Git Link

    我曾经像您一样手动移动所有内容,但是使用此框架,您只需在 AppDelegate 中实现一次,它就可以完全 100% 自动运行。不管是垂直的还是水平的。如果在 TextFields 或 Views 或其他任何地方。从那以后,我在每个应用程序中都使用它。

    要像您想要的那样在键盘上附加 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

    希望对你有帮助。

    【讨论】:

    • 实际上,我希望我的输入刚好在键盘上方(带有箭头和完成按钮的额外视图位于此处)。所以无论如何我都必须处理同样的问题..
    • 所以你希望它像“Instagram -> 发表评论”那样?嗯,是。那不好意思了。我想这个框架不会为你解决问题。
    • 是的。第二个看起来很棒。为什么这样的库在 Github 上只有 3 星?
    • 很高兴为您提供帮助!和好。大多数人使用框架并使用 stack 和 co 的帮助,却没有回馈喜欢和投票之类的东西......
    • 拿第一个。最好的例子。 7,111 颗星。好的。但是根据 cocoapods 的 486,840 次下载。 7.111 是 486.840 的 1.46%
    【解决方案2】:

    好的,这是一个不需要 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

    【讨论】:

    • 哇!使用底部约束要好得多!!!我添加了一些动画,现在可以按预期工作了。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-06
    • 1970-01-01
    • 1970-01-01
    • 2023-03-22
    • 2016-11-18
    相关资源
    最近更新 更多