这是所有做电子书之类的程序都会遇到的一个问题. 前一阵搞一个项目, 花了3天时间搞这个小方法, 总是分页不够精确. 最后我发现了问题所在: 要用UILabel来显示文字, 而不是TextView!!
我发现盛大起点中文的电子书app还存在分页不准的问题, 李博 要努力噢 哈哈~~
大体思路就是,把字符串分段落, 用段落去填充页. 下面是这个小方法, 希望会对大家有帮助:
-(NSArray*)getPagesOfString:(NSString*)cache withFont:(UIFont*)font inRect:(CGRect)r{
//返回一个数组, 包含每一页的字符串开始点和长度(NSRange)
NSMutableArray *ranges=[NSMutableArray array];
//断行类型
UILineBreakMode lineBreakMode=UILineBreakModeCharacterWrap;
//显示字体的行高
CGFloat lineHeight=[@"Sample样本" sizeWithFont:font].height;
NSInteger maxLine=floor(r.size.height/lineHeight);
NSInteger totalLines=0;
NSLog(@”Max Line Per Page: %d (%.2f/%.2f)”,maxLine,r.size.height,lineHeight);
NSString*lastParaLeft=nil;
NSRange range=NSMakeRange(0, 0);
//把字符串按段落分开, 提高解析效率
NSArray *paragraphs=[cache componentsSeparatedByString:@"/n"];
for (int p=0;p< [paragraphs count];p++) {
NSString*para;
if (lastParaLeft!=nil) {
//上一页完成后剩下的内容继续计算
para=lastParaLeft;
lastParaLeft=nil;
}else {
para=[paragraphs objectAtIndex:p];
if (p<[paragraphs count]-1)
para=[para stringByAppendingString:@"/n"]; //刚才分段去掉了一个换行,现在换给它
}
CGSize paraSize=[para sizeWithFont:font
constrainedToSize:r.size
lineBreakMode:lineBreakMode];
NSInteger paraLines=floor(paraSize.height/lineHeight);
if (totalLines+paraLines<maxLine) {
totalLines+=paraLines;
range.length+=[para length];
if (p==[paragraphs count]-1) {
//到了文章的结尾 这一页也算
[ranges addObject:[NSValue valueWithRange:range]];
//IMILog(@”===========Page Over=============”);
}
}else if (totalLines+paraLines==maxLine) {
//很幸运, 刚好一段结束,本页也结束, 有这个判断会提高一定的效率
range.length+=[para length];
[ranges addObject:[NSValue valueWithRange:range]];
range.location+=range.length;
range.length=0;
totalLines=0;
//IMILog(@”===========Page Over=============”);
}else{
//重头戏, 页结束时候本段文字还有剩余
NSInteger lineLeft=maxLine-totalLines;
CGSize tmpSize;
NSInteger i;
for (i=1; i<[para length]; i++) {
//逐字判断是否达到了本页最大容量
NSString *tmp=[para substringToIndex:i];
tmpSize=[tmp sizeWithFont:font
constrainedToSize:r.size
lineBreakMode:lineBreakMode];
int nowLine=floor(tmpSize.height/lineHeight);
if (lineLeft<nowLine) {
//超出容量,跳出, 字符要回退一个, 应为当前字符已经超出范围了
lastParaLeft=[para substringFromIndex:i-1];
break;
}
}
range.length+=i-1;
[ranges addObject:[NSValue valueWithRange:range]];
range.location+=range.length;
range.length=0;
totalLines=0;
p–;
//IMILog(@”===========Page Over=============”);
}
}
return [NSArray arrayWithArray:ranges];
}
分享到:
相关推荐
字符串分页,从网上下来后整理的。字符串分页,从网上下来后整理的。
可以解决字符串超长传递问题,一句话的描述可能帮助到你
* 超大字符串拼接,单个字符串4000、分隔符100,可拼出超4000的超长字符串 * 可自定义指定分隔符separator * 可自定义指定排序字段sequence,对于数字或日期类型的字段,先转为字符串,比如to_char(line, 'FM000'...
C代码实现超长整数字符串 相加,及相应执行程序
C#字符串删除指定字符串|C#字符串删除子字符串
java 字符串转16进制 16进制转字符串 将两个ASCII字符合成一个字节; java 字符串转16进制 16进制转字符串 将两个ASCII字符合成一个字节; java 字符串转16进制 16进制转字符串 将两个ASCII字符合成一个字节; java ...
主要介绍了ORACLE 超长字符串问题的解决办法,需要的朋友可以参考下
第一节、一道俩个字符串是否包含的问题 1.1、O(n*m)的轮询方法 1.2、O(mlogm)+O(nlogn)+O(m+n)的排序方法 1.3、O(n+m)的计数排序方法 第二节 2.1、O(n+m)的hashtable的方法 2.2、O(n+m)的数组存储方法 ...
GridView实现用“...”代替超长字符串
易语言字符串操作源码,字符串操作,字符串_取长度,字符串_取中间,字符串_取左边,字符串_取右边,字符串_替换,到宽字符,到多字节,取文本数据地址,取字节集数据地址,MultiByteToWideChar,WideCharToMultiByte
编写程序:从键盘上输入一个包含10个字符的字符串,把该字符串与程序中给定的字符串("bacdbcabca") //依次比较,统计两个字符串对应字符相等的数目。然后输出从键盘上输入的字符串, //并把两个字符串中对应字符不...
jvm如何处理长字符串?java的classs文件中,constant_utf8_info的长度是u2,也就是说,一个字符串最长是65535个字节,但是,在本机做测试,超过这个长度的字符串也是允许的,原因是什么?
给写了2个方法,一个是直接截取单个需要的字符串,比如字符串string a="ab123456",我只需要提取3,那么就是单独截取就可以了,从2开始到4结束就行。 第二个是把所有的符合条件的字符串都截取出来,提取出来,比如...
字符串比较问题 Description ?问题描述: 对于长度相同的2 个字符串A和B,其距离定义为相应位置字符距离之和。2 个非空格 字符的距离是它们的ASCII码之差的绝对值。空格与空格的距离为0;空格与其它字符的距 离...
最近需要的这个功能,就是文章分页的那个,页面没用控件接收,字符串没有分页符,所以我就研究了一下,终于是写出来了,也许不是最优的。如果谁有更好的,希望能告诉我。谢谢
纯C语言实现字符串拆分操作,把字符串拆分成字符串数组,然后再输出。 使用sstream方法,作为底层驱动操作实现非常方便。
indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置。如果要检索的字符串值没有出现,则该方法返回 -1。 方法二:match() var str = "123" var reg = RegExp(/3/); if(str.match(reg)){ //包含; } ...
求两个字符串的最长公共字符串 输出全部位置信息,并输出字符串,相同字符串先输出所有位置信息在输出字符串 测试平台:XP/VS 2008 CN
一个关于字符串匹配的算法,已经经过编译,希望对你有帮助
必须实现如下操作,字符串比较、求串的长度、判断串是否为空、将串置空、字符串赋值(包括两个字符串类复制,一个字符串赋值到CmyString对象)、求字符串中的一个字符或改变字符串中的一个字符(采用重载[]),...