1. 程式人生 > >好友推薦---環信傳送名片(自定義檢視)訊息

好友推薦---環信傳送名片(自定義檢視)訊息

在整合環信即時通訊的基礎上,要做好友推薦的功能,查了下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,自行選擇下載,可以把下載後的類檔案直接拷貝道專案中使用,不會用就亂噴的請繞行