当键盘出现Swift时发出移动视图

时间:2016-05-21 22:16:12

标签: ios swift user-interface textview uitextfield

我正在使用滚动视图和自动布局在键盘出现时移动视图并隐藏我的一个文本输入元素。为此,我使用以下功能。

问题在于我无法让它同时适用于文本字段和文本视图。我已经研究了很多,并尝试实现我在SO和其他资源上找到的所有答案,但大多数答案只涉及单个文本字段而不是多个,我没有找到文本字段和文本视图的单一解决方案。

我知道下面的代码是为文本字段设计的,但是我正在尝试修改它以使用文本视图,因为我发现在键盘出现时移动视图的所有不同方式都是最好的对我来说。

我想知道是否有办法使用我当前的代码让视图移动我的文本字段和文本视图。我也想知道这是否是移动视图的最佳方式。

键盘出现时移动视图的功能:

func keyboardWillShow(sender: NSNotification) {
    let info: NSDictionary = sender.userInfo!
    let value: NSValue = info.valueForKey(UIKeyboardFrameBeginUserInfoKey) as! NSValue
    let keyboardSize: CGSize = value.CGRectValue().size
    let contentInsets: UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize.height + 20, 0.0)
    scrollView.contentInset = contentInsets

    var aRect: CGRect = self.view.frame
    aRect.size.height -= keyboardSize.height
    let activeTextFieldRect: CGRect? = myTextField?.frame
    let activeTextFieldOrigin: CGPoint? = activeTextFieldRect?.origin
    if (!CGRectContainsPoint(aRect, activeTextFieldOrigin!)) {
        scrollView.scrollRectToVisible(activeTextFieldRect!, animated:true)
    }
}

func keyboardWillHide(sender: NSNotification) {
    let contentInsets: UIEdgeInsets = UIEdgeInsetsZero
    scrollView.contentInset = contentInsets
}

func textFieldDidBeginEditing(textField: UITextField) {
    myTextField = textField
    scrollView.scrollEnabled = true
}

func textFieldDidEndEditing(textField: UITextField) {
    myTextField = nil
    scrollView.scrollEnabled = true
} 

我已尝试实施textViewDidBeginEditingtextViewDidEndEditing,然后在此行中分配myTextView代替let activeTextFieldRect: CGRect? = myTextField?.frame,但这似乎是一种草率的方式来做到这一点,无论如何都不起作用。非常感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

第一步是确定作为当前第一响应者的文本字段或文本视图。使用textField和textView委托来正确地确定第一个响应者或遍历所有文本字段和文本视图,通过执行以下操作来查看哪个是第一个响应者:

func activeItemRect() -> CGRect? {
        for textField in textFields {
            if textField.isFirstResponder() { return textField.frame }
        }
        for textView in textViews{
            if textView.isFirstResponder() { return textView.frame }
        }
        return nil
    }

第二步是确定当前项目是否在视图的可见部分。这样做是通过检查所选项目的原点是否在视图的可见矩形内。您应该检查所选项目的中心或底部而不是其原点,因为有时原点将位于可见视图rect中,但会被显示在键盘顶部的iOS文本输入建议面板隐藏。

在我用于测试您的方案的整个代码下方发布:

class ViewController: UIViewController {

    @IBOutlet var textFields: [UITextField]!
    @IBOutlet var textViews: [UITextView]!
    @IBOutlet weak var scrollView: UIScrollView!

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
        NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillShow:", name: UIKeyboardWillShowNotification, object: nil)
        NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillHide:", name: UIKeyboardWillHideNotification, object: nil)
    }

    override func viewWillDisappear(animated: Bool) {
        super.viewWillDisappear(animated)
        NSNotificationCenter.defaultCenter().removeObserver(self)
    }


    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        for textField in textFields { textField.resignFirstResponder() }
        for textView in textViews{ textView.resignFirstResponder() }
    }

    func activeItemRect() -> CGRect? {
        for textField in textFields {
            if textField.isFirstResponder() { return textField.frame }
        }
        for textView in textViews{
            if textView.isFirstResponder() { return textView.frame }
        }
        return nil
    }

    func keyboardWillShow(sender: NSNotification) {
        let info: NSDictionary = sender.userInfo!
        let value: NSValue = info.valueForKey(UIKeyboardFrameBeginUserInfoKey) as! NSValue
        let keyboardSize: CGSize = value.CGRectValue().size
        let contentInsets: UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize.height + 20, 0.0)
        scrollView.contentInset = contentInsets

        var aRect: CGRect = self.view.frame
        aRect.size.height -= keyboardSize.height
        let activeTextFieldRect: CGRect? = activeItemRect()
        let activeTextFieldCentre: CGPoint? = CGPointMake(CGRectGetMidX(activeTextFieldRect!), CGRectGetMidY(activeTextFieldRect!))
        if (!CGRectContainsPoint(aRect, activeTextFieldCentre!)) {
            scrollView.scrollRectToVisible(activeTextFieldRect!, animated:true)
        }
    }

    func keyboardWillHide(sender: NSNotification) {
        let contentInsets: UIEdgeInsets = UIEdgeInsetsZero
        scrollView.contentInset = contentInsets
    }

}

首先,我为所有文本字段创建了一个IBOutletCollection。 然后我为所有文本视图创建了一个IBoutletCollection。 然后创建的方法将循环遍历所有textFields和textViews并返回活动项的框架。

其余的代码与你正在做的90%相似。 唯一的区别是检查所选项目的原点是否位于视图的可见部分内,而不是检查所选项目的中心是否位于视图的可见部分内。