根据字体大小将文本滚动到UITextView中的特定点

时间:2018-08-29 15:04:27

标签: ios xcode scroll uitextview nsrange

当用户在textview本身之外按一个按钮时(在iOS上),我希望UITextView滚动到特定点(一个单词,或者更好的是一个断点:“ >>>”)。字体大小可以根据用户交互而变化(即用户可以增大或减小字体大小)。文本本身由用户粘贴(用户交互地添加断点)。

我正在尝试通过获取断点(“ >>>”)的y位置(以像素为单位),然后根据(使用setContentOffset)设置textView的偏移量来实现这一点。

问题是我得到的y点是错误的!

这是我的代码的一小段(仅重复一次“ >>>”):

NSRange range = [self.textview.text rangeOfString:@">>>"];

UITextPosition *beginning = self.textview.beginningOfDocument;
UITextPosition *start = [self.textview positionFromPosition:beginning offset:range.location];
UITextPosition *end = [self.textview positionFromPosition:start offset:range.length];
UITextRange *textRange = [self.textview textRangeFromPosition:start toPosition:end];
CGRect rect = [self.textview firstRectForRange:textRange];

[self.textview setContentOffset:CGPointMake(0, rect.origin.y)];

我的方法有什么问题?我觉得有一种更好(更轻松)的方法来做同样的事情...

PS:我发现了另一个与同一问题有关的主题,但是该主题很快,我无法翻译:Scroll UITextView to specific text

2 个答案:

答案 0 :(得分:0)

您需要将rect转换为文本视图坐标空间。

像这样尝试:

// get the range
NSRange range = [self.textview.text rangeOfString:@">>>"];

// get the rect in the textview's coordinate space
CGRect foundRect = [self frameOfTextRange:range inTextView:self.textview];

// scroll the found rect into view
[self.textview setContentOffset:CGPointMake(0.0, foundRect.origin.y) animated:YES];

使用此方法(在此处找到:https://stackoverflow.com/a/9606413/6257435):

- (CGRect)frameOfTextRange:(NSRange)range inTextView:(UITextView *)textView
{
    // ensure textview layouManager has been processed
    [textView.layoutManager ensureLayoutForTextContainer:textView.textContainer];

    UITextPosition *beginning = textView.beginningOfDocument;
    UITextPosition *start = [textView positionFromPosition:beginning offset:range.location];
    UITextPosition *end = [textView positionFromPosition:start offset:range.length];
    UITextRange *textRange = [textView textRangeFromPosition:start toPosition:end];
    CGRect rect = [textView firstRectForRange:textRange];
    return [textView convertRect:rect fromView:textView.textInputView];
}

您当然需要添加错误处理(对于未找到的文本等)。

答案 1 :(得分:0)

我迅速地尝试了上面的事情,发现计算rect然后滚动到该rect没有任何意义。您只需调用func scrollRangeToVisible(_ range: NSRange)即可滚动到textView中的单词。

let range: Range = self.textView.text.range(of: "amendment")!
let nsRange = NSRange(range, in: self.textView.text)

self.textView.scrollRangeToVisible(nsRange)