制作 iPhone 电子书时,如果把大段文字放在 UITextView 或 UILabel 里显示,是不能分页的,阅读时就像再看一大卷滚不到头的纸带,用户体验很差。下面这段代码可以实现 UILabel 尺寸固定,根据文本内容和字体动态分页显示,电子书方面的应用应该非常有用。
1 // Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
2 - (void)viewDidLoad {
3 [super viewDidLoad];
4
5 //
6 totalPages = 0;
7 currentPage = 0;
8
9 //
10 textLabel.numberOfLines = 0;
11
12 //
13 if (!text) {
14 // 从文件里加载文本串
15 [self loadString];
16
17 // 计算文本串的大小尺寸
18 CGSize totalTextSize = [text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE_MAX]
19 constrainedToSize:CGSizeMake(textLabel.frame.size.width, CGFLOAT_MAX)
20 lineBreakMode:UILineBreakModeWordWrap];
21
22 // 如果一页就能显示完,直接显示所有文本串即可。
23 if (totalTextSize.height
25 }
26 else {
27 // 计算理想状态下的页面数量和每页所显示的字符数量,只是拿来作为参考值用而已!
28 NSUInteger textLength = [text length];
29 referTotalPages = (int)totalTextSize.height/(int)textLabel.frame.size.height+1;
30 referCharatersPerPage = textLength/referTotalPages;
31
32 // 申请最终保存页面NSRange信息的数组缓冲区
33 int maxPages = referTotalPages;
34 rangeOfPages = (NSRange *)malloc(referTotalPages*sizeof(NSRange));
35 memset(rangeOfPages, 0x0, referTotalPages*sizeof(NSRange));
36
37 // 页面索引
38 int page = 0;
39
40 for (NSUInteger location = 0; location
42 NSRange range = NSMakeRange(location, referCharatersPerPage);
43
44 // reach end of text ?
45 NSString *pageText;
46 CGSize pageTextSize;
47
48 while (range.location + range.length
50
51 pageTextSize = [pageText sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE_MAX]
52 constrainedToSize:CGSizeMake(textLabel.frame.size.width, CGFLOAT_MAX)
53 lineBreakMode:UILineBreakModeWordWrap];
54
55 if (pageTextSize.height > textLabel.frame.size.height) {
56 break;
57 }
58 else {
59 range.length += referCharatersPerPage;
60 }
61 }
62
63 if (range.location + range.length >= textLength) {
64 range.length = textLength - range.location;
65 }
66
67 // 然后一个个缩短字符串的长度,当缩短后的字符串尺寸小于textLabel的尺寸时即为满足
68 while (range.length > 0) {
69 pageText = [text substringWithRange:range];
70
71 pageTextSize = [pageText sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE_MAX]
72 constrainedToSize:CGSizeMake(textLabel.frame.size.width, CGFLOAT_MAX)
73 lineBreakMode:UILineBreakModeWordWrap];
74
75 if (pageTextSize.height <&#61; textLabel.frame.size.height) {
76 range.length &#61; [pageText length];
77 break;
78 }
79 else {
80 range.length -&#61; 2;
81 }
82 }
83
84 // 得到一个页面的显示范围
85 if (page >&#61; maxPages) {
86 maxPages &#43;&#61; 10;
87 rangeOfPages &#61; (NSRange *)realloc(rangeOfPages, maxPages*sizeof(NSRange));
88 }
89 rangeOfPages[page&#43;&#43;] &#61; range;
90
91 // 更新游标
92 location &#43;&#61; range.length;
93 }
94
95 // 获取最终页面数量
96 totalPages &#61; page;
97
98 // 更新UILabel内容
99 textLabel.text &#61; [text substringWithRange:rangeOfPages[currentPage]];
100 }
101 }
102
103 // 显示当前页面进度信息&#xff0c;格式为&#xff1a;"8/100"
104 pageInfoLabel.text &#61; [NSString stringWithFormat:&#64;"%d/%d", currentPage&#43;1, totalPages];
105 }
1 // 上一页
2 - (IBAction)actionPrevious:(id)sender {
3 if (currentPage > 0) {
4 currentPage--;
5
6 NSRange range &#61; rangeOfPages[currentPage];
7 NSString *pageText &#61; [text substringWithRange:range];
8
9 textLabel.text &#61; pageText;
10
11 //
12 pageInfoLabel.text &#61; [NSString stringWithFormat:&#64;"%d/%d", currentPage&#43;1, totalPages];
13 }
14 }
1 // 下一页
2 - (IBAction)actionNext:(id)sender {
3 if (currentPage
4 currentPage&#43;&#43;;
5
6 NSRange range &#61; rangeOfPages[currentPage];
7 NSString *pageText &#61; [text substringWithRange:range];
8
9 textLabel.text &#61; pageText;
10
11 //
12 pageInfoLabel.text &#61; [NSString stringWithFormat:&#64;"%d/%d", currentPage&#43;1, totalPages];
13 }
14 }