融云 iOS SDK 自定义消息类型及展示
通过以下代码,开发者可实现自定义消息的类型及 UI 展示:
1、新建自定义消息类 “SimpleMessage.h” 文件,代码如下:
#import <RongIMLib/RongIMLib.h>
#import <RongIMLib/RCMessageContentView.h>
#define RCLocalMessageTypeIdentifier @”RC:SimpleMsg”
/**
* 文本消息类定义
*/
@interface SimpleMessage : RCMessageContent <NSCoding,RCMessageContentView>
/** 文本消息内容 */
@property(nonatomic, strong) NSString* content;
/**
* 附加信息
*/
@property(nonatomic, strong) NSString* extra;
/**
* 根据参数创建文本消息对象
* @param content 文本消息内容
*/
+(instancetype)messageWithContent:(NSString *)content;
@end
`SimpleMessage.m` 文件代码如下:
#import “SimpleMessage.h”
#import <RongIMLib/RCUtilities.h>
@implementation SimpleMessage
+(instancetype)messageWithContent:(NSString *)content {
SimpleMessage *msg = [[SimpleMessage alloc] init];
if (msg) {
msg.content = content;
}
return msg;
}
+(RCMessagePersistent)persistentFlag {
return (MessagePersistent_ISPERSISTED | MessagePersistent_ISCOUNTED);
}
#pragma mark – NSCoding protocol methods
#define KEY_TXTMSG_CONTENT @”content”
#define KEY_TXTMSG_EXTRA @”extra”
– (instancetype)initWithCoder:(NSCoder *)aDecoder
{
self = [super init];
if (self) {
self.content = [aDecoder decodeObjectForKey:KEY_TXTMSG_CONTENT];
self.extra = [aDecoder decodeObjectForKey:KEY_TXTMSG_EXTRA]; }
return self;
}
– (void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:self.content forKey:KEY_TXTMSG_CONTENT];
[aCoder encodeObject:self.extra forKey:KEY_TXTMSG_EXTRA];
}
#pragma mark – RCMessageCoding delegate methods
-(NSData *)encode {
NSMutableDictionary *dataDict=[NSMutableDictionary dictionary];
[dataDict setObject:self.content forKey:@”content”];
if (self.extra) {
[dataDict setObject:self.extra forKey:@”extra”];
}
if (self.senderUserInfo) {
NSMutableDictionary *__dic=[[NSMutableDictionary alloc]init];
if (self.senderUserInfo.name) {
[__dic setObject:self.senderUserInfo.name forKeyedSubscript:@”name”];
}
if (self.senderUserInfo.portraitUri) {
[__dic setObject:self.senderUserInfo.portraitUri forKeyedSubscript:@”icon”];
}
if (self.senderUserInfo.userId) {
[__dic setObject:self.senderUserInfo.userId forKeyedSubscript:@”id”];
}
[dataDict setObject:__dic forKey:@”user”];
}
//NSDictionary* dataDict = [NSDictionary dictionaryWithObjectsAndKeys:self.content, @”content”, nil];
NSData *data = [NSJSONSerialization dataWithJSONObject:dataDict
options:kNilOptions
error:nil];
return data;
}
-(void)decodeWithData:(NSData *)data {
__autoreleasing NSError* __error = nil;
if (!data) {
return;
}
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data
options:kNilOptions
error:&__error];
}
– (NSString *)conversationDigest
{
return @”会话列表要显示的内容”;
}
+(NSString *)getObjectName {
return @”xxxx”;
}
#if ! __has_feature(objc_arc)
-(void)dealloc
{
[super dealloc];
}
#endif//__has_feature(objc_arc)
@end
2、新建自定义消息展示 UI “SimpleMessageCell.h” 文件代码如下:
/**
* 文本消息Cell
*/
@interface SimpleMessageCell : RCMessageCell
/**
* 消息显示Label
*/
@property(strong, nonatomic) RCAttributedLabel *textLabel;
/**
* 消息背景
*/
@property(nonatomic, strong) UIImageView *bubbleBackgroundView;
/**
* 设置消息数据模型
*
* @param model 消息数据模型
*/
– (void)setDataModel:(RCMessageModel *)model;
@end
“SimpleMessageCell.m” 文件代码如下:
@interface SimpleMessageCell ()
– (void)initialize;
@end
@implementation SimpleMessageCell
– (NSDictionary *)attributeDictionary {
if (self.messageDirection == MessageDirection_SEND) {
return @{
@(NSTextCheckingTypeLink) : @{NSForegroundColorAttributeName : [UIColor blueColor]},
@(NSTextCheckingTypePhoneNumber) : @{NSForegroundColorAttributeName : [UIColor blueColor]}
};
} else {
return @{
@(NSTextCheckingTypeLink) : @{NSForegroundColorAttributeName : [UIColor blueColor]},
@(NSTextCheckingTypePhoneNumber) : @{NSForegroundColorAttributeName : [UIColor blueColor]}
};
}
return nil;
}
– (NSDictionary *)highlightedAttributeDictionary {
return [self attributeDictionary];
}
– (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self initialize];
}
return self;
}
– (id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
[self initialize];
}
return self;
}
– (void)initialize {
self.bubbleBackgroundView = [[UIImageView alloc] initWithFrame:CGRectZero];
[self.messageContentView addSubview:self.bubbleBackgroundView];
self.textLabel = [[RCAttributedLabel alloc] initWithFrame:CGRectZero];
self.textLabel.attributeDictionary = [self attributeDictionary];
self.textLabel.highlightedAttributeDictionary = [self highlightedAttributeDictionary];
[self.textLabel setFont:[UIFont systemFontOfSize:Text_Message_Font_Size]];
self.textLabel.numberOfLines = 0;
[self.textLabel setLineBreakMode:NSLineBreakByWordWrapping];
[self.textLabel setTextAlignment:NSTextAlignmentLeft];
[self.textLabel setTextColor:[UIColor blackColor]];
//[self.textLabel setBackgroundColor:[UIColor yellowColor]];
[self.bubbleBackgroundView addSubview:self.textLabel];
self.bubbleBackgroundView.userInteractionEnabled = YES;
UILongPressGestureRecognizer *longPress =
[[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressed:)];
[self.bubbleBackgroundView addGestureRecognizer:longPress];
}
– (void)setDataModel:(RCMessageModel *)model {
[super setDataModel:model];
[self setAutoLayout];
}
– (void)setAutoLayout {
RCTextMessage *_textMessage = (RCTextMessage *)self.model.content;
if (_textMessage) {
self.textLabel.text = _textMessage.content;
} else {
//DebugLog(@”[RongIMKit]: RCMessageModel.content is NOT RCTextMessage object”);
}
// ios 7
CGSize __textSize =
[_textMessage.content
boundingRectWithSize:CGSizeMake(self.baseContentView.bounds.size.width –
(10 + [RCIM sharedKit].globalMessagePortraitSize.width + 10) * 2 – 5 –
35,
MAXFLOAT)
options:NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesLineFragmentOrigin |
NSStringDrawingUsesFontLeading
attributes:@{
NSFontAttributeName : [UIFont systemFontOfSize:Text_Message_Font_Size]
} context:nil]
.size;
__textSize = CGSizeMake(ceilf(__textSize.width), ceilf(__textSize.height));
CGSize __labelSize = CGSizeMake(__textSize.width + 5, __textSize.height + 5);
CGFloat __bubbleWidth = __labelSize.width + 15 + 20 < 50 ? 50 : (__labelSize.width + 15 + 20);
CGFloat __bubbleHeight = __labelSize.height + 5 + 5 < 35 ? 35 : (__labelSize.height + 5 + 5);
CGSize __bubbleSize = CGSizeMake(__bubbleWidth, __bubbleHeight);
CGRect messageContentViewRect = self.messageContentView.frame;
if (MessageDirection_RECEIVE == self.messageDirection) {
messageContentViewRect.size.width = __bubbleSize.width;
self.messageContentView.frame = messageContentViewRect;
self.bubbleBackgroundView.frame = CGRectMake(0, 0, __bubbleSize.width, __bubbleSize.height);
self.textLabel.frame = CGRectMake(20, 5, __labelSize.width, __labelSize.height);
self.bubbleBackgroundView.image = [self imageNamed:@”chat_from_bg_normal” ofBundle:@”RongCloud.bundle”];
UIImage *image = self.bubbleBackgroundView.image;
self.bubbleBackgroundView.image = [self.bubbleBackgroundView.image
resizableImageWithCapInsets:UIEdgeInsetsMake(image.size.height * 0.8, image.size.width * 0.8,
image.size.height * 0.2, image.size.width * 0.2)];
} else {
messageContentViewRect.size.width = __bubbleSize.width;
messageContentViewRect.origin.x =
self.baseContentView.bounds.size.width –
(messageContentViewRect.size.width + 10 + [RCIM sharedKit].globalMessagePortraitSize.width + 10);
self.messageContentView.frame = messageContentViewRect;
self.bubbleBackgroundView.frame = CGRectMake(0, 0, __bubbleSize.width, __bubbleSize.height);
self.textLabel.frame = CGRectMake(15, 5, __labelSize.width, __labelSize.height);
self.bubbleBackgroundView.image = [self imageNamed:@”chat_to_bg_normal” ofBundle:@”RongCloud.bundle”];
UIImage *image = self.bubbleBackgroundView.image;
self.bubbleBackgroundView.image = [self.bubbleBackgroundView.image
resizableImageWithCapInsets:UIEdgeInsetsMake(image.size.height * 0.8, image.size.width * 0.2,
image.size.height * 0.2, image.size.width * 0.8)];
}
}
– (UIImage *)imageNamed:(NSString *)name ofBundle:(NSString *)bundleName {
UIImage *image = nil;
NSString *image_name = [NSString stringWithFormat:@”%@.png”, name];
NSString *resourcePath = [[NSBundle mainBundle] resourcePath];
NSString *bundlePath = [resourcePath stringByAppendingPathComponent:bundleName];
NSString *image_path = [bundlePath stringByAppendingPathComponent:image_name];
image = [[UIImage alloc] initWithContentsOfFile:image_path];
return image;
}
– (void)longPressed:(id)sender {
UILongPressGestureRecognizer *press = (UILongPressGestureRecognizer *)sender;
if (press.state == UIGestureRecognizerStateEnded) {
//DebugLog(@”long press end”);
return;
} else if (press.state == UIGestureRecognizerStateBegan) {
[self.delegate didLongTouchMessageCell:self.model inView:self.bubbleBackgroundView];
}
}
@end
3、注册自定义消息类及 UI
SDK 初始化方法 initWithAppKey 之后后注册消息类型
[[RCIMClient sharedClient]registerMessageType:SimpleMessage.class];
会话页面注册 UI
[self registerClass:SimpleMessageCell.class forCellWithReuseIdentifier:@”SimpleMessageCell”];
4、重写会话页面自定义消息展示的两个方法
-(RCMessageBaseCell *)rcConversationCollectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
RCMessageModel *model = self.conversationDataRepository[indexPath.row];
NSString * cellIndentifier=@”SimpleMessageCell”;
RCMessageBaseCell* cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIndentifier forIndexPath:indexPath];
[cell setDataModel:model];
return cell;
}
-(CGSize)rcConversationCollectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
//返回自定义cell的实际高度
return CGSizeMake(300, 60);
}
至此已完成自定义消息类型及展示,谢谢!