iOS 控件定制iOS Developer程序员

iOS实现一个开源的IMKit

2016-08-22  本文已影响1286人  151ba12c22e5

用过融云IMKit的人想必都会吐槽一番,因为是闭源的项目,想要进行�复杂的定制着实要费一番功夫。虽然可以用IMLib自己实现UI,真的做起来也不免费些心思。现在Github上有很多�例如UUChat等优秀的IM框架,但是�也并不能很快的实现与IML�ib的对接。基于以上原因,这个框架便孕育而生。啰嗦了这么多,接下来的几篇文章将详细的讲一些这个项目用到的一些东西。

首先,这个项目的布局完全基于Masonry,也就是对�AutoLayout的一层封装,把之前又臭又长的NSLayoutConstraint封装成链式语法,造福了我这种Storyboard黑粉。ok,接下来讲一下项目里用到了哪些Masonry的黑魔法

气泡

整个聊天的UI,�主要就是一个tableview,那��么问题来了,怎么能让�cell里的气泡可长可短可大可小呢,这里先普及个概念,intrinsicContentSize�这个属性存在于UIButton,UILabel,UITextView,UIImage�View等一切有‘内容’的控件,�比如说上图气泡中的UILabel,在绘制文字的时候会在内部调用CTFramesetterSuggestFrameSizeWithConstraints计算出一个size,这个size正是内容的size,这也就是调用sizeToFit后会‘自动’给Label一个size的原因。知道了这个神奇的属性,接下来我们就需要用Label的size去�‘撑开’这个气泡

//添加气泡与cell的约束

[self.bubbleImageViewmas_makeConstraints:^(MASConstraintMaker*make) {

make.top.equalTo(self.avatarImageView.mas_top).offset(0);

make.bottom.equalTo(self.contentView.mas_bottom).offset(-8);

SMAS(make.left.equalTo(self.avatarImageView.mas_right).offset(7));

SMAS(make.right.lessThanOrEqualTo(self.contentView.mas_right).offset(-78));

}];

//添加气泡内文字与气泡的约束

[self.messageLabel mas_makeConstraints:^(MASConstraintMaker*make) {

make.edges.mas_offset(UIEdgeInsetsMake(10,15,10,15));

}];

关键代码,就是上面这段了,这里我们借用Reveal来看一下约束关系,撇开SMAS是什么鬼先不说,可能比较难理解的就是lessThanOrEqualTo这句了,但是这句就是能让气泡伸缩自如的关键之一。

即:label的左边界的X坐标值“小于等于”contentView的左边界的X坐标值。

也就是说lable.width最大可以是contentView.�width - 78,最小可以是0。不知道这解释,大家能不能理解,但是不妨多用equal,�greaterThanOrEqualTo,lessThanOrEqualTo实验下。

好了接下来讲一下SMAS是啥,看起来有点玄乎但是真相只有一个

#define SMAS(x) [self.constraints addObject:x]

没错,这就是一个宏而已,它的作用就是把约束保存在self.constraints这个数组中,那为啥要这么做呢,

�由于我们一个cell要实现两种气泡方向(我方发出/对方发出),还是看�上上段代码,这里我们把气泡的左右约束都保存到了数组中,接下来我们只需要在合适的地方将约束卸载掉,然后再make新的约束即可,当然这里也可以用mas_remakeConstraints来实现,当然缺点就是每次都要把所有约束都重写一遍。这里可能会对这种用法有更详细的解释

for(MASConstraint*constraint in self.constraints) {

[constraint uninstall];

}

重新为气泡添加新的左右约束

[self.bubbleImageView mas_makeConstraints:^(MASConstraintMaker*make) {

if(direction == MessageDirection_RECEIVE) {

SMAS(make.left.equalTo(self.avatarImageView.mas_right).offset(7));

SMAS(make.right.lessThanOrEqualTo(self.contentView.mas_right).offset(-78));

}else{

SMAS(make.right.equalTo(self.avatarImageView.mas_left).offset(-7));

SMAS(make.left.greaterThanOrEqualTo(self.contentView.mas_left).offset(78));

}

}];

  另外在这里普及一下为什么不能用mas_updateConstraints,mas_updateConstraints只能用于相同约束的情况下。

例如:

[self.retryBtn mas_makeConstraints:^(MASConstraintMaker*make) {

make.centerY.equalTo(self.statusView.mas_centerY).offset(0);

make.centerX.equalTo(self.statusView.mas_centerX).offset(0);

}];

[self.retryBtnmas_updateConstraints:^(MASConstraintMaker*make) {

make.centerX.equalTo(self.statusView.mas_centerX).offset(100);

}];

简而言之,update只适用于更改offset之后的数值。�

  最后,�既然是tableview,那当然就少不了老生常谈的计算rowheight的问题。�在这里给大家推荐一个�自适应cell高度的神器FDTemplateLayoutCell,�只要是cell里的纵向约束添加完整,便可以自动计算并�缓存cell高度。当然在ios8+也可以使用tableview新增的estimatedHeightForRowAtIndexPath来估算高度。在这个项目里我选择了前者。具体的用法可以参考我之前写的一个demo:FDWithMasonryDemo。这样一来气泡的上下伸缩就so easy了~

�这个项目�写了有几天了,接下来还会不断的完善,如果有小伙伴想加入的话可以私信我,或者fork这个项目。��

�最后附上Github:TLMessage

未完待续。。

上一篇下一篇

猜你喜欢

热点阅读