当编辑文本时,保持文本视图在键盘上方

4
我有一个高度动态的文本视图。当用户添加或删除文本时,文本视图的高度会改变。
我的问题是,当用户添加文本并且文本视图增长时,它会消失在键盘后面。我已成功移动了视图以在键盘出现时隐藏文本视图,但我似乎无法弄清如何在高度改变时将其保持在键盘之上。非常感谢任何帮助!
移动视图的函数在键盘出现和消失时:
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
}

你的textView包含在哪里?如果它是一个tableView,请参考https://dev59.com/W2Ml5IYBdhLWcg3we283 - sschale
这不是一个表格视图。文本字段是内容视图的子视图,而内容视图是滚动视图的子视图,滚动视图位于原始视图内部。谢谢! - 01Riv
1个回答

3
因此,需要在光标位置超出边界时告诉包含 scrollView 滚动。我从链接中改编了一个函数来调用此操作。请确保将 scrollView 替换为您的名称。
internal func scrollToCursorForTextView(textView: UITextView) {
    var cursorRect = textView.caretRectForPosition(textView.selectedTextRange!.start)
    cursorRect = scrollView.convertRect(cursorRect, fromView: textView)
    if !self.rectVisible(cursorRect) {
      cursorRect.size.height += 8
      scrollView.scrollRectToVisible(cursorRect, animated: true)
    }
}

internal func rectVisible(rect: CGRect) -> Bool {
    var visibleRect = CGRect()
    visibleRect.origin = scrollView.contentOffset
    visibleRect.origin.y += scrollView.contentInset.top
    visibleRect.size = scrollView.bounds.size
    visibleRect.size.height -= scrollView.contentInset.top + scrollView.contentInset.bottom
    return CGRectContainsRect(visibleRect, rect)
}

Swift 4 更新

internal func scrollToCursorForTextView(textView: UITextView) {
    guard let startOfRange = textView.selectedTextRange?.start else { return }
    var cursorRect = textView.caretRect(for: startOfRange)
    cursorRect = scrollView.convert(cursorRect, from: textView)
    if !rectVisible(rect: cursorRect) {
        cursorRect.size.height += 8
        scrollView.scrollRectToVisible(cursorRect, animated: true)
    }
}

func rectVisible(rect: CGRect) -> Bool {
    var visibleRect = CGRect()
    visibleRect.origin = scrollView.contentOffset
    visibleRect.origin.y += scrollView.contentInset.top
    visibleRect.size = scrollView.bounds.size
    visibleRect.size.height -= scrollView.contentInset.top + scrollView.contentInset.bottom
    return visibleRect.contains(rect)
}

谢谢,我一定会尝试!但是这些函数该如何调用?我应该添加一个通知来监听它们吗? - 01Riv
每当textView的边界发生变化时,您都可以调用它们 - 您说这可能会动态发生。如果您没有一个好的方法,请使用UITextFieldDelegate方法。 - sschale
1
我尝试了在我用来改变文本视图高度的方法中,但什么也没发生,也尝试了在UITextViewDelegate方法中,但那里也没有任何反应。 - 01Riv
添加一些日志以查看发生了什么-我从在TableView中使用中进行了调整。另外一个可能对您有帮助的是使用https://github.com/michaeltyson/TPKeyboardAvoiding(将其作为ScrollView的超类),它可以帮助自动重新计算键盘插入。 - sschale
每次添加新行时,我都会在日志中看到这个。我不确定它的含义是什么。requesting caretRectForPosition: while the NSTextStorage has oustanding changes {0, 1} x位置上的数字每添加一行就会增加。 - 01Riv

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接