实现微信朋友圈动态列表

前言

项目中需要实现类似朋友圈动态的列表,需要用到图文混排,正好可以使用ibireme大神的开源控件YYText实现这种效果,在这里记录一下使用过程中遇到的问题,参考文章iOS 保持界面流畅的技巧

朋友圈列表最终效果.gif

布局

列表中的主要布局如下图所示,预先将每个cell的高度计算出来,并且将高度缓存下来,不重复计算高度。ibireme实现的微博列表Demo写的已经很清晰了,这里主要写下自己在使用时,遇到的一些问题。

布局.png

1.TableView刷新时出现闪动问题

TableView在刷新的时候,YYLabel会出现闪动,解决方法是将异步绘制关闭displaysAsynchronously = NO;,参考https://github.com/ibireme/YYKit/issues/64

2.动态Label默认最多显示六行

计算文本的行数,YYTextContainer有最大行数maximumNumberOfRows属性,根据这个属性可以设置文本最大行数。

    YYTextContainer *container = [YYTextContainer new];
    container.size = CGSizeMake(kWBCellContentWidth, HUGE);
    container.linePositionModifier = modifier;
    
    //计算文本的行数,判断显示6行,还是显示完全
    YYTextLayout *tmpTextLayout = [YYTextLayout layoutWithContainer:container text:text];
    NSUInteger rowCount = tmpTextLayout.rowCount;

当行数大于6行时,显示展开按钮,点击展开按钮显示全部文本,显示收起按钮,将当前最大行数设置为6行。

     //判断是否隐藏展开按钮
     if (rowCount > 6) {
        _isShowExpendButton = YES;
         //判断展开或者收起状态
      if (_isExpend == NO) {
            container.maximumNumberOfRows = 6;
             _expendButtonTitle = @"全文";
        }else{
             _expendButtonTitle = @"收起";
         }
      }else{
          _isShowExpendButton = NO;
      }
3.匹配字符串

将动态字符串中的[呵呵] ,[可爱]等字符串替换为表情图片。将电话号码,网址等进行高亮显示,并且为其设置userInfo,用于后面响应用户点击事件。将这些方法放在了NSString+Emotion类中,方便调用。关于正则表达式怎么匹配,可以查看这篇文章从零开始学习正则表达式

    // 匹配 [表情]
    NSArray<NSTextCheckingResult *> *emoticonResults = [[EmoticonHelper regexEmoticon] matchesInString:text.string options:kNilOptions range:text.yy_rangeOfAll];
    NSUInteger emoClipLength = 0;
    for (NSTextCheckingResult *emo in emoticonResults) {
        if (emo.range.location == NSNotFound && emo.range.length <= 1) continue;
        NSRange range = emo.range;
        range.location -= emoClipLength;
        if ([text yy_attribute:YYTextHighlightAttributeName atIndex:range.location]) continue;
        if ([text yy_attribute:YYTextAttachmentAttributeName atIndex:range.location]) continue;
        NSString *emoString = [text.string substringWithRange:range];
        NSString *imagePath = [EmoticonHelper emoticonDic][emoString];
        UIImage *image = [EmoticonHelper imageWithPath:imagePath];
        if (!image) continue;
        
        NSAttributedString *emoText = [NSAttributedString yy_attachmentStringWithEmojiImage:image fontSize:font.pointSize];
        [text replaceCharactersInRange:range withAttributedString:emoText];

        //emoText的length都是1
        emoClipLength += range.length - 1;
    }

响应手机号和网址的点击事件,获取高亮状态字符串的userInfo,然后进行相应的操作。

/// 点击了 Label 的链接
- (void)cell:(TwitterCell *)cell didClickInLabel:(YYLabel *)label textRange:(NSRange)textRange{
    NSAttributedString *text = label.textLayout.text;
    if (textRange.location >= text.length) return;
    YYTextHighlight *highlight = [text yy_attribute:YYTextHighlightAttributeName atIndex:textRange.location];
    NSDictionary *info = highlight.userInfo;
    if (info.count == 0) return;
    if (info[kWBLinkURLName]) {
        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:info[kWBLinkURLName]]];
        
    }else if (info[KWBLinkPhone]){
        NSMutableString *str2=[[NSMutableString alloc] initWithFormat:@"tel:%@",info[KWBLinkPhone]];
        UIWebView * callWebview = [[UIWebView alloc] init];
        [callWebview loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:str2]]];
        [self.view addSubview:callWebview];
    }
}
4.评论列表点击可以拷贝

评论视图是用UITableView实现的,可以使用TableView的系统方法,实现长按cell,弹出copy菜单,然后进行复制[UIPasteboard generalPasteboard].string = model.comment

- (BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath {
    return YES;
}

- (BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender {
    if (action == @selector(copy:)) {
        return YES;
    }
    return NO;
}

- (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender {
    if (action == @selector(copy:)) {
        TweetCommentModel *model;
        if (self.commentArray.count > 0) {
            model  = self.commentArray[indexPath.row];
        }
        [UIPasteboard generalPasteboard].string = model.comment;
    }
}

YYKit中微博Demo的表情键盘,自己也照着作者的代码敲了一篇,学到了很多。

表情键盘.gif

最后代码可以到动态列表表情键盘下载。