上一篇寫(xiě)了cell的iOS8的新特性(Self Sizing Cells)可以自己適配cell高度,這里用AutoLayout的VFL純代碼添加布局約束來(lái)配合使用一下,以及我自己遇到的一些坑。。廢話不多說(shuō),先介紹一下什么是VFL。
VFL(Visual Format Language):可視化格式語(yǔ)言
VFL的語(yǔ)法介紹:
- “H”:表示這是個(gè)水平方向上的約束;
“V”:表示這是個(gè)垂直方向上的約束。 - "|" :表示所設(shè)置視圖的父視圖superview。
- "-" :表示間距。
- "@":表示優(yōu)先級(jí)
- "[xxview]" :這個(gè)括號(hào)里面放置你要設(shè)置的視圖。
例: *V:|-8-[Textlabel(30)]-8-| *
在垂直方向上,Textlabel距父視圖頂部距離為8,距父視圖底部距離為8,高度為30。
添加約束的方法:
+(NSArray *)constraintsWithVisualFormat:(NSString *)format options:(NSLayoutFormatOptions)opts metrics:(NSDictionary *)metrics views:(NSDictionary *)views;
- format: 是VFL字符串。
- opts:設(shè)置VFL語(yǔ)句中的視圖相互間的對(duì)齊方式,一般默認(rèn)傳0即可。
- metrics:字典。一般是把VFL字符串中涉及到的高度、寬帶等數(shù)據(jù)參數(shù)轉(zhuǎn)為字典存到metrics中。在format中,高度、寬度等數(shù)據(jù)參數(shù)就用metrics中的key代替,然后編譯器解析時(shí)會(huì)自動(dòng)替換metrics中的值 value。
- views: 字典。把format中所有相關(guān)的視圖控件放入這個(gè)字典。
VFL與iOS8新特性(Self Sizing Cells)自適應(yīng)高度配合
ViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
self.buttonArr = [NSArray arrayWithObjects:@"北京香格里拉飯店從去年開(kāi)始就邀請(qǐng)入住酒店的愛(ài)心明星們?cè)诰频甑募槲镄⌒芡砩虾炏滤麄兊拿?,加入?ài)心競(jìng)拍的隊(duì)伍中,截止到現(xiàn)在我們一共籌得愛(ài)心款項(xiàng)人民幣 24776 元。其中最高的一只明星簽名小熊拍價(jià)高達(dá)10000元人民幣。 在北京香格里拉飯店27歲生日的今天,我們?cè)诿襟w朋友們、啟喑實(shí)驗(yàn)學(xué)校老師和學(xué)生及客人們的見(jiàn)證、祝福和陪伴中一起度過(guò)了一個(gè)意義非凡的生日,愛(ài)心傳遞和善款交付儀式圓滿(mǎn)成功!今天的儀式只是我們這個(gè)慈善項(xiàng)目的一個(gè)開(kāi)始,會(huì)有越來(lái)越多的明星朋友加入到其中,也會(huì)有更多的簽名小熊參與競(jìng)拍。這是一場(chǎng)愛(ài)的接力賽,希望您和您的朋友都能關(guān)注北京香格里拉飯店的官方微信和微博,來(lái)參與到我們的競(jìng)拍活動(dòng)中來(lái)。愛(ài)心“童童”的起拍價(jià)為人民幣1000元,想要為孩子們奉獻(xiàn)一份力量,同時(shí)收藏自己偶像簽名的愛(ài)心人士可致電(8610)6841 2211 轉(zhuǎn) 6901,發(fā)郵件至chris.ma@shangri-la.com,微博私信“北京香格里拉飯店”或微信留言等多種方式聯(lián)系酒店參與競(jìng)拍。競(jìng)拍金額最高的愛(ài)心人士不僅能夠得到中意的明星簽字“童童”,還將被邀請(qǐng)到之后的活動(dòng)現(xiàn)場(chǎng),親自見(jiàn)",
nil];
self.MTableView.delegate = self;
self.MTableView.dataSource = self;
self.MTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
[self.MTableView registerNib:[UINib nibWithNibName:@"MTableViewCell" bundle:nil] forCellReuseIdentifier:@"MTableViewCell"];
//高度自動(dòng)適配(只適用于cell極少數(shù)量下使用)
self.MTableView.estimatedRowHeight = 20;
self.MTableView.rowHeight = UITableViewAutomaticDimension;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return self.buttonArr.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
MTableViewCell *(^block_textCell)()= ^MTableViewCell*() {
MTableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:@"MTableViewCell" forIndexPath:indexPath];
[cell cellLableGetText:self.buttonArr[indexPath.row]];
[cell layoutIfNeeded];
return cell;
};
return block_textCell();
}
cell.m
-(void)cellLableGetText:(NSString *)contentText{
UILabel* Textlabel =[[UILabel alloc] init];
Textlabel.text=contentText;
Textlabel.numberOfLines=0;
Textlabel.lineBreakMode = NSLineBreakByWordWrapping;
Textlabel.translatesAutoresizingMaskIntoConstraints=NO; //使用VFL布局約束要加這一句,不然會(huì)報(bào)錯(cuò)
[self.contentView addSubview:Textlabel];
//純代碼添加水平方向約束
NSArray *constraints1=[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[Textlabel]-|"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(Textlabel)];
//純代碼添加垂直方向約束
NSArray *constraints2=[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-8-[Textlabel]-8-|"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(Textlabel)];
/*format: 是VFL字符串。
opts:設(shè)置VFL語(yǔ)句中的視圖相互間的對(duì)齊方式,一般默認(rèn)傳0即可。
metrics:字典。一般是把VFL字符串中涉及到的高度、寬帶等數(shù)據(jù)參數(shù)轉(zhuǎn)為字典存到metrics中。在format中,高度、寬度等數(shù)據(jù)參數(shù)就用metrics中的key代替,然后編譯器解析時(shí)會(huì)自動(dòng)替換metrics中的值 value。
views: 字典。把format中所有相關(guān)的視圖控件放入這個(gè)字典。
*/
[self.contentView addConstraints:constraints1];
[self.contentView addConstraints:constraints2];
}
看看cell上方的是lable的控件,簡(jiǎn)單約束好后效果實(shí)現(xiàn)如下,達(dá)到了我想要的效果:

但是。。有個(gè)坑就是當(dāng)我不想使用lable的時(shí)候,換成了button:
-(void)cellButtonGetText:(NSString *)contentText{
UIButton *Textbutton = [[UIButton alloc] init];
Textbutton.backgroundColor = [UIColor clearColor];
[Textbutton setTitle:contentText forState:UIControlStateNormal];
[Textbutton setTitleColor:[UIColor brownColor] forState:UIControlStateNormal];
Textbutton.titleLabel.font = [UIFont systemFontOfSize:15];
Textbutton.titleLabel.numberOfLines = 0;
Textbutton.titleLabel.lineBreakMode = NSLineBreakByCharWrapping;
Textbutton.translatesAutoresizingMaskIntoConstraints = NO; //使用VFL布局約束要加這一句,不然會(huì)報(bào)錯(cuò)
[Textbutton sizeToFit];
[Textbutton layoutIfNeeded];
[self.contentView addSubview:Textbutton];
//純代碼添加水平方向約束
NSArray *constraintsH = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[Textbutton]-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(Textbutton)];
//純代碼添加垂直方向約束
NSArray *constraintsV = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-8-[Textbutton]-8-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(Textbutton)];
/*format: 是VFL字符串。
opts:設(shè)置VFL語(yǔ)句中的視圖相互間的對(duì)齊方式,一般默認(rèn)傳0即可。
metrics:字典。一般是把VFL字符串中涉及到的高度、寬帶等數(shù)據(jù)參數(shù)轉(zhuǎn)為字典存到metrics中。在format中,高度、寬度等數(shù)據(jù)參數(shù)就用metrics中的key代替,然后編譯器解析時(shí)會(huì)自動(dòng)替換metrics中的值 value。
views: 字典。把format中所有相關(guān)的視圖控件放入這個(gè)字典。
*/
[self.contentView addConstraints:constraintsH];
[self.contentView addConstraints:constraintsV];
[super layoutSubviews];
}
在運(yùn)行之后發(fā)現(xiàn):

咦。。這是什么情況,cell高度怎么木有適配起來(lái),哪里寫(xiě)錯(cuò)了嗎?在我查看一番發(fā)現(xiàn)原來(lái)是因?yàn)閎utton的文字是在它的titlelable上,titlelable高度是根據(jù)文字的高度適配了,但是button的高度沒(méi)有適配起來(lái),而cell的新特性自動(dòng)適配是根據(jù)button來(lái)適配的,所以會(huì)出現(xiàn)上面的效果,看看層級(jí)結(jié)構(gòu)如下:

看到上面的層級(jí)關(guān)系,我們大概可以想到就是要把button和他的titlelable也要給約束起來(lái),那么就要用到這個(gè)屬性:metrics?!癧Textlabel(30)]”在這里高度30是一個(gè)固定值,但如果這個(gè)值是變動(dòng)的呢?那么就需要metrics這個(gè)屬性傳入,更改方法如下:
-(void)cellButtonGetText:(NSString *)contentText{
UIButton *Textbutton = [[UIButton alloc] init];
Textbutton.backgroundColor = [UIColor clearColor];
[Textbutton setTitle:contentText forState:UIControlStateNormal];
[Textbutton setTitleColor:[UIColor brownColor] forState:UIControlStateNormal];
Textbutton.titleLabel.font = [UIFont systemFontOfSize:15];
Textbutton.titleLabel.numberOfLines = 0;
Textbutton.titleLabel.lineBreakMode = NSLineBreakByCharWrapping;
Textbutton.translatesAutoresizingMaskIntoConstraints = NO; //使用VFL布局約束要加這一句,不然會(huì)報(bào)錯(cuò)
[Textbutton sizeToFit];
[Textbutton layoutIfNeeded];
[self.contentView addSubview:Textbutton];
CGSize expectedSize = [Textbutton.titleLabel sizeThatFits:CGSizeMake([UIScreen mainScreen].bounds.size.width, 0)];
//算出文字適配寬度后的高度,傳入到約束里
NSDictionary *metrics = @{@"lableHeight": @(expectedSize.height)};
//純代碼添加水平方向約束
NSArray *constraintsH = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[Textbutton]-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(Textbutton)];
//純代碼添加垂直方向約束
NSArray *constraintsV = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-8-[Textbutton(lableHeight)]-8-|" options:0 metrics:metrics views:NSDictionaryOfVariableBindings(Textbutton)];
/*format: 是VFL字符串。
opts:設(shè)置VFL語(yǔ)句中的視圖相互間的對(duì)齊方式,一般默認(rèn)傳0即可。
metrics:字典。一般是把VFL字符串中涉及到的高度、寬帶等數(shù)據(jù)參數(shù)轉(zhuǎn)為字典存到metrics中。在format中,高度、寬度等數(shù)據(jù)參數(shù)就用metrics中的key代替,然后編譯器解析時(shí)會(huì)自動(dòng)替換metrics中的值 value。
views: 字典。把format中所有相關(guān)的視圖控件放入這個(gè)字典。
*/
[self.contentView addConstraints:constraintsH];
[self.contentView addConstraints:constraintsV];
[super layoutSubviews];
}
這回再運(yùn)行起來(lái),就可以了。