文本分頁顯示(2)

今天我們將介紹iPhone電子書的分頁功能的代碼。製作iPhone電子書時,如果把大段文字放在 UITextView 或 UILabel 裏顯示,是不能分頁的,閱讀時就像再看一大卷滾不到頭的紙帶,用戶體驗很差。下面這段代碼可以實現 UILabel 尺寸固定,根據文本內容和字體動態分頁顯示,電子書方面的應用應該非常有用。 

// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    [super viewDidLoad];
    
    //
    totalPages = 0;
    currentPage = 0;
    
    //
    textLabel.numberOfLines = 0;
    
    //
    if (!text) {
        // 從文件里加載文本串
        [self loadString];
        
        // 計算文本串的大小尺寸
        CGSize totalTextSize = [text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE_MAX]
                                         constrainedToSize:CGSizeMake(textLabel.frame.size.width, CGFLOAT_MAX)
                                    lineBreakMode:UILineBreakModeWordWrap];

        // 如果一頁就能顯示完,直接顯示所有文本串即可。
        if (totalTextSize.height < textLabel.frame.size.height) {
            textLabel.text = text;
        }
        else {
            // 計算理想狀態下的頁面數量和每頁所顯示的字符數量,只是拿來作爲參考值用而已!
            NSUInteger textLength = [text length];
            referTotalPages = (int)totalTextSize.height/(int)textLabel.frame.size.height+1;
            referCharatersPerPage = textLength/referTotalPages;
            
            // 申請最終保存頁面NSRange信息的數組緩衝區
            int maxPages = referTotalPages;
            rangeOfPages = (NSRange *)malloc(referTotalPages*sizeof(NSRange));
            memset(rangeOfPages, 0x0, referTotalPages*sizeof(NSRange));
            
            // 頁面索引
            int page = 0;
            
            for (NSUInteger location = 0; location < textLength; ) {
                // 先計算臨界點(尺寸剛剛超過UILabel尺寸時的文本串)
                NSRange range = NSMakeRange(location, referCharatersPerPage);
                
                // reach end of text ?
                NSString *pageText;
                CGSize pageTextSize;
                
                while (range.location + range.length < textLength) {
                    pageText = [text substringWithRange:range];
                    
                    pageTextSize = [pageText sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE_MAX]
                                        constrainedToSize:CGSizeMake(textLabel.frame.size.width, CGFLOAT_MAX)
                                            lineBreakMode:UILineBreakModeWordWrap];
                    
                    if (pageTextSize.height > textLabel.frame.size.height) {
                        break;
                    }
                    else {
                        range.length += referCharatersPerPage;
                    }
                }
                
                if (range.location + range.length >= textLength) {
                    range.length = textLength - range.location;
                }
                
                // 然後一個個縮短字符串的長度,當縮短後的字符串尺寸小於textLabel的尺寸時即爲滿足
                while (range.length > 0) {
                    pageText = [text substringWithRange:range];
                    
                    pageTextSize = [pageText sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE_MAX]
                                        constrainedToSize:CGSizeMake(textLabel.frame.size.width, CGFLOAT_MAX)
                                            lineBreakMode:UILineBreakModeWordWrap];
                    
                    if (pageTextSize.height <= textLabel.frame.size.height) {
                        range.length = [pageText length];
                        break;
                    }
                    else {
                        range.length -= 2;
                    }
                }
                
                // 得到一個頁面的顯示範圍
                if (page >= maxPages) {
                    maxPages += 10;
                    rangeOfPages = (NSRange *)realloc(rangeOfPages, maxPages*sizeof(NSRange));
                }
                rangeOfPages[page++] = range;
                
                // 更新遊標
                location += range.length;
            }

            // 獲取最終頁面數量
            totalPages = page;
            
            // 更新UILabel內容
            textLabel.text = [text substringWithRange:rangeOfPages[currentPage]];
        }
    }
    
    // 顯示當前頁面進度信息,格式爲:"8/100"
    pageInfoLabel.text = [NSString stringWithFormat:@"%d/%d", currentPage+1, totalPages];
}


////////////////////////////////////////////////////////////////////////////////////////
// 上一頁
- (IBAction)actionPrevious:(id)sender {
    if (currentPage > 0) {
        currentPage--;
        
        NSRange range = rangeOfPages[currentPage];
        NSString *pageText = [text substringWithRange:range];
        
        textLabel.text = pageText;

        //
        pageInfoLabel.text = [NSString stringWithFormat:@"%d/%d", currentPage+1, totalPages];
    }
}

////////////////////////////////////////////////////////////////////////////////////////
// 下一頁
- (IBAction)actionNext:(id)sender {
    if (currentPage < totalPages-1) {
        currentPage++;
        
        NSRange range = rangeOfPages[currentPage];
        NSString *pageText = [text substringWithRange:range];
        
        textLabel.text = pageText;
        
        //
        pageInfoLabel.text = [NSString stringWithFormat:@"%d/%d", currentPage+1, totalPages];
    }
}


發佈了19 篇原創文章 · 獲贊 15 · 訪問量 37萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章