如何根据框架的大小为UISCrollView/UitextView分开字符串



我当前正在尝试在RSS feed中阅读,并将长段落的文本分离为启用了分页的UISCrollView。我需要将文本分为不同的页面,也就是适合每个页面上的内容,然后将字符串分开。我不确定是否有标准,我认为这是大多数RSS读取应用程序在多个页面上分开其信息的方式。有人知道如何解决这个问题吗?我不想在文字不合格之前逐字看字母。

编辑:

这是一个不错的开始,但是示例代码几乎涉及我试图避免并且不知道如何解决的问题。该范围为UITEXTVIEW错误地计算。我更改字体,如下所示。一切都在尝试在 - (nsrange)visiblerangeoftextview :( uitextview *)textView中进行计算。此方法由 - (void)AdvidTextDisplay调用,在设置UITEXTVIEW的文本后,外部类调用。我不知道为什么将内容大小设置为屏幕的帧大小不限制视图(如下所示),也不知道为什么此方法将完整的字符串长度返回为范围。

而不是重迭代的计算,我将完整(从上一页的结尾开始)到文本视图,并获得最后显示的字符位置。然后,很容易执行快速向后搜索以截断单词/句子。


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

带有Pager的基本项目,但不是从这里获取文本视图

- (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;

从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
    }
}

最新更新