好友推薦---環信傳送名片(自定義檢視)訊息
在整合環信即時通訊的基礎上,要做好友推薦的功能,查了下SDK發現裡面提供了自定義訊息的介面,接下來我們就可以根據自己的需要去自定義訊息檢視了
- (UITableViewCell *)messageViewController:(UITableView *)tableView cellForMessageModel:(id<IMessageModel>)messageModel{
環信的註釋是: 獲取訊息自定義cell
使用者根據messageModel判斷是否顯示自定義cell,返回nil顯示預設cell,否則顯示使用者自定義cell
既然提供了方法,那麼接下來我們就可以根據自己的需求去操作了(這裡只做好友推薦的檢視)
首先建立了繼承EaseBaseMessageCell的自定義訊息檢視(有些博友問我後面不執行代理方法,在這裡特此說明下,我是繼承重寫的,好多方法都是自己新增的,請留意你們的專案是直接修改還是繼承)
.h
@interface IMChatBusinessCardCell : EaseBaseMessageCell
@end
.m
#import "IMChatBusinessCardCell.h"
#import "EaseBubbleView+IMChatBusinessCard.h"
static const CGFloat kCellHeight = 110.0f;
@implementation IMChatBusinessCardCell
- (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)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)model{
[_bubbleView setupBusinessCardBubbleView];
_bubbleView.imageView.image = [UIImage imageNamed:@"shouyeliaotiankuangbai"];
}
- (void)updateCustomBubbleViewMargin:(UIEdgeInsets)bubbleMargin model:(id<IMessageModel>)mode{
[_bubbleView updateBusinessCardMargin:bubbleMargin];
_bubbleView.translatesAutoresizingMaskIntoConstraints = YES;
CGFloat bubbleViewHeight = 84;// 氣泡背景圖高度
CGFloat nameLabelHeight = 15;// 暱稱label的高度
if (mode.isSender) {
_bubbleView.frame =
CGRectMake([UIScreen mainScreen].bounds.size.width - 273.5, nameLabelHeight, 213, bubbleViewHeight);
}else{
_bubbleView.frame = CGRectMake(55, nameLabelHeight, 213, bubbleViewHeight);
}
// 這裡強制呼叫內部私有方法
[_bubbleView _setupConstraintsXX];
}
- (NSString *)cellIdentifierWithModel:(id<IMessageModel>)model{
return NSStringFromClass([self class]);
}
- (CGFloat)cellHeightWithModel:(id<IMessageModel>)model{
return kCellHeight;
}
- (void)setModel:(id<IMessageModel>)model{
[super setModel:model];
NSDictionary *dict = model.message.ext;
self.bubbleView.userNameLabel.text = dict[@"cardUserName"];
self.bubbleView.userPhoneLabel.text = dict[@"cardUserPhone"];
_hasRead.hidden = YES;//名片訊息不顯示已讀
}
- (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;
}
在這裡我們需要將控制元件的屬性介面放出來,在這裡有兩種方式,一種是直接在EaseBubbleView裡自行新增,還有一種是建立它的Category.這裡採用第二種方式
.h
#import "EaseBubbleView.h"
@interface EaseBubbleView (IMChatBusinessCard)
// 使用者頭像
@property (strong, nonatomic) UIImageView *userHeaderImageView;
// 使用者暱稱
@property (strong, nonatomic) UILabel *userNameLabel;
// 使用者手機號
@property (strong, nonatomic) UILabel *userPhoneLabel;
// 分割線
@property (strong, nonatomic) UIView *line;
// tip標籤
@property (strong, nonatomic) UILabel *tipsLabel;
// 設定名片氣泡
- (void)setupBusinessCardBubbleView;
// 更新名片間距
- (void)updateBusinessCardMargin:(UIEdgeInsets)margin;
// 設定約束
- (void)_setupConstraintsXX;
@end
.m
#import "EaseBubbleView+IMChatBusinessCard.h"
#import <objc/runtime.h>
static char _userHeaderImageView_;
static char _userNameLabel_;
static char _userPhoneLabel_;
static char _line_;
static char _tipsLabel_;
@implementation EaseBubbleView (IMChatBusinessCard)
- (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];
}
#pragma mark - public
- (void)setupBusinessCardBubbleView{
// 頭像
self.userHeaderImageView = [UIImageView new];
[self.userHeaderImageView setImage:[UIImage imageNamed:STR_DEFAULT_APPIMAGE]];
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
現在都定義好了,再回到自定義訊息樣式的方法中新增判斷就好了
- (UITableViewCell *)messageViewController:(UITableView *)tableView cellForMessageModel:(id<IMessageModel>)messageModel{
if (messageModel.bodyType == EMMessageBodyTypeText &&
[[messageModel text] hasPrefix:@"[名片]"]) {
NSString *CellIdentifier = [IMChatBusinessCardCell cellIdentifierWithModel:messageModel];
IMChatBusinessCardCell *cell = (IMChatBusinessCardCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[IMChatBusinessCardCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier model:messageModel];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
cell.model = messageModel;
return cell;
}
return nil;
}
說到這裡,那麼當我們推薦事件觸發的時候要怎麼做呢,這裡我隨便給了些假資料,僅供參考
- (void)sendRecommendFriend{
RMLog(@"傳送推薦好友");
EMMessage *message = [EaseSDKHelper sendTextMessage:@"[名片]"
to:@"600018"
messageType:EMChatTypeChat
messageExt:@{@"cardUserName":@"Raymon",@"cardUserPhone":@"13843838438"}];
[[EMClient sharedClient].chatManager sendMessage:message progress:^(int progress) {
RMLog(@"%d",progress);
} completion:^(EMMessage *message, EMError *error) {
TXHChatViewController *chatController = [[TXHChatViewController alloc] initWithConversationChatter:@"600018" conversationType:EMConversationTypeChat];
[self.navigationController pushViewController:chatController animated:YES];
}];
}
到這裡,我們傳送名片的功能已經做完,但可能也會有人和我一樣,如果要點選名片,要怎麼去做呢,這裡我問了下技術諮詢,是讓我在EaseMessageCell的bubbleViewTapAction方法中只保留
if ([_delegate respondsToSelector:@selector(messageCellSelected:)]) {
[_delegate messageCellSelected:_model];
return;
}
這一句,開始我也感覺其餘的判斷是多餘的,這樣就完全可以了,但是後面發現如果這樣修改後,到了後面自己要寫的和判斷的就要好多,所以變化了下思路,在EaseMessageViewController中添加了個點選自定義檢視(名片)訊息的協議,在- (void)messageCellSelected:(id<IMessageModel>)model
的
switch
判斷中協議
case EMMessageBodyTypeText:
{
if ([_delegate respondsToSelector:@selector(didSelectMessageModel:)]) {
[_delegate didSelectMessageModel:model];
}
}
然後在回到自己的控制器中進行判斷,個人感覺這樣可能更方便些吧
- (void)didSelectMessageModel:(id<IMessageModel>)messageModel{
if (messageModel.bodyType == EMMessageBodyTypeText &&
[[messageModel text] hasPrefix:@"[名片]"]){
// 點選名片
RMLog(@"點選名片");
}
}
好友推薦暫時就到這裡,後續還有好多功能,這裡只是積累下自己的開發心得和體會,也給自己留個記錄備註.而這些主要是參考了環信Demo裡的紅包功能去仿寫的,當然開始也在網上查詢了好多,都沒有發現完整的.希望在這裡一起學習
特此宣告,有些博友下載連結後說沒有Demo,我提供的只是邏輯,傳送紅包和其他自定義檢視都可適用,而連結下載的只是自定義的名片類,本身就不是完整的Demo,自行選擇下載,可以把下載後的類檔案直接拷貝道專案中使用,不會用就亂噴的請繞行