2

現在、RSSフィードを読み込んで、長い段落のテキストをページングが有効になっているUIScrollViewに分割しようとしています。テキストを異なるページに分割する必要があります。つまり、各ページに収まるものに合わせて、文字列をそのように分離する必要があります。これを行うための標準があるかどうかはわかりません。これが、ほとんどのRSS読み取りアプリが複数のページで情報を分離する方法であると思います。誰かがこれに取り組む方法を知っていますか?テキストが収まらず、続行するまで、文字ごとに見たくありませんでした。

編集:

これは良いスタートですが、サンプルコードは、私が避けようとしていた問題にほとんど遭遇し、回避する方法がわかりません。この範囲は、UITextViewに対して正しく計算されません。以下のようにフォントなどを変更します。すべてが-(NSRange)visibleRangeOfTextView:(UITextView *)textView内で計算されようとしています。このメソッドは、UITextViewのテキストを設定した後、外部クラスによって呼び出される-(void)adjustTextDisplayによって呼び出されます。コンテンツサイズを画面のフレームサイズに設定してもビューが制限されない理由(以下に示す)も、このメソッドが文字列の全長を範囲として返す理由もわかりません。

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 に答える