ios - как найти видимый диапазон текста в UITextView? - PullRequest
17 голосов
/ 20 мая 2011

как найти текст, видимый в прокручиваемом, нередактируемом UITextView?

например, мне может понадобиться показать следующий абзац, затем я хочу найти текущий видимый диапазон текста и использовать его для вычислениясоответствующий диапазон и используйте scrollRangeToVisible: для прокрутки текстового представления

Ответы [ 5 ]

7 голосов
/ 07 августа 2012

Я нахожу другое решение здесь. Это лучший способ решить эту проблему в моих глазах. 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]);
}

Предполагается расположение текста сверху вниз, слева направо. Если вы хотите, чтобы он работал для других направлений компоновки, вам придется работать усерднее. :)

4 голосов
/ 24 мая 2011

Я бы сделал так, чтобы вычислить все размеры каждого абзаца.С sizeWithFont: constrainedToSize: lineBreakMode:

вы сможете определить, какой абзац видим, из [textView contentOffset].

для прокрутки, не используйте scrollRangeToVisible, просто используйте setContentOffset:Параметр y CGPoint для этого должен быть либо суммой всех высотных размеров для следующего абзаца, либо просто добавить 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];
3 голосов
/ 23 апреля 2016

Если вы хотите решение 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))
    }
}
1 голос
/ 26 марта 2017

Swift 3.0 / 3.1 решение на основе " Лапши смерти " ответа .

public extension UITextView {

    public var visibleRange: NSRange? {
        if let start = closestPosition(to: contentOffset) {
            if let end = characterRange(at: CGPoint(x: contentOffset.x + bounds.maxX, y: contentOffset.y + bounds.maxY))?.end {
                return NSMakeRange(offset(from: beginningOfDocument, to: start), offset(from: start, to: end))
            }
        }
        return nil
    }
}
1 голос
/ 24 мая 2011

Один вариант, который у вас есть, - это использовать UIWebView вместо UITextView.Затем вы можете использовать якоря и JavaScript, чтобы прокрутить до соответствующих мест в тексте.Возможно, вы можете вставить якоря программно в начале каждого абзаца, чтобы сделать это проще.

...