根据字体大小将文本滚动到 UITextView 中的特定点
Scroll text to specific point in UITextView depending on font size
我希望我的 UITextView 在用户按下 textview 本身之外的按钮(在 iOS 上)时滚动到特定点(一个词,或者更好的断点:“>>>”)。字体大小可以根据用户交互而变化(即用户可以增大或减小字体大小)。文本本身由用户粘贴(用户以交互方式添加断点)。
我试图通过获取断点 (">>>") 的 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:我发现了另一个与同一问题相关的主题,但它在 swift 中,我无法翻译它:
您需要将 rect
转换为文本视图坐标 space。
这样试试:
// 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];
使用此方法(在此处找到:):
- (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];
}
当然,您需要添加错误处理(对于找不到文本等)。
我在 swift 中尝试了以上操作,发现计算矩形然后滚动到该矩形毫无意义。您只需调用 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)
我希望我的 UITextView 在用户按下 textview 本身之外的按钮(在 iOS 上)时滚动到特定点(一个词,或者更好的断点:“>>>”)。字体大小可以根据用户交互而变化(即用户可以增大或减小字体大小)。文本本身由用户粘贴(用户以交互方式添加断点)。
我试图通过获取断点 (">>>") 的 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:我发现了另一个与同一问题相关的主题,但它在 swift 中,我无法翻译它:
您需要将 rect
转换为文本视图坐标 space。
这样试试:
// 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];
使用此方法(在此处找到:):
- (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];
}
当然,您需要添加错误处理(对于找不到文本等)。
我在 swift 中尝试了以上操作,发现计算矩形然后滚动到该矩形毫无意义。您只需调用 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)