【问题标题】:Following cursor in dynamic UITextView with UITableView no longer working in iOS 11在动态 UITextView 中跟随光标,UITableView 不再在 iOS 11 中工作
【发布时间】:2017-10-19 00:04:57
【问题描述】:

我创建了一个 UITextView,它在 UITableViewCell 中作为人员类型动态调整大小。

在 iOS 10 上,UITextView 的光标会自动跟随,只需要很少的代码。

UITextViewDelegate 方法textViewDidChange: 中,我使用了这段代码,它更新了文本视图的大小,没有任何跳转。

func textViewDidChange(_ textView: UITextView) {
    UIView.setAnimationsEnabled(false)
    self.tableView.beginUpdates()
    self.tableView.endUpdates()
    UIView.setAnimationsEnabled(true)
    self.tableView.contentOffset = currentOffset
}

在 iOS 11 中,这不再有效,当我键入时,光标会在键盘下消失。请注意,当键盘出现时,我不需要任何更改。

我知道 iOS 11 中与内容插入的工作方式有关的更改,但一直无法弄清楚我需要进行哪些更改才能使其正常工作。

我应该在哪里进行这些更改来修复它?

-- 更新--

事实证明,删除所有这些代码可以解决我在 iOS 11 中的问题,并且 iOS 11 句柄在我自动键入时向下滚动以跟随光标而不会出现任何问题。

我剩下的一个问题是,在 UITextView 停止更新 UITextViews 大小之前,我最多只能在 UITextView 中输入 28 行文本。

【问题讨论】:

  • 你把这个textView的行数设置为零了吗?
  • 你能提供一个minimal working example吗?
  • 尝试过 textView.textContainer.maximumNumberOfLines = 0。这不会限制行数
  • @BrunoFulberWide 我不认为这是 IB 中的一个选项。
  • @ThanhPham 除了上面的代码,其余的是一个 UITableView,其中一个单元格中有一个 UITextView。 UITextView 被固定到具有大于或等于高度约束的单元格侧面。除了您在上面看到的之外,没有其他自定义代码,因此我无需提供任何其他内容。

标签: ios swift uitableview autolayout uitextview


【解决方案1】:

我有同样的问题,一个 UITableViewController 和一个 UITableViewCell 在一个单元格中包含一个不可滚动的可编辑 UITextView,并且光标会在 iOS11 中的键盘后面。在之前的 iOS 版本中运行良好。

我终于根据这篇文章和其他文章找到了解决方法:

- (void)textViewDidChange:(UITextView *)textView {
    // handle to UITableView
    UITableView *tableView = ....

    // tell table to resize itself
    [UIView performWithoutAnimation:^{
        [tableView beginUpdates];
        [tableView endUpdates];
    }];

    // get the caret rectangle so we can make sure we scroll it into view.
    CGRect unconvertedRect = [textView caretRectForPosition:textView.selectedTextRange.start];
    CGRect caretRect = [textView convertRect:unconvertedRect toView:tableView];
    // make the rect a little bigger so it's not at the extreme bottom of the view area
    caretRect.size.height += caretRect.size.height / 2;

    // this doesn't seem to work with a simple dispatch_async, but dispatch_after 0.1s seems to work.
    // why, i have no idea.
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [tableView scrollRectToVisible:caretRect animated:NO];
    });
}

希望这对某人有帮助...

【讨论】:

  • 这是在 iOS 11 上为我修复的问题。谢谢。
  • 它可以工作,但由于这个 0.1 秒,仍然有短跳效果。
【解决方案2】:

从 XCode 9 开始,一旦您在 tableview 的大小检查器中设置属性,行的计算就会自动进行。Here, You can check this in image 我对func textViewDidChange(_ textView: UITextView) 进行了一次更改 下面是我的代码

 func textViewDidChange(_ textView: UITextView) {
        UIView.setAnimationsEnabled(false)
        self.tableView.beginUpdates()
        self.tableView.endUpdates()
        UIView.setAnimationsEnabled(true)
        textView.sizeToFit()
    }

它在 iOS 11 中对我来说运行良好

你也可以看到约束,很简单,我使用它没有边距。

还有你的textview光标问题,我建议你IQKeyboardManager,它会像这样管理所有事情。

【讨论】:

  • 感谢这个。我试了一下,它仍然不适合我。你能分享一下你对这个设置的自动布局限制吗?
  • 确认一下,当我用这个设置输入 UITextView 时,光标会在键盘下消失,所以如果你有什么要修复的,可以分享一下吗?
  • 我已经更新了我的答案,请查看。希望对你有帮助。
【解决方案3】:
class TextViewTableCell: UITableViewCell {

    @IBOutlet private weak var textView: UITextView! {
        didSet {
            textView.delegate = self
            textView.isScrollEnabled = false
        }
    }

    var textDidChangeHandler: (((text: String?, shouldScroll: Bool)) -> Void)?

    func textViewDidChange(_ textView: UITextView) {
        let size = textView.bounds.size
        let newSize = textView.sizeThatFits(CGSize(width: size.width, height: .greatestFiniteMagnitude))

        let shouldScroll = size.height != newSize.height ? textView.text.count == textView.selectedRange.location : false
        textDidChangeHandler?((text: textView.text, shouldScroll: shouldScroll))
    }
}

内部数据源cellForRow方法:

// dequeue TextViewTableCell cell
cell.textDidChangeHandler = { [weak self] (text, shouldScroll) in
    guard let this = self else { return }
    // do whatever actions with text if needed
    guard shouldScroll else { return }
    UIView.performWithoutAnimation {
        tableView.beginUpdates()
        tableView.endUpdates() 
    }
    tableView.scrollToRow(at: indexPath, at: .bottom, animated: false)
}

最好有文本视图的最小高度限制(例如 >=44)

【讨论】:

  • 我已经尝试过了,但没有任何运气。我看到发生了一些滚动,但是一旦文本低于键盘级别,tableview 就会向下滚动一点,然后弹回顶部。
  • @MarkReid 好吧,也许在这种情况下,您将 tableView contentInset 设置为错误值?我的例子和 UITableViewController 有关,它默认处理 tableView insets。
  • 感谢您的建议,但我也只是在此特定情况下使用未经修改的 UITableViewController。
【解决方案4】:

我正在使用 sabe 方法来更新一个 textView,它对于超过 28 行的文本都可以正常工作,请确保您设置了所有这些属性:

textView.showsVerticalScrollIndicator = false
textView.isScrollEnabled = false

当我定义 textView 文本时,我调用textView.sizeToFit()

【讨论】:

  • 嗨,这些都设置在我的应用程序中,我仍然遇到同样的问题,但感谢您的回复。
猜你喜欢
  • 1970-01-01
  • 2018-04-06
  • 1970-01-01
  • 1970-01-01
  • 2014-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多