AutoLayout進階之朋友圈界面實現(xiàn)

前面我已經(jīng)寫了4篇關(guān)于AutoLayout進階的文章,但是講的點都很散性宏。我準備用這篇文章將前面所講的知識串起來,運用到實際书斜,然后將AutoLayout系列做一個總結(jié)酵使。我們先來看看效果:

2016-07-18 10_43_37.gif

這是一個類似朋友圈的社交界面口渔,也是我以前做過的項目的一部分,全部由基本的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布局

這個是我上半部分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可以改變字體顏色严嗜,大小等,但是不支持響應事件茄蚯。如果專門為了這個功能去封裝UIViewtouch事件又太過麻煩。因此壮不,我選擇上網(wǎng)查找第三方控件皱碘,很幸運,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

我是翻滾的牛寶寶沛申,歡迎大家評論交流~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市尖淘,隨后出現(xiàn)的幾起案子衫贬,更是在濱河造成了極大的恐慌,老刑警劉巖梆造,帶你破解...
    沈念sama閱讀 221,273評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件镇辉,死亡現(xiàn)場離奇詭異贴捡,居然都是意外死亡,警方通過查閱死者的電腦和手機屹逛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評論 3 398
  • 文/潘曉璐 我一進店門罕模,熙熙樓的掌柜王于貴愁眉苦臉地迎上來帘瞭,“玉大人,你說我怎么就攤上這事抛腕。” “怎么了摔敛?”我有些...
    開封第一講書人閱讀 167,709評論 0 360
  • 文/不壞的土叔 我叫張陵舷夺,是天一觀的道長售貌。 經(jīng)常有香客問我疫萤,道長,這世上最難降的妖魔是什么恒削? 我笑而不...
    開封第一講書人閱讀 59,520評論 1 296
  • 正文 為了忘掉前任钓丰,我火速辦了婚禮每币,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘梦鉴。我一直安慰自己揭保,他們只是感情好,可當我...
    茶點故事閱讀 68,515評論 6 397
  • 文/花漫 我一把揭開白布存筏。 她就那樣靜靜地躺著椭坚,像睡著了一般励负。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上巾表,一...
    開封第一講書人閱讀 52,158評論 1 308
  • 那天,我揣著相機與錄音考阱,去河邊找鬼鞠苟。 笑死,一個胖子當著我的面吹牛吃既,可吹牛的內(nèi)容都是我干的跨细。 我是一名探鬼主播,決...
    沈念sama閱讀 40,755評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼散休!你這毒婦竟也來了戚丸?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,660評論 0 276
  • 序言:老撾萬榮一對情侶失蹤猴鲫,失蹤者是張志新(化名)和其女友劉穎谣殊,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體宜狐,經(jīng)...
    沈念sama閱讀 46,203評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡抚恒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,287評論 3 340
  • 正文 我和宋清朗相戀三年俭驮,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片遗遵。...
    茶點故事閱讀 40,427評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡逸嘀,死狀恐怖崭倘,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情司光,我是刑警寧澤飘庄,帶...
    沈念sama閱讀 36,122評論 5 349
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響碾盐,放射性物質(zhì)發(fā)生泄漏揩局。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,801評論 3 333
  • 文/蒙蒙 一付枫、第九天 我趴在偏房一處隱蔽的房頂上張望驰怎。 院中可真熱鬧县忌,春花似錦、人聲如沸症杏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,272評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽精肃。三九已至,卻和暖如春溉仑,著一層夾襖步出監(jiān)牢的瞬間状植,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評論 1 272
  • 我被黑心中介騙來泰國打工振定, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留肉拓,地道東北人。 一個月前我還...
    沈念sama閱讀 48,808評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像驻售,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子毫痕,可洞房花燭夜當晚...
    茶點故事閱讀 45,440評論 2 359

推薦閱讀更多精彩內(nèi)容

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫消请、插件类腮、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,117評論 4 61
  • WebSocket-Swift Starscream的使用 WebSocket 是 HTML5 一種新的協(xié)議。它實...
    香橙柚子閱讀 23,898評論 8 183
  • wxg 我披著一層皮 身著一件光鮮艷麗的衣 我被人群高高抬起 認不清 自 己 迷茫 迷失 在 人群里 我存哲、想...
    silencesky閱讀 352評論 0 2
  • “哎呀,我的小寶貝哭了修肠『爻剑” “沒事媽,我沖好奶就過去∷腔” “那你不早說莽鸭,給我抱啊〕钥浚” “媽硫眨,你別抱巢块。他是故意大聲哭...
    chen姐chen閱讀 3,803評論 0 2
  • 你一定要清楚礁阁,自己想成為什么樣的人。三十歲時族奢,你想要的生活是什么樣的姥闭?你眼下要做的事,應該是有助于你實現(xiàn)你的長期目...
    充滿自信的我閱讀 144評論 0 0