为了支持UIAccessibilityReadingContent协议(protocol),我需要UITextView来回答有关其行的问题。这些是我需要实现的协议(protocol)方法:

  • accessibilityLineNumberForPoint:
  • accessibilityContentForLineNumber:
  • accessibilityFrameForLineNumber:
  • accessibilityPageContent
    我认为NSLayoutManager可以为我提供帮助,但是我对此并不了解。我已经弄清了其中的一些(我认为),但仍然需要一些帮助。

    Apple有一些示例代码(here),可以使我获得文本 View 中的行数:
    NSLayoutManager *layoutManager = [textView layoutManager];
    unsigned numberOfLines, index, numberOfGlyphs =
            [layoutManager numberOfGlyphs];
    NSRange lineRange;
    for (numberOfLines = 0, index = 0; index < numberOfGlyphs; numberOfLines++){
        (void) [layoutManager lineFragmentRectForGlyphAtIndex:index
                effectiveRange:&lineRange];
        index = NSMaxRange(lineRange);
    }
    

    我认为上面的lineRange可以在NSLayoutManager上使用此方法来计算行rects:
    - (NSRect)boundingRectForGlyphRange:(NSRange)glyphRange inTextContainer:(NSTextContainer *)container
    

    在给定lineRanges的情况下,我应该能够使用(通过找到包含字形索引的lineRange来计算一个点的行号:
    - (NSUInteger)glyphIndexForPoint:(CGPoint)point inTextContainer:(NSTextContainer *)container fractionOfDistanceThroughGlyph:(CGFloat *)partialFraction
    

    那么剩下的就是,在给定行号的情况下,如何获取行的内容(作为NSString)?

    最佳答案

    在一个简单的解决方案中思考,这是一个小代码,可重现您所需的内容

    - (void)analyse:(UITextView *)textView
    {
        NSLayoutManager *layoutManager = [textView layoutManager];
        NSString *string = textView.text;
        unsigned numberOfLines, index, stringLength = [string length];
    
        NSMutableArray *ranges = [NSMutableArray new];
        NSMutableArray *frames = [NSMutableArray new];
        for (index = 0, numberOfLines = 0; index < stringLength; numberOfLines++)
        {
            NSRange tmprange;
            NSRange range = [string lineRangeForRange:NSMakeRange(index, 0)];
            CGRect rect = [layoutManager lineFragmentRectForGlyphAtIndex:index
                                               effectiveRange:&tmprange];
    
            [ranges addObject:[NSValue valueWithRange:range]];
    
            [frames addObject:[NSValue valueWithCGRect:rect]];
            index = NSMaxRange(tmpRange);
        }
        self.ranges = ranges;
        self.frames = frames;
        self.numberOfLines = numberOfLines;
    }
    

    请看一下属性:
    self.ranges = ranges;
    self.frames = frames;
    self.numberOfLines = numberOfLines;
    

    您可以在类中具有以下内容来创建此属性:
    @property (nonatomic) NSInteger numberOfLines;
    @property (strong, nonatomic) NSArray *ranges;
    @property (strong, nonatomic) NSArray *frames;
    

    我建议您将分析调用添加到以下委托(delegate)中:
    - (void)textViewDidChange:(UITextView *)textView
    

    在那里,例如,您可以在分析后得到刚做的第二行的帧: self.frames [1]

    或获取第二行的文本: [textView.text substringWithRange:[self.ranges [1] rangeValue]]

    例如这样的例子:
    if (self.numberOfLines > 1)
    {
        NSRange range = [self.ranges[1] rangeValue];
        NSLog(@"2nd line = %@", [textView.text substringWithRange:range]);
        NSLog(@"2nd line frame = %@", self.frames[1]);
    }
    

    将所有帧都放在 self.frames 中,我认为您可以轻松地完成另一件事,请使用坐标猜测行号。

  • 10-01 03:45