1、根据文本大小动态调整UILabel大小:
iOS 7之前有一系列的方法可以计算NSString绘制后的具体大小,然后以此预估控件的大小,从而可以根据文本长短动态调整控件大小。一共5个方法,都是NSString的方法,都以sizeWithFont开头,通过传入字体格式、换行模式、预设大小等来计算绘制后的大小。iOS7开始禁用了这些方法,使用
CGSize size = [str boundingRectWithSize:CGSizeMake(200, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin |NSStringDrawingTruncatesLastVisibleLine attributes:attriDic context:nil].size;
来代替。这里是使用了一个方法来整个了之前的所有方法,但是提供的参数是类似的,不过这里的attributes:attriDic部分使用的是和NSAttributedString同样的属性字典,即NSAttributedString有很多属性可以调节,而这里使用同样的属性调节key,基本可以满足所有的文本属性设置了。使用方法是使用这些特定的key构建一个字典,如:
NSDictionary * attriDic = @{NSFontAttributeName : [UIFont systemFontOfSize:15],NSParagraphStyleAttributeName : style};
这里的NSFontAttributeName 是字体对应的key,NSParagraphStyleAttributeName 是NSMutableParagraphStyle 类对象对应的类,这个类使用来管理段落格式的,行距就是有它调节。
2、使用上述方法可以很好的做到预估字符串显示的大小,从而相应的更改承载这些字符串的控件大小,比如UILabel。但是这个东西碰到UITableViewCell就有个难点:比如cell上面要显示文本,但是这个文本是不确定的,会根据数据的变化而变化,那么可能这个文本的显示会是1行、两行或者3、4行更多,而显示这个文本的cell也需要跟着变换高度,因为不同的行数,高度不一样。貌似这里只要调节cell的大小就可以了,但是对于UITableView,调节cell的高度是需要通过委托方法来实现的,就是方法:
-(CGFloat )tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
一般使用tableView,显示的数据都是结构相同的,也一般保存在数组里面,所以这里有一个参数indexPath,通过这个多以对应的获取每一条数据,然后通过每个特定的数据来确定当前这个indexPath的cell的高度。所以这里需要根据数据,计算一遍cell的高度。然后在cell的构建的委托方法:
-(UITableViewCell* )tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
里面cell构建,cell上面显示文本的控件肯定也需要根据数据计算一遍,所以这里还要算一遍。
好像难点也没有什么,就是要通过计算字符串绘制后的大小设置cell的高度。
不过有两点问题:1、如果cell是自定义的类,那么我觉得可以把
-(CGFloat )tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
这里面需要计算cell高度的方法写在自定义的cell里面,这样的封装性比较好。因为cell的高度,虽然是根据传入的数据不断改变的,但是根本的还是cell本身的控件排版决定的,这件事不应该是viewcontroller的责任,而是cell的一个属性,所以把事情归结给cell会更好。比如你现在的tableview需要混入另一种cell,那么高度计算只需要调用另一个cell的同一个方法。
然后这里又不需要cell的对象本身的属性,因为这就是一个计算的过程,所以可以写成类方法,这样不用构建cell的实例就可以计算cell的高度,这样避免了不必要的内存消耗。
2、即使封装好了,不过这里还是有些浪费,因为高度计算其实做了两次。因为UITableView的cell的高度有专门的方法,这里需要计算。然后我们的cell的构建,肯定是要计算里面空间的大小。不知道是否有更好的方法我还没有发现,不过我的想法是,如果在
-(UITableViewCell* )tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
也就是cell的构建方法里面可以给cell设定大小,然后系统也会读取就好了,那么就只要计算一次就可以了。实际是直接设置cell的frame是没用了。