2

我目前正在尝试读取 RSS 提要并将长段落文本分离到启用分页的 UIScrollView 中。我需要将文本分成不同的页面,也就是适合每个页面的内容并将字符串分开。我不确定这样做是否有标准,我认为这是大多数 RSS 阅读应用程序在多个页面上分离信息的方式。有谁知道如何解决这个问题?在文本不适合并继续之前,我不想逐个字母地查看。

编辑:

这是一个好的开始,但是示例代码几乎遇到了我试图避免并且不知道如何解决的问题。此范围为 UITextView 计算不正确。我更改了字体,如下所示。一切都试图在 - (NSRange)visibleRangeOfTextView:(UITextView *)textView 内计算。此方法由 -(void)adjustTextDisplay 调用,该方法在为 UITextView 设置文本后由外部类调用。我不知道为什么将内容大小设置为屏幕的框架大小不会限制视图(如下所示),也不知道为什么此方法会返回完整的字符串长度作为范围。

4

2 回答 2

3

我没有进行繁重的迭代计算,而是将完整的(当然从上一页开始)文本设置为 textView 并获取最后显示的字符位置。然后很容易执行快速向后搜索来截断单词/句子。


我有以下解决方案,跳过最后部分显示的行,以避免滚动并使其看起来更好看,这是一个有点棘手的部分。您仍然需要移动endCutIndex以使其为单词或句子换行。

带有寻呼机但没有文本视图的基础项目取自这里

- (void)viewDidLoad {
    [super viewDidLoad];

    NSString * fullText = @"Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda.";

    pageControlBeingUsed = NO;


    int pageNumber = 0;
    UIFont * theFont = [UIFont boldSystemFontOfSize:30];
    const CGSize charSize = [@"A" sizeWithFont:theFont];

    while (fullText.length > 0) {
        CGRect frame;
        frame.origin.x = self.scrollView.frame.size.width * (pageNumber++);
        frame.origin.y = 0;
        frame.size = self.scrollView.frame.size;

        UIView *subview = [[UIView alloc] initWithFrame:frame];

        UITextView * textView = [[UITextView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)];
        textView.font = theFont;
        [subview addSubview:textView];
        [textView release];


        textView.text = fullText;

        CGRect bounds = textView.bounds;
        // - charSize.height to skip a partially visible line
        // - charSize.width*2 to skip annoying character still displayed at partially visible line
        CGPoint endPoint = CGPointMake(CGRectGetMaxX(bounds) - charSize.width*2, CGRectGetMaxY(bounds) - charSize.height);
        UITextPosition *start = [textView characterRangeAtPoint:bounds.origin].start;
        UITextPosition *end = [textView characterRangeAtPoint:endPoint].end;

        const int startCutIndex = [textView offsetFromPosition:textView.beginningOfDocument toPosition:start];
        const int endCutIndex =   [textView offsetFromPosition:textView.beginningOfDocument toPosition:end];

        NSString * cutText = [fullText substringToIndex:endCutIndex];
        textView.text = cutText;
        fullText = [fullText substringFromIndex:endCutIndex];

        [self.scrollView addSubview:subview];
        [subview release];

        NSLog(@"Page (1-total) %d, start text index %d, end text index %d \ntext:%@", pageNumber, startCutIndex, endCutIndex, cutText);
    }

    const int totalPages = pageNumber;

    self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width * totalPages, self.scrollView.frame.size.height);

    self.pageControl.currentPage = 0;
    self.pageControl.numberOfPages = totalPages;
}

这是 .h 文件的一部分:

@interface FCContentViewController : UIViewController <UIScrollViewDelegate, UITextViewDelegate>{
    UIPageControl *pageControl;   
    NSString *trunkedString;
    UITextView *bodyText;
}
@property (nonatomic, retain) UIScrollView *scrollView;
@property (nonatomic, retain) NSString *bodyTextString;
于 2012-10-23T00:30:26.707 回答
1

从 iOS 7 开始,我在下面的示例代码中包含了一个更优雅的使用 TextKit 的解决方案。这个想法是让 TextKit 的布局管理器处理分离字形并以这种方式正确布置所有内容。这可以防止中途截断单词和大量的灵活性:

class BookView: UIScrollView {

    var bookMarkup: NSAttributedString!
    private let layoutManager = NSLayoutManager()

    override func layoutSubviews() {
        super.layoutSubviews()

        if layoutManager.textContainers.count == 0 {
            buildFrames()
        }
    }

    func buildFrames() {
        let textStorage = NSTextStorage(attributedString: bookMarkup)

        textStorage.addLayoutManager(layoutManager)

        var range = NSMakeRange(0, 0)
        var containerIndex = 0

        while NSMaxRange(range) < layoutManager.numberOfGlyphs {
            let textViewRect = frameForViewAtIndex(containerIndex)
            let containerSize = CGSizeMake(CGRectGetWidth(textViewRect), CGRectGetHeight(textViewRect) - 16) //UITextView adds an 8 margin above and below the container so we take that into consideration here with the 16. heightTracksTextView causes a performance hit when adding multiple containers... so we don't do that instead
            let textContainer = NSTextContainer(size: containerSize)
            layoutManager.addTextContainer(textContainer)

            let textView = UITextView(frame: textViewRect, textContainer: textContainer)

            addSubview(textView)

            containerIndex++

            range = layoutManager.glyphRangeForTextContainer(textContainer)
        }

        contentSize = CGSize(width: CGRectGetWidth(bounds) / 2 * CGFloat(containerIndex), height: CGRectGetHeight(bounds))

        pagingEnabled = true
    }

    private func frameForViewAtIndex(index: Int) -> CGRect {

        var textViewRect = CGRect(origin: CGPointZero, size: CGSize(width: CGRectGetWidth(bounds)/2, height: CGRectGetHeight(bounds)))
        textViewRect = CGRectInset(textViewRect, 10, 20)
        textViewRect = CGRectOffset(textViewRect, CGRectGetWidth(bounds) / 2 * CGFloat(index), 0)
        return textViewRect
    }
}
于 2015-06-26T15:08:52.623 回答