提問
1.自適應(yīng)cell高度,你會幾種?
2.約束,局部,適配 你會幾種?
- textview 是否會自定義高度。
這里textview實現(xiàn)的cell IOS 8 自適應(yīng)方法。 使用Masonry布局,使用runtimer給分類,進行動態(tài)添加方法,和交換方法。
整體的邏輯,textview ,首先自適應(yīng)高度,然后把高度和輸入的字符用block 的方式,傳到cell里,viewController通過代理事件,進行更新自適應(yīng)高度!
我試過很多方法,和各種回調(diào),還是不能達(dá)到預(yù)期的效果,就是解決不了cell跟著更新?。ㄟ@個很皮?。。?br>
難點,在于textview,和cell的結(jié)合,textview怎么樣才能實時的自適應(yīng)來適應(yīng)高度,這里肯定想要了用KVO KVC 觀察著啊,但是這些我都無法很巧妙和結(jié)合起來使用,也沒有達(dá)到預(yù)期的效果bug一大推! 然后去github上找了找,發(fā)現(xiàn)盡然用到runtimer! 于是就下了狠心一定要把這個東西給弄懂!
下面我一步一步的解讀下來
首先我們看,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)建了一個cell,設(shè)置了一個代理。給控件賦值了!
LSTextViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
cell.delegate = self;
cell.textView.text = self.dataSource[indexPath.row];
cell.label.text = self.titls[indexPath.row];
//通過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;
}
//將對象anObject插入數(shù)組的index元素
[self.dataSource replaceObjectAtIndex:indexPath.row withObject:text];
}
//更新
-(void)textViewCell:(LSTextViewCell)cell textHeightChange:(NSString)text{
[self.tableView beginUpdates];
[self.tableView endUpdates];
}
//在上面,就實例化出來了cell,賦值,遵從了一個delegate;代理分別是一個更新和取值的方法。
//在來看cell這個控件做了啥
控件的添加我就不說了!
-(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:)]) {
//代理傳值,這個是text改變!
//這個是更新tableview
[self.delegate textViewCell:self textChange:self.textView.text];
}
}
這個方法就是限制text的,給viewcontroller的text ,做了一個限制字符的輸入!
[self.textView setHeightDidChangeBlock:^(NSString *text, CGFloat height) {
[weakSelf.textView mas_updateConstraints:^(MASConstraintMaker *make) {
make.height.mas_greaterThanOrEqualTo(@(height)).priority(888);
}];
//高度改變,這個就把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];
}];
上面就算完了,邏輯都沒在里面寫的,重頭戲來了。。
自定義的textview,主要做了寫什么呢?
首先設(shè)置本身的屬性讓他不能夠滾動自適應(yīng)起來來。
監(jiān)聽Text屬性值的變化
sizeThatFits 這個方法返回實際的尺寸,ceil 在向上取整
在判斷是否 高度變化,給他傳出去給cell去修改約束
可以說到這里就已經(jīng)結(jié)束了一切的代碼了。你的cell 和textview都已經(jīng)可以自適應(yīng)了。
但是他還是不完美的,他不能設(shè)置占位符,沒有提示符。
這樣的話,就只有使用runtime來設(shè)置了。。
其實說白了,就給他動態(tài)添加屬性就行了,不過這個你不能亂添加你要看下需要的屬性是不是能夠跟你拿來做臨時的UI 能夠很好的結(jié)合,這樣的話,你寫起來就方便!
提示符,提示符的顏色,和花字體,全部都用一個lable來代替! 因為labe全部都有相同的屬性!這樣就很方便了。。我直接set方法在我內(nèi)部修改就OK了。
然后你得把lable的frame算出來,還有是否顯示。(這里方法有很多種)
作者用的確實,比較難的! 使用觀察者 不知道為什么作者那么喜歡觀察者模式?。▊€人認(rèn)為觀察者是比較麻煩的,還有很容易出問題),作者這里就會出問題,因為你要考慮到他的銷毀!
這里作者有來搞runtime!
他把方法dealloc方法交互,去銷毀觀察者!和通知!