|
|
|
//
|
|
|
|
// XHMessageTableViewCell.m
|
|
|
|
// MessageDisplayExample
|
|
|
|
//
|
|
|
|
// Created by HUAJIE-1 on 14-4-24.
|
|
|
|
// Copyright (c) 2014年 曾宪华 开发团队(http://iyilunba.com ) 本人QQ:543413507 本人QQ群(142557668). All rights reserved.
|
|
|
|
//
|
|
|
|
|
|
|
|
#import "XHMessageTableViewCell.h"
|
|
|
|
#import "Circle.h"
|
|
|
|
#import "JSToastDialogs.h"
|
|
|
|
#import "User.h"
|
|
|
|
#import "UIViewExt.h"
|
|
|
|
|
|
|
|
static const CGFloat kXHLabelPadding = 5.0f;
|
|
|
|
static const CGFloat kXHTimeStampLabelHeight = 20.0f;
|
|
|
|
|
|
|
|
static const CGFloat kXHAvatarPaddingX = 16.0;
|
|
|
|
static const CGFloat kXHAvatarPaddingY = 15;
|
|
|
|
|
|
|
|
static const CGFloat kXHUserNameLabelHeight = 12;
|
|
|
|
|
|
|
|
@interface XHMessageTableViewCell () {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
@property (nonatomic, weak, readwrite) XHMessageBubbleView *messageBubbleView;
|
|
|
|
|
|
|
|
@property (nonatomic, weak, readwrite) UIButton *avatarButton;
|
|
|
|
|
|
|
|
@property (nonatomic, weak, readwrite) UILabel *userNameLabel;
|
|
|
|
|
|
|
|
//@property (nonatomic, weak, readwrite) LKBadgeView *timestampLabel;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 是否显示时间轴Label
|
|
|
|
*/
|
|
|
|
@property (nonatomic, assign) BOOL displayTimestamp;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 1、是否显示Time Line的label
|
|
|
|
*
|
|
|
|
* @param message 需要配置的目标消息Model
|
|
|
|
*/
|
|
|
|
- (void)configureTimestamp:(BOOL)displayTimestamp atMessage:(XHMessage *)message;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 2、配置头像
|
|
|
|
*
|
|
|
|
* @param message 需要配置的目标消息Model
|
|
|
|
*/
|
|
|
|
- (void)configAvatarWithMessage:(XHMessage *)message;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 3、配置需要显示什么消息内容,比如语音、文字、视频、图片
|
|
|
|
*
|
|
|
|
* @param message 需要配置的目标消息Model
|
|
|
|
*/
|
|
|
|
- (void)configureMessageBubbleViewWithMessage:(XHMessage *)message;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 头像按钮,点击事件
|
|
|
|
*
|
|
|
|
* @param sender 头像按钮对象
|
|
|
|
*/
|
|
|
|
- (void)avatarButtonClicked:(UIButton *)sender;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 统一一个方法隐藏MenuController,多处需要调用
|
|
|
|
*/
|
|
|
|
- (void)setupNormalMenuController;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 点击Cell的手势处理方法,用于隐藏MenuController的
|
|
|
|
*
|
|
|
|
* @param tapGestureRecognizer 点击手势对象
|
|
|
|
*/
|
|
|
|
- (void)tapGestureRecognizerHandle:(UITapGestureRecognizer *)tapGestureRecognizer;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 长按Cell的手势处理方法,用于显示MenuController的
|
|
|
|
*
|
|
|
|
* @param longPressGestureRecognizer 长按手势对象
|
|
|
|
*/
|
|
|
|
- (void)longPressGestureRecognizerHandle:(UILongPressGestureRecognizer *)longPressGestureRecognizer;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 单击手势处理方法,用于点击多媒体消息触发方法,比如点击语音需要播放的回调、点击图片需要查看大图的回调
|
|
|
|
*
|
|
|
|
* @param tapGestureRecognizer 点击手势对象
|
|
|
|
*/
|
|
|
|
- (void)sigleTapGestureRecognizerHandle:(UITapGestureRecognizer *)tapGestureRecognizer;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 双击手势处理方法,用于双击文本消息,进行放大文本的回调
|
|
|
|
*
|
|
|
|
* @param tapGestureRecognizer 双击手势对象
|
|
|
|
*/
|
|
|
|
- (void)doubleTapGestureRecognizerHandle:(UITapGestureRecognizer *)tapGestureRecognizer;
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation XHMessageTableViewCell
|
|
|
|
|
|
|
|
- (void)avatarButtonClicked:(UIButton *)sender {
|
|
|
|
if ([self.delegate respondsToSelector:@selector(didSelectedAvatarOnMessage:atIndexPath:)]) {
|
|
|
|
[self.delegate didSelectedAvatarOnMessage:self.messageBubbleView.message atIndexPath:self.indexPath];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark - Copying Method
|
|
|
|
|
|
|
|
- (BOOL)canBecomeFirstResponder {
|
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL)becomeFirstResponder {
|
|
|
|
return [super becomeFirstResponder];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
|
|
|
|
return (action == @selector(copyed:) || action == @selector(transpond:) || action == @selector(favorites:) || action == @selector(more:));
|
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark - Menu Actions
|
|
|
|
|
|
|
|
- (void)copyed:(id)sender {
|
|
|
|
[[UIPasteboard generalPasteboard] setString:self.messageBubbleView.displayTextView.text];
|
|
|
|
[self resignFirstResponder];
|
|
|
|
DLog(@"Cell was copy");
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)transpond:(id)sender {
|
|
|
|
DLog(@"Cell was transpond");
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)favorites:(id)sender {
|
|
|
|
DLog(@"Cell was favorites");
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)more:(id)sender {
|
|
|
|
DLog(@"Cell was more");
|
|
|
|
|
|
|
|
if (self.messageBubbleView.message.content && self.messageBubbleView.message.senderID) {
|
|
|
|
|
|
|
|
NSMutableDictionary *parameters = [[NSMutableDictionary alloc] init];
|
|
|
|
[parameters setObject:self.messageBubbleView.message.content forKey:@"content"];
|
|
|
|
[parameters setObject:self.messageBubbleView.message.senderID forKey:@"reportID"];
|
|
|
|
|
|
|
|
Circle *circle = [[Circle alloc] init];
|
|
|
|
[circle reportCircleMessageWithParameters:parameters
|
|
|
|
success:^(id responseObject) {
|
|
|
|
DLog(@"Report success");
|
|
|
|
[[JSToastDialogs shareInstance] makeToast:@"举报发送成功" duration:3];
|
|
|
|
} failure:^{
|
|
|
|
DLog(@"Report failure");
|
|
|
|
}];
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark - Setters
|
|
|
|
|
|
|
|
- (void)configureCellWithMessage:(XHMessage *)message
|
|
|
|
displaysTimestamp:(BOOL)displayTimestamp {
|
|
|
|
// 1、是否显示Time Line的label
|
|
|
|
[self configureTimestamp:displayTimestamp atMessage:message];
|
|
|
|
|
|
|
|
// 2、配置头像
|
|
|
|
[self configAvatarWithMessage:message];
|
|
|
|
|
|
|
|
// 3、配置用户名
|
|
|
|
[self configUserNameWithMessage:message];
|
|
|
|
|
|
|
|
// 4、配置需要显示什么消息内容,比如语音、文字、视频、图片
|
|
|
|
[self configureMessageBubbleViewWithMessage:message];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)configureTimestamp:(BOOL)displayTimestamp atMessage:(XHMessage *)message {
|
|
|
|
self.displayTimestamp = [message shouldShowTimestamp];
|
|
|
|
self.timestampLabel.hidden = ![message shouldShowTimestamp];
|
|
|
|
if (displayTimestamp) {
|
|
|
|
NSString *dateText = nil;
|
|
|
|
NSString *timeText = nil;
|
|
|
|
|
|
|
|
NSDate *today = [NSDate date];
|
|
|
|
NSDateComponents *components = [[NSDateComponents alloc] init];
|
|
|
|
[components setDay:-1];
|
|
|
|
NSDate *yesterday = [[NSCalendar currentCalendar] dateByAddingComponents:components toDate:today options:0];
|
|
|
|
|
|
|
|
NSDateComponents *dateComponents = [[NSCalendar currentCalendar] components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay
|
|
|
|
fromDate:[NSDate dateWithTimeIntervalSince1970:[message.timestamp doubleValue]]];
|
|
|
|
NSDateComponents *todayComponents = [[NSCalendar currentCalendar] components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay
|
|
|
|
fromDate:today];
|
|
|
|
NSDateComponents *yesterdayComponents = [[NSCalendar currentCalendar] components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay
|
|
|
|
fromDate:yesterday];
|
|
|
|
|
|
|
|
if (dateComponents.year == todayComponents.year && dateComponents.month == todayComponents.month && dateComponents.day == todayComponents.day) {
|
|
|
|
dateText = NSLocalizedStringFromTable(@"Today", @"MessageDisplayKitString", @"今天");
|
|
|
|
} else if (dateComponents.year == yesterdayComponents.year && dateComponents.month == yesterdayComponents.month && dateComponents.day == yesterdayComponents.day) {
|
|
|
|
dateText = NSLocalizedStringFromTable(@"Yesterday", @"MessageDisplayKitString", @"昨天");
|
|
|
|
} else {
|
|
|
|
dateText = [NSDateFormatter localizedStringFromDate:[NSDate dateWithTimeIntervalSince1970:[message.timestamp doubleValue]]
|
|
|
|
dateStyle:NSDateFormatterMediumStyle
|
|
|
|
timeStyle:NSDateFormatterNoStyle];
|
|
|
|
}
|
|
|
|
timeText = [NSDateFormatter localizedStringFromDate:[NSDate dateWithTimeIntervalSince1970:[message.timestamp doubleValue]]
|
|
|
|
dateStyle:NSDateFormatterNoStyle
|
|
|
|
timeStyle:NSDateFormatterShortStyle];
|
|
|
|
|
|
|
|
self.timestampLabel.text = [NSString stringWithFormat:@"%@ %@",dateText,timeText];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)configAvatarWithMessage:(XHMessage *)message {
|
|
|
|
UIImage *avatarPhoto = message.avatar;
|
|
|
|
NSString *avatarURL = message.avator;
|
|
|
|
|
|
|
|
if (avatarPhoto)
|
|
|
|
{
|
|
|
|
[self configAvatarWithPhoto:avatarPhoto];
|
|
|
|
if (avatarURL) {
|
|
|
|
[self configAvatarWithPhotoURLString:avatarURL];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (avatarURL)
|
|
|
|
{
|
|
|
|
[self configAvatarWithPhotoURLString:avatarURL];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
UIImage *avatarPhoto = [self getAvatarPlaceholderImage];
|
|
|
|
[self configAvatarWithPhoto:avatarPhoto];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- (UIImage *)getAvatarPlaceholderImage {
|
|
|
|
NSString *avatarPalceholderImageName = [[XHConfigurationHelper appearance].messageTableStyle objectForKey:kXHMessageTableAvatarPalceholderImageNameKey];
|
|
|
|
if (!avatarPalceholderImageName) {
|
|
|
|
avatarPalceholderImageName = @"avatar";
|
|
|
|
}
|
|
|
|
return [UIImage imageNamed:avatarPalceholderImageName];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)configAvatarWithPhoto:(UIImage *)photo {
|
|
|
|
[self.avatarButton setImage:photo forState:UIControlStateNormal];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)configAvatarWithPhotoURLString:(NSString *)photoURLString {
|
|
|
|
BOOL customLoadAvatarNetworkImage = [[[XHConfigurationHelper appearance].messageTableStyle objectForKey:kXHMessageTableCustomLoadAvatarNetworImageKey] boolValue];
|
|
|
|
if (!customLoadAvatarNetworkImage) {
|
|
|
|
XHMessageAvatarType avatarType = [[[XHConfigurationHelper appearance].messageTableStyle objectForKey:kXHMessageTableAvatarTypeKey] integerValue];
|
|
|
|
self.avatarButton.messageAvatarType = avatarType;
|
|
|
|
[self.avatarButton setImageWithURL:[NSURL URLWithString:photoURLString] placeholer:[self getAvatarPlaceholderImage]];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)configUserNameWithMessage:(XHMessage *)message {
|
|
|
|
self.userNameLabel.text = message.senderName;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)configureMessageBubbleViewWithMessage:(XHMessage *)message {
|
|
|
|
XHBubbleMessageMediaType currentMediaType = message.messageMediaType;
|
|
|
|
for (UIGestureRecognizer *gesTureRecognizer in self.messageBubbleView.bubbleImageView.gestureRecognizers) {
|
|
|
|
[self.messageBubbleView.bubbleImageView removeGestureRecognizer:gesTureRecognizer];
|
|
|
|
}
|
|
|
|
for (UIGestureRecognizer *gesTureRecognizer in self.messageBubbleView.bubblePhotoImageView.gestureRecognizers) {
|
|
|
|
[self.messageBubbleView.bubblePhotoImageView removeGestureRecognizer:gesTureRecognizer];
|
|
|
|
}
|
|
|
|
for (UIGestureRecognizer *gesTureRecognizer in self.messageBubbleView.gestureRecognizers) {
|
|
|
|
[self.messageBubbleView.bubblePhotoImageView removeGestureRecognizer:gesTureRecognizer];
|
|
|
|
}
|
|
|
|
for (UIGestureRecognizer *gesTureRecognizer in self.gestureRecognizers) {
|
|
|
|
[self.messageBubbleView.bubblePhotoImageView removeGestureRecognizer:gesTureRecognizer];
|
|
|
|
}
|
|
|
|
switch (currentMediaType) {
|
|
|
|
case XHBubbleMessageMediaTypePhoto:
|
|
|
|
case XHBubbleMessageMediaTypeVideo:
|
|
|
|
case XHBubbleMessageMediaTypeLocalPosition: {
|
|
|
|
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(sigleTapGestureRecognizerHandle:)];
|
|
|
|
[self.messageBubbleView.bubblePhotoImageView addGestureRecognizer:tapGestureRecognizer];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case XHBubbleMessageMediaTypeText:
|
|
|
|
case XHBubbleMessageMediaTypeVoice:
|
|
|
|
case XHBubbleMessageMediaTypeEmotion: {
|
|
|
|
UITapGestureRecognizer *tapGestureRecognizer;
|
|
|
|
if (currentMediaType == XHBubbleMessageMediaTypeText) {
|
|
|
|
tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doubleTapGestureRecognizerHandle:)];
|
|
|
|
} else {
|
|
|
|
tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(sigleTapGestureRecognizerHandle:)];
|
|
|
|
}
|
|
|
|
tapGestureRecognizer.numberOfTapsRequired = (currentMediaType == XHBubbleMessageMediaTypeText ? 2 : 1);
|
|
|
|
[self.messageBubbleView.bubbleImageView addGestureRecognizer:tapGestureRecognizer];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(sigleTapGestureRecognizerHandle:)];
|
|
|
|
[self.messageBubbleView addGestureRecognizer:tapGestureRecognizer];
|
|
|
|
[self addGestureRecognizer:tapGestureRecognizer];
|
|
|
|
|
|
|
|
[self.messageBubbleView configureCellWithMessage:message];
|
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark - Gestures
|
|
|
|
|
|
|
|
- (void)setupNormalMenuController {
|
|
|
|
UIMenuController *menu = [UIMenuController sharedMenuController];
|
|
|
|
if (menu.isMenuVisible) {
|
|
|
|
[menu setMenuVisible:NO animated:YES];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)tapGestureRecognizerHandle:(UITapGestureRecognizer *)tapGestureRecognizer {
|
|
|
|
[self updateMenuControllerVisiable];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)updateMenuControllerVisiable {
|
|
|
|
[self setupNormalMenuController];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)longPressGestureRecognizerHandle:(UILongPressGestureRecognizer *)longPressGestureRecognizer {
|
|
|
|
if (longPressGestureRecognizer.state != UIGestureRecognizerStateBegan || ![self becomeFirstResponder])
|
|
|
|
return;
|
|
|
|
|
|
|
|
NSArray *popMenuTitles = [[XHConfigurationHelper appearance] popMenuTitles];
|
|
|
|
NSMutableArray *menuItems = [[NSMutableArray alloc] init];
|
|
|
|
for (int i = 0; i < popMenuTitles.count; i ++) {
|
|
|
|
NSString *title = popMenuTitles[i];
|
|
|
|
SEL action = nil;
|
|
|
|
switch (i) {
|
|
|
|
case 0: {
|
|
|
|
if ([self.messageBubbleView.message messageMediaType] == XHBubbleMessageMediaTypeText) {
|
|
|
|
action = @selector(copyed:);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 1: {
|
|
|
|
action = @selector(transpond:);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 2: {
|
|
|
|
action = @selector(favorites:);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 3: {
|
|
|
|
action = @selector(more:);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (action) {
|
|
|
|
UIMenuItem *item = [[UIMenuItem alloc] initWithTitle:title action:action];
|
|
|
|
if (item) {
|
|
|
|
[menuItems addObject:item];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
UIMenuController *menu = [UIMenuController sharedMenuController];
|
|
|
|
[menu setMenuItems:menuItems];
|
|
|
|
|
|
|
|
CGRect targetRect = [self convertRect:[self.messageBubbleView bubbleFrame]
|
|
|
|
fromView:self.messageBubbleView];
|
|
|
|
|
|
|
|
[menu setTargetRect:CGRectInset(targetRect, 0.0f, 4.0f) inView:self];
|
|
|
|
|
|
|
|
|
|
|
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
|
|
selector:@selector(handleMenuWillShowNotification:)
|
|
|
|
name:UIMenuControllerWillShowMenuNotification
|
|
|
|
object:nil];
|
|
|
|
[menu setMenuVisible:YES animated:YES];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)sigleTapGestureRecognizerHandle:(UITapGestureRecognizer *)tapGestureRecognizer {
|
|
|
|
if (tapGestureRecognizer.state == UIGestureRecognizerStateEnded) {
|
|
|
|
[self setupNormalMenuController];
|
|
|
|
|
|
|
|
if ([self.delegate respondsToSelector:@selector(multiMediaMessageDidSelectedOnMessage:atIndexPath:onMessageTableViewCell:)]) {
|
|
|
|
if ([tapGestureRecognizer.view isEqual:self.messageBubbleView] || [tapGestureRecognizer.view isEqual:self]) {
|
|
|
|
[self.delegate multiMediaMessageDidSelectedOnMessage:nil atIndexPath:self.indexPath onMessageTableViewCell:self];
|
|
|
|
}else{
|
|
|
|
[self.delegate multiMediaMessageDidSelectedOnMessage:self.messageBubbleView.message atIndexPath:self.indexPath onMessageTableViewCell:self];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)doubleTapGestureRecognizerHandle:(UITapGestureRecognizer *)tapGestureRecognizer {
|
|
|
|
if (tapGestureRecognizer.state == UIGestureRecognizerStateEnded) {
|
|
|
|
if ([self.delegate respondsToSelector:@selector(didDoubleSelectedOnTextMessage:atIndexPath:)]) {
|
|
|
|
[self.delegate didDoubleSelectedOnTextMessage:self.messageBubbleView.message atIndexPath:self.indexPath];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark - Notifications
|
|
|
|
|
|
|
|
- (void)handleMenuWillHideNotification:(NSNotification *)notification {
|
|
|
|
[[NSNotificationCenter defaultCenter] removeObserver:self
|
|
|
|
name:UIMenuControllerWillHideMenuNotification
|
|
|
|
object:nil];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)handleMenuWillShowNotification:(NSNotification *)notification {
|
|
|
|
[[NSNotificationCenter defaultCenter] removeObserver:self
|
|
|
|
name:UIMenuControllerWillShowMenuNotification
|
|
|
|
object:nil];
|
|
|
|
|
|
|
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
|
|
selector:@selector(handleMenuWillHideNotification:)
|
|
|
|
name:UIMenuControllerWillHideMenuNotification
|
|
|
|
object:nil];
|
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark - Getters
|
|
|
|
|
|
|
|
- (XHBubbleMessageType)bubbleMessageType {
|
|
|
|
return self.messageBubbleView.message.bubbleMessageType;
|
|
|
|
}
|
|
|
|
|
|
|
|
+ (CGFloat)calculateCellHeightWithMessage:(XHMessage *)message
|
|
|
|
displaysTimestamp:(BOOL)displayTimestamp {
|
|
|
|
|
|
|
|
// 第一,是否有时间戳的显示
|
|
|
|
CGFloat timestampHeight = displayTimestamp ? (kXHTimeStampLabelHeight + kXHLabelPadding * 2) : 10;
|
|
|
|
CGFloat userHi = message.messageMediaType == XHBubbleMessageMediaTypeEmotion ? 20 : 0;
|
|
|
|
|
|
|
|
CGFloat userInfoNeedHeight = kXHAvatarPaddingY + kXHAvatarImageSize + kXHUserNameLabelHeight + kXHAvatarPaddingY + timestampHeight;
|
|
|
|
|
|
|
|
CGFloat bubbleMessageHeight = [XHMessageBubbleView calculateCellHeightWithMessage:message] + timestampHeight + kXHUserNameLabelHeight;
|
|
|
|
|
|
|
|
NSLog(@"----%f\n----%f\n----%f",timestampHeight,bubbleMessageHeight,MAX(bubbleMessageHeight, userInfoNeedHeight));
|
|
|
|
|
|
|
|
return MAX(bubbleMessageHeight, userInfoNeedHeight)+userHi;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#pragma mark - Life cycle
|
|
|
|
|
|
|
|
- (void)setup {
|
|
|
|
self.backgroundColor = [UIColor clearColor];
|
|
|
|
self.selectionStyle = UITableViewCellSelectionStyleNone;
|
|
|
|
self.accessoryType = UITableViewCellAccessoryNone;
|
|
|
|
self.accessoryView = nil;
|
|
|
|
|
|
|
|
UILongPressGestureRecognizer *recognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressGestureRecognizerHandle:)];
|
|
|
|
[recognizer setMinimumPressDuration:0.4f];
|
|
|
|
[self addGestureRecognizer:recognizer];
|
|
|
|
|
|
|
|
|
|
|
|
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapGestureRecognizerHandle:)];
|
|
|
|
[self addGestureRecognizer:tapGestureRecognizer];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (instancetype)initWithMessage:(XHMessage *)message
|
|
|
|
displaysTimestamp:(BOOL)displayTimestamp
|
|
|
|
reuseIdentifier:(NSString *)cellIdentifier {
|
|
|
|
self = [self initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
|
|
|
|
if (self) {
|
|
|
|
// 如果初始化成功,那就根据Message类型进行初始化控件,比如配置头像,配置发送和接收的样式
|
|
|
|
|
|
|
|
// 1、是否显示Time Line的label
|
|
|
|
if (!_timestampLabel) {
|
|
|
|
UIColor *timestampLabelTextColor = [[XHConfigurationHelper appearance].messageTableStyle objectForKey:kXHMessageTableTimestampTextColorKey];
|
|
|
|
if (!timestampLabelTextColor) {
|
|
|
|
timestampLabelTextColor = [UIColor whiteColor];
|
|
|
|
}
|
|
|
|
UIColor *timestampBackgroundColor = [[XHConfigurationHelper appearance].messageTableStyle objectForKey:kXHMessageTableTimestampBackgroundColorKey];
|
|
|
|
if (!timestampBackgroundColor) {
|
|
|
|
//timestampBackgroundColor = [UIColor colorWithWhite:0.734 alpha:1.000];
|
|
|
|
timestampBackgroundColor = KKClearColor;
|
|
|
|
}
|
|
|
|
LKBadgeView *timestampLabel = [[LKBadgeView alloc] initWithFrame:CGRectMake(0, kXHLabelPadding, MDK_SCREEN_WIDTH, kXHTimeStampLabelHeight)];
|
|
|
|
timestampLabel.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin;
|
|
|
|
timestampLabel.badgeColor = timestampBackgroundColor;
|
|
|
|
//timestampLabel.textColor = timestampLabelTextColor;
|
|
|
|
timestampLabel.textColor = KKGrey163;
|
|
|
|
timestampLabel.font = Font_(12);
|
|
|
|
timestampLabel.center = CGPointMake(CGRectGetWidth([[UIScreen mainScreen] bounds]) / 2.0, timestampLabel.center.y);
|
|
|
|
[self.contentView addSubview:timestampLabel];
|
|
|
|
[self.contentView bringSubviewToFront:timestampLabel];
|
|
|
|
_timestampLabel = timestampLabel;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 2、配置头像
|
|
|
|
CGRect avatarButtonFrame;
|
|
|
|
switch (message.bubbleMessageType) {
|
|
|
|
case XHBubbleMessageTypeReceiving:
|
|
|
|
avatarButtonFrame = CGRectMake(kXHAvatarPaddingX,
|
|
|
|
kXHAvatarPaddingY + (self.displayTimestamp ? (kXHTimeStampLabelHeight + kXHLabelPadding * 2) : 0),
|
|
|
|
kXHAvatarImageSize,
|
|
|
|
kXHAvatarImageSize);
|
|
|
|
break;
|
|
|
|
case XHBubbleMessageTypeSending:
|
|
|
|
avatarButtonFrame = CGRectMake(CGRectGetWidth(self.bounds) - kXHAvatarImageSize - kXHAvatarPaddingX,
|
|
|
|
kXHAvatarPaddingY + (self.displayTimestamp ? (kXHTimeStampLabelHeight + kXHLabelPadding * 2) : 0),
|
|
|
|
kXHAvatarImageSize,
|
|
|
|
kXHAvatarImageSize);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
UIButton *avatarButton = [[UIButton alloc] initWithFrame:avatarButtonFrame];
|
|
|
|
[avatarButton setImage:[self getAvatarPlaceholderImage] forState:UIControlStateNormal];
|
|
|
|
avatarButton.layer.cornerRadius = kXHAvatarImageSize/2;
|
|
|
|
avatarButton.layer.masksToBounds = YES;
|
|
|
|
[avatarButton addTarget:self action:@selector(avatarButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
|
|
|
|
[self.contentView addSubview:avatarButton];
|
|
|
|
self.avatarButton = avatarButton;
|
|
|
|
|
|
|
|
UILabel *userNameLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.avatarButton.bounds) + 20, kXHUserNameLabelHeight)];
|
|
|
|
userNameLabel.backgroundColor = [UIColor clearColor];
|
|
|
|
userNameLabel.font = [UIFont systemFontOfSize:12];
|
|
|
|
userNameLabel.textColor = [UIColor darkGrayColor];
|
|
|
|
[self.contentView addSubview:userNameLabel];
|
|
|
|
self.userNameLabel = userNameLabel;
|
|
|
|
|
|
|
|
// 4、配置需要显示什么消息内容,比如语音、文字、视频、图片
|
|
|
|
if (!_messageBubbleView) {
|
|
|
|
// bubble container
|
|
|
|
XHMessageBubbleView *messageBubbleView = [[XHMessageBubbleView alloc] initWithFrame:CGRectZero message:message];
|
|
|
|
[self.contentView addSubview:messageBubbleView];
|
|
|
|
[self.contentView sendSubviewToBack:messageBubbleView];
|
|
|
|
self.messageBubbleView = messageBubbleView;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
|
|
|
|
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
|
|
|
|
if (self) {
|
|
|
|
// Initialization code
|
|
|
|
[self setup];
|
|
|
|
// self.backgroundColor = UIColor.blueColor;
|
|
|
|
}
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)awakeFromNib {
|
|
|
|
// Initialization code
|
|
|
|
[self setup];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)layoutSubviews {
|
|
|
|
[super layoutSubviews];
|
|
|
|
|
|
|
|
// 布局头像
|
|
|
|
CGFloat layoutOriginY = kXHAvatarPaddingY + (self.displayTimestamp ? kXHTimeStampLabelHeight : 0);
|
|
|
|
CGRect avatarButtonFrame = self.avatarButton.frame;
|
|
|
|
avatarButtonFrame.origin.y = layoutOriginY;
|
|
|
|
avatarButtonFrame.origin.x = ([self bubbleMessageType] == XHBubbleMessageTypeReceiving) ? kXHAvatarPaddingX : ((CGRectGetWidth(self.bounds) - kXHAvatarPaddingX - kXHAvatarImageSize));
|
|
|
|
self.avatarButton.frame = avatarButtonFrame;
|
|
|
|
|
|
|
|
// self.userNameLabel.backgroundColor = mainColor;
|
|
|
|
// self.messageBubbleView.backgroundColor = RGBA(220, 220, 220, .3);
|
|
|
|
if (self.bubbleMessageType == XHBubbleMessageTypeReceiving) {
|
|
|
|
self.userNameLabel.alpha = 1;
|
|
|
|
// 布局用户名
|
|
|
|
self.userNameLabel.textAlignment = NSTextAlignmentLeft;
|
|
|
|
self.userNameLabel.frame = CGRectMake(CGRectGetMaxX(avatarButtonFrame) + 8,
|
|
|
|
CGRectGetMinY(avatarButtonFrame),
|
|
|
|
CGRectGetWidth(self.bounds),
|
|
|
|
kXHUserNameLabelHeight);
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
self.userNameLabel.textAlignment = NSTextAlignmentRight;
|
|
|
|
self.userNameLabel.alpha = 1;
|
|
|
|
self.userNameLabel.frame = CGRectMake(self.avatarButton.left-8-120,
|
|
|
|
CGRectGetMinY(avatarButtonFrame),
|
|
|
|
120,
|
|
|
|
kXHUserNameLabelHeight);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 布局消息内容的View
|
|
|
|
CGFloat bubbleX = 0.0f;
|
|
|
|
CGFloat offsetX = 0.0f;
|
|
|
|
if ([self bubbleMessageType] == XHBubbleMessageTypeReceiving) {
|
|
|
|
bubbleX = kXHAvatarImageSize + kXHAvatarPaddingX * 2-7;
|
|
|
|
} else {
|
|
|
|
offsetX = kXHAvatarImageSize + kXHAvatarPaddingX * 2-7;
|
|
|
|
}
|
|
|
|
CGFloat timeStampLabelNeedHeight = (self.displayTimestamp ? (kXHTimeStampLabelHeight + kXHLabelPadding) : 0);
|
|
|
|
|
|
|
|
// if (self.bubbleMessageType == XHBubbleMessageTypeReceiving) {
|
|
|
|
// self.messageBubbleView.frame = CGRectMake(bubbleX,
|
|
|
|
// self.userNameLabel.bottom,
|
|
|
|
// CGRectGetWidth(self.contentView.bounds) - bubbleX - offsetX,
|
|
|
|
// CGRectGetHeight(self.contentView.bounds) - timeStampLabelNeedHeight - nameHeight);
|
|
|
|
// }
|
|
|
|
// else
|
|
|
|
{
|
|
|
|
self.messageBubbleView.frame = CGRectMake(bubbleX,
|
|
|
|
self.userNameLabel.bottom,
|
|
|
|
CGRectGetWidth(self.contentView.bounds) - bubbleX - offsetX,
|
|
|
|
CGRectGetHeight(self.contentView.bounds) - timeStampLabelNeedHeight);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)dealloc {
|
|
|
|
_avatarButton = nil;
|
|
|
|
_timestampLabel = nil;
|
|
|
|
_messageBubbleView = nil;
|
|
|
|
_indexPath = nil;
|
|
|
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark - TableViewCell
|
|
|
|
|
|
|
|
- (void)prepareForReuse {
|
|
|
|
// 这里做清除工作
|
|
|
|
[super prepareForReuse];
|
|
|
|
self.messageBubbleView.displayTextView.text = nil;
|
|
|
|
self.messageBubbleView.displayTextView.attributedText = nil;
|
|
|
|
self.messageBubbleView.bubbleImageView.image = nil;
|
|
|
|
self.messageBubbleView.emotionImageView.animatedImage = nil;
|
|
|
|
self.messageBubbleView.animationVoiceImageView.image = nil;
|
|
|
|
self.messageBubbleView.voiceDurationLabel.text = nil;
|
|
|
|
self.messageBubbleView.bubblePhotoImageView.messagePhoto = nil;
|
|
|
|
self.messageBubbleView.geolocationsLabel.text = nil;
|
|
|
|
|
|
|
|
self.userNameLabel.text = nil;
|
|
|
|
[self.avatarButton setImage:nil forState:UIControlStateNormal];
|
|
|
|
self.timestampLabel.text = nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
|
|
|
|
[super setSelected:selected animated:animated];
|
|
|
|
|
|
|
|
// Configure the view for the selected state
|
|
|
|
}
|
|
|
|
|
|
|
|
@end
|