前面我已經(jīng)寫了4篇關(guān)于AutoLayout進階的文章,但是講的點都很散性宏。我準備用這篇文章將前面所講的知識串起來,運用到實際书斜,然后將AutoLayout系列做一個總結(jié)酵使。我們先來看看效果:
這是一個類似朋友圈的社交界面口渔,也是我以前做過的項目的一部分,全部由基本的UITableView實現(xiàn)痪欲。為了避免暴露服務器接口,我去除了與服務器交互的部分以及一大部分業(yè)務邏輯咧党,只剩下寫死的數(shù)據(jù)和界面布局陨亡。當時為了完成項目任務,做這個界面大概花了5天的時間(demo外還有很多功能)蛙埂,為了實現(xiàn)功能和優(yōu)化卡頓也費了不少心思遮糖,也幫助我對約束布局有了更深認識欲账。話不多說,我們來看看怎么實現(xiàn)惩嘉。
大圖小圖布局切換
看gif圖我們可以看見踢故,圖片的布局有多樣,準確的說最多顯示9種耸峭,根據(jù)圖片數(shù)量不同淋纲,布局也不同。網(wǎng)上有些人采用幾個不同的cell來顯示不同種類的圖片玷或,但我這為了節(jié)省代碼量片任,我采用AutoLayout布局对供,并通過修改約束來實現(xiàn)不同個數(shù)的圖片顯示。
這個是我上半部分cell的布局鹅髓。中間的大方框就是我放圖片的位置京景,我在這單獨擺放了一個UIView确徙,方便后續(xù)的界面布局。這個方框的寬度不會改變芜赌,唯一會變的應該是高度(虛線顯示的約束),因此我將這個高度約束設置成變量伴逸,在cell的.m
文件中,通過改變變量的值來動態(tài)調(diào)整UiView的高度洲愤,再把imageView填上去顷锰。
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *bigPictureViewHeight;
- (void)createPicTureView:(NSArray *)picArray{
[self.pictureView removeAllSubviews];
[pictureArray removeAllObjects];
picWidth = 0;
picHeight = 0;
int rowPicCount = 1;
float bigPicViewWidth = screenWidth - space *2;
if ([picArray count]==0) {
self.bigPictureViewHeight.constant = 0;
return ;
}
else if ([picArray count] == 1) {
picWidth = (screenWidth - space *2) ;
picHeight = picWidth;
self.bigPictureViewHeight.constant = bigPicViewWidth;
rowPicCount =1;
}
else if ([picArray count] <=2){
picWidth = (screenWidth - space *2 - 5)/2;
picHeight = picWidth;
self.bigPictureViewHeight.constant = picHeight;
rowPicCount =2;
}
else if ([picArray count] <=4){
picWidth = (screenWidth - space *2 - 5)/2;
picHeight = picWidth;
self.bigPictureViewHeight.constant = bigPicViewWidth;
rowPicCount = 2;
}
else if ([picArray count] <=6){
picWidth = (screenWidth - space *2 - 10)/3;
picHeight = picWidth;
self.bigPictureViewHeight.constant = picHeight *2 +5;
rowPicCount = 3;
}
else if ([picArray count] <= 9){
picWidth = (screenWidth - space *2 - 10)/3;
picHeight = picWidth;
self.bigPictureViewHeight.constant = bigPicViewWidth;
rowPicCount = 3;
}
float x=0;
float y =0;
for (int i =0 ; i<[picArray count]; i++) {
UIImageView * imageView = [[UIImageView alloc] initWithFrame:CGRectMake(x, y , picWidth, picHeight)];
imageView.backgroundColor = [UIColor whiteColor];
imageView.clipsToBounds = YES;
imageView.contentMode =UIViewContentModeScaleAspectFill;
[imageView sd_getImageWithId:picArray[i] andSize:picWidth square:NO placeholderImage:[UIImage imageNamed:@"place_holder_album"]];
[self.pictureView addSubview:imageView];
[pictureArray addObject:imageView];
//白色圓角邊框
UIImageView *cornerImageView = [[UIImageView alloc] initWithFrame:CGRectMake(x, y , picWidth, picHeight)];
cornerImageView.image = [UIImage stretchableImageNamed:@"white_corner"];
[self.pictureView addSubview:cornerImageView];
UIButton * button = [[UIButton alloc]initWithFrame:imageView.frame];
button.tag = i;
//點擊圖片展示
[button addTarget:self action:@selector(showPic:) forControlEvents:UIControlEventTouchUpInside];
[self.pictureView addSubview:button];
if ((i+1)%rowPicCount == 0) {
x= 0;
y = y + 5 + picHeight;
}
else {
x= x+picWidth +5;
}
}
}
這里其實有一點不足之處躺率,如果每次顯示cell都將控件remove再add一遍万矾,其實是很耗性能的良狈,如果有什么好的建議歡迎再評論區(qū)分享。
文字點擊事件TTTAttributedLabel
文字點擊事件獲取一直都是這類界面的難點遇西。我們都知道NSMutableAttributedString
可以改變字體顏色严嗜,大小等,但是不支持響應事件茄蚯。如果專門為了這個功能去封裝UIView
的touch
事件又太過麻煩。因此壮不,我選擇上網(wǎng)查找第三方控件皱碘,很幸運,TTTAttributedLabel
剛好能滿足我的需求健蕊。
- 導入方法采用pod
pod 'TTTAttributedLabel', '~> 1.13.4'
- github地址:https://github.com/TTTAttributedLabel/TTTAttributedLabel
TTTAttributedLabel的使用很簡單如失,首先設置addLinkToAddress:withRange:
方法褪贵,將響應的參數(shù)和范圍傳進去,然后設置delegate
世舰。在代理的attributedLabel:didSelectLinkWithAddress:
會返回回調(diào)槽卫,在里面處理點擊事件就可以了。TTTAttributedLabel還能像NSMutableAttributedString
那樣震蒋,通過setText:afterInheritingLabelAttributesAndConfiguringWithBlock:
方法設置文字顏色躲庄,點擊顏色等噪窘。關(guān)鍵代碼如下:
TTTAttributedLabel * textLabel = [[TTTAttributedLabel alloc] initWithFrame:CGRectMake(0, 0, 20, 0)];
textLabel.extendsLinkTouchArea = NO;//網(wǎng)上說設置這個可以減少點擊面積,從而使滑動更流暢
textLabel.font = FontRealityNormal;
NSString * userName1 = dataModel.username;
NSString * userName2 = dataModel.targetusername;
NSString * text = dataModel.text;
NSRange firstRange = NSMakeRange(0, userName1.length);
NSRange secondRange;
NSRange thirdRange;
NSString * result = [NSString stringWithFormat:@"%@",userName1];
if (userName2.length > 0) {
result = [NSString stringWithFormat:@"%@ 回復 %@",result,userName2];
secondRange = NSMakeRange(userName1.length+4, userName2.length);
}
else {
secondRange = NSMakeRange(userName1.length+4, 0);
}
result = [NSString stringWithFormat:@"%@ :%@",result,text];
thirdRange = NSMakeRange(0, result.length);
textLabel.lineSpacing = 5;
textLabel.preferredMaxLayoutWidth = screenWidth - 68 -30 -6-6-10;
if (self.type == TalkTypeNomal) {
textLabel.numberOfLines = 5;
}
else {
textLabel.numberOfLines = 0;
}
textLabel.linkAttributes = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:NO] forKey:(NSString *)kCTUnderlineStyleAttributeName];
[textLabel setText:result afterInheritingLabelAttributesAndConfiguringWithBlock:^NSMutableAttributedString *(NSMutableAttributedString *mutableAttributedString) {
UIFont *boldSystemFont = [UIFont systemFontOfSize:13];
CTFontRef font = CTFontCreateWithName((__bridge CFStringRef)boldSystemFont.fontName, boldSystemFont.pointSize, NULL);
if (font) {
//設置可點擊文本的大小
[mutableAttributedString addAttribute:(NSString *)kCTFontAttributeName value:(__bridge id)font range:firstRange];
[mutableAttributedString addAttribute:(NSString *)kCTFontAttributeName value:(__bridge id)font range:secondRange];
//設置可點擊文本的顏色
[mutableAttributedString addAttribute:(NSString*)kCTForegroundColorAttributeName value:(id)[[UIColor colorWithRed:62/255.0 green:81/255.0 blue:105/255.0 alpha:1] CGColor] range:firstRange];
[mutableAttributedString addAttribute:(NSString*)kCTForegroundColorAttributeName value:(id)[[UIColor colorWithRed:62/255.0 green:81/255.0 blue:105/255.0 alpha:1] CGColor] range:secondRange];
CFRelease(font);
}
return mutableAttributedString;
}];
textLabel.delegate = self;
[textLabel addLinkToAddress:@{@"kind":@"comment",@"object":dataModel} withRange:thirdRange];
[textLabel addLinkToAddress:@{@"kind":@"user",@"object":dataModel.userid} withRange:firstRange];
[textLabel addLinkToAddress:@{@"kind":@"user",@"object":dataModel.targetuserid} withRange:secondRange];
[self.commentView addSubview:textLabel];
///添加長按事件
UILongPressGestureRecognizer * longPressGestureRecognizer =[[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(longPressGesture:)];
[textLabel addGestureRecognizer:longPressGestureRecognizer];
[textLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.commentView).offset(3);
make.left.equalTo(avatar.mas_right).offset(5);
make.right.equalTo(self.commentView).offset(-10);
make.bottom.equalTo(self.commentView).offset(-3);
}];
將評論添加到view上并布局我采用Masonry
設置約束浩习,代碼如上最后一段。參考:Autolayout進階之代碼編寫約束(一)
自動計算cell高度
朋友圈類型的界面籍嘹,自動計算高度是少不了的弯院。這里我采用的是自己的一套框架,用法比較簡單颂碘,而且我以前也介紹過椅挣,這里就不再累述。參考:AutoLayout進階之可變cell高度
主要代碼:
- (CGFloat)getHeightWidthInfo:(id)info{
[self setInfo:info];
[self layoutSubviews];
[self setNeedsUpdateConstraints];
[self updateConstraintsIfNeeded];
[self setNeedsLayout];
[self layoutIfNeeded];
CGFloat height = [self.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height ;
return height;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
if((self.type == TalkTypeNomal || self.type == TalkTopic) && indexPath.row == 6){
return 50;
}
//先從緩存中查看數(shù)據(jù),如果有數(shù)據(jù)就直接返回量九,如果沒有再進行計算
float height = [tableViewHeightCache getHeightWithNSIndexPath:indexPath].floatValue;
if (height != 0) {
return height;
}
if (indexPath.row == 0) {
float height;
MCTalkMainViewCell * cell = [tableView MCTalkMainViewCell];
height = [cell getHeightWidthInfo:dataArray[indexPath.section]] ;
[tableViewHeightCache setHeightWithNSIndexPatch:indexPath andValue:@(height)];
return height;
}
else {
float height;
MCTalkCommentCell * cell = [tableView MCTalkCommentCell];
cell.type = self.type;
PZHListItemModel * listModel = dataArray[indexPath.section];
TalkCommentModel * commentModel = listModel.commentPoList[indexPath.row -1];
height = [(MCTalkCommentCell *)cell getHeightWidthInfo:@{@"listModel":listModel,@"commentModel":commentModel}];
[tableViewHeightCache setHeightWithNSIndexPatch:indexPath andValue:@(height)];
return height;
}
return 0.1;
}
總結(jié)
類似朋友圈最大的問題就是滑動卡頓荠列。如果仔細觀察,微信的朋友圈也是有略微卡頓的费就。因此要盡可能優(yōu)化代碼川队。我曾經(jīng)將評論都放在一個cell,結(jié)果評論一多就根本劃不動眠蚂,原因是每條評論都設置了多個autoLayout約束对雪,在一個cell中的話瑟捣,計算高度十分復雜、緩慢捐祠。后來我將評論分成多個cell桑李,這樣就減少了計算量窿给。一定要記得要緩存高度率拒,這樣能極大的優(yōu)化加載速度。還有富文本label的使用盡量少角撞,因為富文本本身就很消耗性能勃痴。
Show Me The Code!
github: https://github.com/NBaby/PZHCircleOfFriendsDemo
我是翻滾的牛寶寶沛申,歡迎大家評論交流~