提問(wèn)
1.自適應(yīng)cell高度,你會(huì)幾種馁菜?
2.約束茴扁,局部,適配 你會(huì)幾種汪疮?
- textview 是否會(huì)自定義高度峭火。
這里textview實(shí)現(xiàn)的cell IOS 8 自適應(yīng)方法。 使用Masonry布局铲咨,使用runtimer給分類躲胳,進(jìn)行動(dòng)態(tài)添加方法,和交換方法纤勒。
整體的邏輯坯苹,textview ,首先自適應(yīng)高度摇天,然后把高度和輸入的字符用block 的方式粹湃,傳到cell里,viewController通過(guò)代理事件泉坐,進(jìn)行更新自適應(yīng)高度为鳄!
我試過(guò)很多方法,和各種回調(diào)腕让,還是不能達(dá)到預(yù)期的效果孤钦,就是解決不了cell跟著更新F缯濉(這個(gè)很皮啊F巍)
難點(diǎn)静袖,在于textview,和cell的結(jié)合俊扭,textview怎么樣才能實(shí)時(shí)的自適應(yīng)來(lái)適應(yīng)高度队橙,這里肯定想要了用KVO KVC 觀察著啊,但是這些我都無(wú)法很巧妙和結(jié)合起來(lái)使用萨惑,也沒(méi)有達(dá)到預(yù)期的效果bug一大推捐康! 然后去github上找了找,發(fā)現(xiàn)盡然用到runtimer庸蔼! 于是就下了狠心一定要把這個(gè)東西給弄懂解总!
下面我一步一步的解讀下來(lái)
首先我們看,viewconeroller做了些啥朱嘴。倾鲫。粗合!
self.dataSource = [NSMutableArray array];
for (NSInteger i = 0; i < 6; i++) {
[self.dataSource addObject:@""];
}
if (!_titls) {
_titls = [NSMutableArray array];
for (int i = 1; i<100; i++) {
[_titls addObject:[NSString stringWithFormat:@"%d.",i]];
}
}
return _titls;
//創(chuàng)建了一個(gè)cell,設(shè)置了一個(gè)代理萍嬉。給控件賦值了!
LSTextViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
cell.delegate = self;
cell.textView.text = self.dataSource[indexPath.row];
cell.label.text = self.titls[indexPath.row];
//通過(guò)cell 的出indexpath隙疚,獲得cell的綁定indexpath
-(void)textViewCell:(LSTextViewCell *)cell textChange:(NSString )text{
NSIndexPath indexPath = [self.tableView indexPathForCell:cell];
[self.DatasoucerDit setValue:text forKey:[NSString stringWithFormat:@"%ld",indexPath.row]];
if (!indexPath) {
return;
}
//將對(duì)象anObject插入數(shù)組的index元素
[self.dataSource replaceObjectAtIndex:indexPath.row withObject:text];
}
//更新
-(void)textViewCell:(LSTextViewCell)cell textHeightChange:(NSString)text{
[self.tableView beginUpdates];
[self.tableView endUpdates];
}
//在上面壤追,就實(shí)例化出來(lái)了cell,賦值,遵從了一個(gè)delegate;代理分別是一個(gè)更新和取值的方法供屉。
//在來(lái)看cell這個(gè)控件做了啥
控件的添加我就不說(shuō)了行冰!
-(void)textViewDidChange:(UITextView *)textView{
if (self.textView.text.length > self.maxNumberWords && self.maxNumberWords > 0) {
self.textView.text = [self.textView.text substringToIndex:self.maxNumberWords-1];
}
//判斷delegate 是否為空,判斷是否響應(yīng)了 dalegate方法
if (self.delegate && [self.delegate respondsToSelector:@selector(textViewCell:textChange:)]) {
//代理傳值,這個(gè)是text改變伶丐!
//這個(gè)是更新tableview
[self.delegate textViewCell:self textChange:self.textView.text];
}
}
這個(gè)方法就是限制text的悼做,給viewcontroller的text ,做了一個(gè)限制字符的輸入!
[self.textView setHeightDidChangeBlock:^(NSString *text, CGFloat height) {
[weakSelf.textView mas_updateConstraints:^(MASConstraintMaker *make) {
make.height.mas_greaterThanOrEqualTo(@(height)).priority(888);
}];
//高度改變哗魂,這個(gè)就把text 傳出去了肛走。。
if (weakSelf.delegate && [weakSelf.delegate respondsToSelector:@selector(textViewCell:textHeightChange:)]) {
[weakSelf.delegate textViewCell:weakSelf textHeightChange:text];
}
[weakSelf layoutIfNeeded];
}];
//這里也只是改變約束录别,設(shè)置自適應(yīng)
[self.textView setTextDidSetBlock:^(NSString *text, CGFloat textHeight) {
[weakSelf.textView mas_updateConstraints:^(MASConstraintMaker *make) {
make.height.mas_greaterThanOrEqualTo(@(textHeight)).priority(888);
}];
[weakSelf layoutIfNeeded];
}];
上面就算完了朽色,邏輯都沒(méi)在里面寫的,重頭戲來(lái)了组题。葫男。
自定義的textview,主要做了寫什么呢崔列?
首先設(shè)置本身的屬性讓他不能夠滾動(dòng)自適應(yīng)起來(lái)來(lái)梢褐。
監(jiān)聽(tīng)Text屬性值的變化
sizeThatFits 這個(gè)方法返回實(shí)際的尺寸,ceil 在向上取整
在判斷是否 高度變化,給他傳出去給cell去修改約束
可以說(shuō)到這里就已經(jīng)結(jié)束了一切的代碼了盈咳。你的cell 和textview都已經(jīng)可以自適應(yīng)了趣效。
但是他還是不完美的,他不能設(shè)置占位符猪贪,沒(méi)有提示符跷敬。
這樣的話,就只有使用runtime來(lái)設(shè)置了热押。西傀。
其實(shí)說(shuō)白了,就給他動(dòng)態(tài)添加屬性就行了桶癣,不過(guò)這個(gè)你不能亂添加你要看下需要的屬性是不是能夠跟你拿來(lái)做臨時(shí)的UI 能夠很好的結(jié)合拥褂,這樣的話,你寫起來(lái)就方便牙寞!
提示符饺鹃,提示符的顏色,和花字體间雀,全部都用一個(gè)lable來(lái)代替悔详! 因?yàn)閘abe全部都有相同的屬性!這樣就很方便了惹挟。茄螃。我直接set方法在我內(nèi)部修改就OK了。
然后你得把lable的frame算出來(lái)连锯,還有是否顯示归苍。(這里方法有很多種)
作者用的確實(shí),比較難的运怖! 使用觀察者 不知道為什么作者那么喜歡觀察者模式F雌(個(gè)人認(rèn)為觀察者是比較麻煩的,還有很容易出問(wèn)題)摇展,作者這里就會(huì)出問(wèn)題吻氧,因?yàn)槟阋紤]到他的銷毀!
這里作者有來(lái)搞runtime吗购!
他把方法dealloc方法交互医男,去銷毀觀察者!和通知捻勉!