实现思路,跟着官方的红包cell来写。这里写得有点简陋,只是跟有一样需求的人提供下思路,可能写得不对,还望指教。
一、新建一个cell,父类是EaseBaseMessageCell
#import "EaseBaseMessageCell.h" /** * 名片cell */ @interface BSBusinessCardCell : EaseBaseMessageCell @end
二、参照红包cell改成自己项目里需要的
#import "BSBusinessCardCell.h" #import "UIImageView+EMWebCache.h" #import "EaseBubbleView+BusinessCard.h" static const CGFloat kCellHeight = 110.0f; @implementation BSBusinessCardCell #pragma mark - IModelCell - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier model:(id<IMessageModel>)model { self = [super initWithStyle:style reuseIdentifier:reuseIdentifier model:model]; if (self) { self.hasRead.hidden = YES; self.selectionStyle = UITableViewCellSelectionStyleNone; } return self; } - (BOOL)isCustomBubbleView:(id<IMessageModel>)model { return YES; } - (void)setCustomModel:(id<IMessageModel>)model { UIImage *image = model.image; if (!image) { [self.bubbleView.imageView sd_setImageWithURL:[NSURL URLWithString:model.fileURLPath] placeholderImage:[UIImage imageNamed:model.failImageName]]; } else { _bubbleView.imageView.image = image; } if (model.avatarURLPath) { [self.avatarView sd_setImageWithURL:[NSURL URLWithString:model.avatarURLPath] placeholderImage:model.avatarImage]; } else { self.avatarView.image = model.avatarImage; } } - (void)setCustomBubbleView:(id<IMessageModel>)model { [_bubbleView setupBusinessCardBubbleView]; _bubbleView.imageView.image = [UIImage imageNamed:@"imageDownloadFail"]; } - (void)updateCustomBubbleViewMargin:(UIEdgeInsets)bubbleMargin model:(id<IMessageModel>)model { [_bubbleView updateBusinessCardMargin:bubbleMargin]; _bubbleView.translatesAutoresizingMaskIntoConstraints = YES; CGFloat bubbleViewHeight = 84;// 气泡背景图高度 CGFloat nameLabelHeight = 15;// 昵称label的高度 if (model.isSender) { _bubbleView.frame = CGRectMake([UIScreen mainScreen].bounds.size.width - 273.5, nameLabelHeight, 213, bubbleViewHeight); // self.bubbleView.userHeaderImageView.frame = CGRectMake(13, 19, 26, 34); // self.bubbleView.userNameLabel.frame = CGRectMake(48, 19, 156, 15); // self.bubbleView.userPhoneLabel.frame = CGRectMake(48, 41, 49, 12); // self.bubbleView.line.frame = CGRectMake(13, 73, 200, 1); // self.bubbleView.tipsLabel.frame = CGRectMake(145, 73, 80, 20); }else{ _bubbleView.frame = CGRectMake(55, nameLabelHeight, 213, bubbleViewHeight); // self.bubbleView.userHeaderImageView.frame = CGRectMake(20, 19, 26, 34); // self.bubbleView.userNameLabel.frame = CGRectMake(55, 19, 156, 15); // self.bubbleView.userPhoneLabel.frame = CGRectMake(55, 41, 49, 12); // self.bubbleView.line.frame = CGRectMake(20, 73, 200, 1); // self.bubbleView.tipsLabel.frame = CGRectMake(152, 73, 80, 20); } // 这里强制调用内部私有方法 [_bubbleView _setupConstraintsXX]; } + (NSString *)cellIdentifierWithModel:(id<IMessageModel>)model { return NSStringFromClass([self class]); // return model.isSender ? @"__redPacketCellSendIdentifier__" : @"__redPacketCellReceiveIdentifier__"; } + (CGFloat)cellHeightWithModel:(id<IMessageModel>)model { return kCellHeight; } - (void)setModel:(id<IMessageModel>)model { [super setModel:model]; NSDictionary *dict = model.message.ext; // [model nickname]; // 谁发送的这个名片,谁向你推荐一张名片 /* { cardUserAvatarURLString = xs; cardUserName = xs; cardUserPhone = xs; } */ self.bubbleView.userNameLabel.text = dict[@"cardUserName"]; self.bubbleView.userPhoneLabel.text = dict[@"cardUserPhone"]; // NSString *str = [NSString stringWithFormat:@"%@",[dict valueForKey:RedpacketKeyRedpacketGreeting]]; // if (str.length > 10) { // str = [str substringToIndex:8]; // str = [str stringByAppendingString:@"..."]; // self.bubbleView.redpacketTitleLabel.text = str; // }else // { // self.bubbleView.redpacketTitleLabel.text = [dict valueForKey:RedpacketKeyRedpacketGreeting]; // } // // self.bubbleView.redpacketSubLabel.text = @"查看红包"; // self.bubbleView.redpacketNameLabel.text = [dict valueForKey:RedpacketKeyRedpacketOrgName]; // if ([[dict valueForKey:RedpacketKeyRedapcketToAnyone] isEqualToString:@"member"]) { // self.bubbleView.redpacketMemberLable.text = @"专属红包"; // }else // { // self.bubbleView.redpacketMemberLable.text = @""; // } _hasRead.hidden = YES;//名片消息不显示已读 // _nameLabel = nil;// 不显示姓名 } - (void)layoutSubviews { [super layoutSubviews]; NSString *imageName = self.model.isSender ? @"RedpacketCellResource.bundle/redpacket_sender_bg" : @"RedpacketCellResource.bundle/redpacket_receiver_bg"; UIImage *image = self.model.isSender ? [[UIImage imageNamed:imageName] stretchableImageWithLeftCapWidth:30 topCapHeight:35] : [[UIImage imageNamed:imageName] stretchableImageWithLeftCapWidth:20 topCapHeight:35]; // 等待接入名片的背景图片 // self.bubbleView.backgroundImageView.image = image; } @end
三、再针对EaseBubbleView写个分类,关联一些名片所需要的控件,当然也可以像环信默认支持的那几种
cell上直接把属性写在EaseBubbleView类里。
四,头文件里写上自己需要的属性,以及需要外界访问的方法
#import "EaseBubbleView.h" @interface EaseBubbleView (BusinessCard) /** * 用户的头像 */ @property (strong, nonatomic) UIImageView *userHeaderImageView; /** * 用户的昵称 */ @property (strong, nonatomic) UILabel *userNameLabel; /** * 用户的手机号 */ @property (strong, nonatomic) UILabel *userPhoneLabel; /** * 分隔线 */ @property (strong, nonatomic) UIView *line; /** * 提示字 “个人名片” */ @property (strong, nonatomic) UILabel *tipsLabel; - (void)setupBusinessCardBubbleView; - (void)updateBusinessCardMargin:(UIEdgeInsets)margin; - (void)_setupConstraintsXX; @end
五、.m文件示例写法
#import "EaseBubbleView+BusinessCard.h" #import <objc/runtime.h> static char _userHeaderImageView_; static char _userNameLabel_; static char _userPhoneLabel_; static char _line_; static char _tipsLabel_; @implementation EaseBubbleView (BusinessCard) #pragma mark - private - (void)_setupConstraintsXX { [self.marginConstraints removeAllObjects]; //userHeaderImageView NSLayoutConstraint *userHeaderImageViewTopConstraint = [NSLayoutConstraint constraintWithItem:self.userHeaderImageView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.backgroundImageView attribute:NSLayoutAttributeTop multiplier:1.0 constant:10]; NSLayoutConstraint *userHeaderImageViewLeadingConstraint = [NSLayoutConstraint constraintWithItem:self.userHeaderImageView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.backgroundImageView attribute:NSLayoutAttributeLeading multiplier:1.0 constant:10]; [self.marginConstraints addObject:userHeaderImageViewTopConstraint]; [self.marginConstraints addObject:userHeaderImageViewLeadingConstraint]; NSLayoutConstraint *userHeaderImageViewHeightConstraint = [NSLayoutConstraint constraintWithItem:self.userHeaderImageView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:0.0 constant:36]; NSLayoutConstraint *userHeaderImageViewWidthConstraint = [NSLayoutConstraint constraintWithItem:self.userHeaderImageView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:0.0 constant:36]; [self.userHeaderImageView addConstraint:userHeaderImageViewHeightConstraint]; [self.userHeaderImageView addConstraint:userHeaderImageViewWidthConstraint]; // userNameLabel NSLayoutConstraint *userNameLabelWithMarginTopConstraint = [NSLayoutConstraint constraintWithItem:self.userNameLabel attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.userHeaderImageView attribute:NSLayoutAttributeTop multiplier:1.0 constant:2]; NSLayoutConstraint *userNameLabelWithMarginRightConstraint = [NSLayoutConstraint constraintWithItem:self.userNameLabel attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.backgroundImageView attribute:NSLayoutAttributeTrailing multiplier:1.0 constant:-self.margin.right]; NSLayoutConstraint *userNameLabelWithMarginLeftConstraint = [NSLayoutConstraint constraintWithItem:self.userNameLabel attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.userHeaderImageView attribute:NSLayoutAttributeTrailing multiplier:1.0 constant:10]; [self.marginConstraints addObject:userNameLabelWithMarginRightConstraint]; [self.marginConstraints addObject:userNameLabelWithMarginTopConstraint]; [self.marginConstraints addObject:userNameLabelWithMarginLeftConstraint]; // userPhoneLabel NSLayoutConstraint *userPhoneLabelTopConstraint = [NSLayoutConstraint constraintWithItem:self.userPhoneLabel attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.userHeaderImageView attribute:NSLayoutAttributeBottom multiplier:1.0 constant:1]; NSLayoutConstraint *userPhoneLabelLeftConstraint = [NSLayoutConstraint constraintWithItem:self.userPhoneLabel attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.userNameLabel attribute:NSLayoutAttributeLeading multiplier:1.0 constant:0]; NSLayoutConstraint *userPhoneLabelRightConstraint = [NSLayoutConstraint constraintWithItem:self.userPhoneLabel attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.backgroundImageView attribute:NSLayoutAttributeTrailing multiplier:1.0 constant:-self.margin.right]; [self.marginConstraints addObject:userPhoneLabelTopConstraint]; [self.marginConstraints addObject:userPhoneLabelLeftConstraint]; [self.marginConstraints addObject:userPhoneLabelRightConstraint]; // line NSLayoutConstraint *lineTopConstraint = [NSLayoutConstraint constraintWithItem:self.line attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.userHeaderImageView attribute:NSLayoutAttributeBottom multiplier:1.0 constant:10]; NSLayoutConstraint *lineLeftConstraint = [NSLayoutConstraint constraintWithItem:self.line attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.userHeaderImageView attribute:NSLayoutAttributeLeading multiplier:1.0 constant:0]; NSLayoutConstraint *lineRightConstraint = [NSLayoutConstraint constraintWithItem:self.line attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.backgroundImageView attribute:NSLayoutAttributeTrailing multiplier:1.0 constant:-self.margin.right]; NSLayoutConstraint *lineHeightConstraint = [NSLayoutConstraint constraintWithItem:self.line attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:0.0 constant:1]; [self.marginConstraints addObject:lineTopConstraint]; [self.marginConstraints addObject:lineLeftConstraint]; [self.marginConstraints addObject:lineRightConstraint]; [self.marginConstraints addObject:lineHeightConstraint]; // tipsLabel NSLayoutConstraint *tipsLabelTopConstraint = [NSLayoutConstraint constraintWithItem:self.tipsLabel attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.line attribute:NSLayoutAttributeBottom multiplier:1.0 constant:4]; NSLayoutConstraint *tipsLabelLeftConstraint = [NSLayoutConstraint constraintWithItem:self.tipsLabel attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.line attribute:NSLayoutAttributeLeading multiplier:1.0 constant:0]; NSLayoutConstraint *tipsLabelRightConstraint = [NSLayoutConstraint constraintWithItem:self.tipsLabel attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.line attribute:NSLayoutAttributeTrailing multiplier:1.0 constant:0]; [self.marginConstraints addObject:tipsLabelTopConstraint]; [self.marginConstraints addObject:tipsLabelLeftConstraint]; [self.marginConstraints addObject:tipsLabelRightConstraint]; [self addConstraints:self.marginConstraints]; NSLayoutConstraint *backImageConstraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:0.0f constant:260]; [self.superview addConstraint:backImageConstraint]; /* UIView *backImageView = self.backgroundImageView; NSArray *backgroundConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[backImageView]-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(backImageView)]; NSArray *backgroundConstraints2 = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[backImageView(==200)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(backImageView)]; [self addConstraints:backgroundConstraints]; [self addConstraints:backgroundConstraints2]; */ } #pragma mark - public - (void)setupBusinessCardBubbleView { // 头像 self.userHeaderImageView = [UIImageView new]; [self.userHeaderImageView setImage:[UIImage imageNamed:@"聊天输入框名片按钮"]]; self.userHeaderImageView.translatesAutoresizingMaskIntoConstraints = NO; [self.backgroundImageView addSubview:self.userHeaderImageView]; // 昵称 self.userNameLabel = [UILabel new]; self.userNameLabel.font = [UIFont systemFontOfSize:15.0f]; self.userNameLabel.textColor = [UIColor lightGrayColor]; self.userNameLabel.translatesAutoresizingMaskIntoConstraints = NO; [self.backgroundImageView addSubview:self.userNameLabel]; // 手机号 self.userPhoneLabel = [UILabel new]; self.userPhoneLabel.font = [UIFont systemFontOfSize:13.0f]; self.userPhoneLabel.textColor = [UIColor lightGrayColor]; self.userPhoneLabel.translatesAutoresizingMaskIntoConstraints = NO; [self.backgroundImageView addSubview:self.userPhoneLabel]; // 分隔线 self.line = [UIView new]; self.line.backgroundColor = [UIColor blackColor]; self.line.translatesAutoresizingMaskIntoConstraints = NO; [self.backgroundImageView addSubview:self.line]; // 提示字 个人名片 self.tipsLabel = [UILabel new]; self.tipsLabel.text = @"个人名片"; self.tipsLabel.font = [UIFont systemFontOfSize:12.0f]; self.tipsLabel.textColor = [UIColor lightGrayColor]; self.tipsLabel.translatesAutoresizingMaskIntoConstraints = NO; [self.backgroundImageView addSubview:self.tipsLabel]; [self _setupConstraintsXX]; } - (void)updateBusinessCardMargin:(UIEdgeInsets)margin { if (_margin.top == margin.top && _margin.bottom == margin.bottom && _margin.left == margin.left && _margin.right == margin.right) { return; } _margin = margin; [self removeConstraints:self.marginConstraints]; [self _setupConstraintsXX]; } #pragma mark - getter and setter - (void)setUserHeaderImageView:(UIImageView *)userHeaderImageView { objc_setAssociatedObject(self, &_userHeaderImageView_, userHeaderImageView, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } - (UIImageView *)userHeaderImageView { return objc_getAssociatedObject(self, &_userHeaderImageView_); } - (void)setUserNameLabel:(UILabel *)userNameLabel { objc_setAssociatedObject(self, &_userNameLabel_, userNameLabel, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } - (UILabel *)userNameLabel { return objc_getAssociatedObject(self, &_userNameLabel_); } - (void)setUserPhoneLabel:(UILabel *)userPhoneLabel { objc_setAssociatedObject(self, &_userPhoneLabel_, userPhoneLabel, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } - (UILabel *)userPhoneLabel { return objc_getAssociatedObject(self, &_userPhoneLabel_); } - (void)setLine:(UIView *)line { objc_setAssociatedObject(self, &_line_, line, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } - (UIView *)line { return objc_getAssociatedObject(self, &_line_); } - (void)setTipsLabel:(UILabel *)tipsLabel { objc_setAssociatedObject(self, &_tipsLabel_, tipsLabel, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } - (UILabel *)tipsLabel { return objc_getAssociatedObject(self, &_tipsLabel_); } @end
六、写一个控制器,父类是ChatViewController,然后在这个类里实现代理方法,特定cell显示,特定cell行高,或者你也可以像我一样直接在ChatViewController里实现代理方法,官网的红包里是参过继承方式实现的,还有注释,这是一个带有红包功能的聊天控制器。
看了环信的源码,感觉写红包SDK的人明显技术比之前写那些SDK的人技术好,当然如果你懂,你也在里面看到itcast。
#pragma mark - EaseMessageViewControllerDelegate /// 遵守协议,为红包,名片提供自定义cell - (UITableViewCell *)messageViewController:(UITableView *)tableView cellForMessageModel:(id<IMessageModel>)messageModel { //样例为如果消息是文本消息显示用户自定义cell if (messageModel.bodyType == EMMessageBodyTypeText && [[messageModel text] hasPrefix:@"[名片]"]) { NSString *CellIdentifier = [BSBusinessCardCell cellIdentifierWithModel:messageModel]; //CustomMessageCell为用户自定义cell,继承了EaseBaseMessageCell BSBusinessCardCell *cell = (BSBusinessCardCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[BSBusinessCardCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier model:messageModel]; cell.selectionStyle = UITableViewCellSelectionStyleNone; } cell.model = messageModel; return cell; } return nil; } /// 遵守协议,为红包,名片提供自定义高度 - (CGFloat)messageViewController:(EaseMessageViewController *)viewController heightForMessageModel:(id<IMessageModel>)messageModel withCellWidth:(CGFloat)cellWidth { //样例为如果消息是文本消息使用用户自定义cell的高度 if (messageModel.bodyType == EMMessageBodyTypeText && [[messageModel text] hasPrefix:@"[名片]"]) { //CustomMessageCell为用户自定义cell,继承了EaseBaseMessageCell return [BSBusinessCardCell cellHeightWithModel:messageModel]; } return 0.f; }
后续还有很多事要做,点击这个名片,跳转到详细信息,如果是好友,则显示发消息,修改标签
如果不是好友则显示添加到通讯录,貌似微信做的是也可以修改标签,任重而道远,后面还有红包,
我想记录下此刻的状态,毕竟之前也没有搞过环信,这次是直接把环信官网的demo托到项目里来的
时间紧迫,没有办法