ios - 如何找到UITextView中可见的文本范围?

时间:2011-05-20 05:26:06

标签: iphone ios uiscrollview uitextview

如何找到可滚动,不可编辑的UITextView中可见的文本?

例如我可能需要显示下一段,然后我想查找当前可见文本范围并使用它来计算适当的范围并使用scrollRangeToVisible:滚动文本视图

5 个答案:

答案 0 :(得分:7)

我在这里找到另一个解决方案。 这是解决我眼中这个问题的更好方法。 https://stackoverflow.com/a/9283311/889892

由于UITextView是UIScrollView的子类,因此其bounds属性反映了其坐标系的可见部分。所以这样的事情应该有效:

-(NSRange)visibleRangeOfTextView:(UITextView *)textView {
    CGRect bounds = textView.bounds;
    UITextPosition *start = [textView characterRangeAtPoint:bounds.origin].start;
    UITextPosition *end = [textView characterRangeAtPoint:CGPointMake(CGRectGetMaxX(bounds), CGRectGetMaxY(bounds))].end;
    return NSMakeRange([textView offsetFromPosition:textView.beginningOfDocument toPosition:start],
        [textView offsetFromPosition:start toPosition:end]);
}

这假设从上到下,从左到右的文本布局。如果您想使其适用于其他布局方向,则必须更加努力。 :)

答案 1 :(得分:4)

我这样做的方法是计算每个段落的所有大小。使用sizeWithFont:constrainedToSize:lineBreakMode:

然后,您将能够从[textView contentOffset]中找出可见的段落。

滚动,不要使用scrollRangeToVisible,只需使用setContentOffset:CGPoint y参数应该是下一段所有高度大小的总和,或者只是添加textView.frame.size.height,如果是比下一段的开头更接近。

这有道理吗?

回答评论请求代码(未经测试):

  CGFloat paragraphOffset[MAX_PARAGRAPHS];

    CGSize constraint = CGSizeMake(widthOfTextView, 999999 /*arbitrarily large number*/);
    NSInteger paragraphNo = 0;
    CGFloat offset = 0;

    for (NSString* paragraph in paragraphs) {
        paragraphOffset[paragraphNo++] = offset;
        CGSize paragraphSize = [paragraph sizeWithFont:textView.font constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];
        offset += paragraphSize.height;
    }   

    // find visible paragraph
    NSInteger visibleParagraph = 0;
    while (paragraphOffset[visibleParagraph++] < textView.contentOffset.y);


    // scroll to paragraph 6
    [textView setContentOffset:CGPointMake(0, paragraphOffset[6]) animated:YES];

答案 2 :(得分:3)

如果你想要一个Swift解决方案我会用它:

Swift 2

public extension UITextView {
    public var visibleRange: NSRange? {
        if let start = closestPositionToPoint(contentOffset) {
            if let end = characterRangeAtPoint(CGPointMake(contentOffset.x + CGRectGetMaxX(bounds), contentOffset.y + CGRectGetMaxY(bounds)))?.end {
                return NSMakeRange(offsetFromPosition(beginningOfDocument, toPosition: start), offsetFromPosition(start, toPosition: end))
            }
        }
        return nil
    }
}

Swift 3

public extension UITextView {
    public var visibleRange: NSRange? {
        guard let start = closestPosition(to: contentOffset),
                  end = characterRange(at: CGPoint(x: contentOffset.x + bounds.maxX, 
                                                   y: contentOffset.y + bounds.maxY))?.end 
        else { return nil }
        return NSMakeRange(offset(from: beginningOfDocument, to: start), offset(from: start, to: end))
    }
}

答案 3 :(得分:1)

您拥有的一个选项是使用UIWebView而不是UITextView。然后,您可以使用锚点和JavaScript来滚动到文本中的适当位置。您可以在每个段落的开头以编程方式插入锚点,以使其更容易。

答案 4 :(得分:1)

基于"Noodle of Death" answer的Swift 3.0 / 3.1解决方案。

@Stateful
@LocalBean
public class UserBean
{
  private String name;
  public String getName() { return name; }
  public void setName( String name_ ) { name = name_; }
}