Message Type | Renderings |
Text message | ![]() |
Image message | ![]() |
Audio message | ![]() |
Video message | ![]() |
File message | ![]() |

onRecvNewMessage function in TUIMessageBaseDataProvider,Cell mode in the message list. The data required for Cell drawing is called CellData.TUILinkCellData in the TUIChat/UI_Classic/Cell/CellData/Custom folder, derived from TUIMessageCellData, for storing the text to display and the link to redirect. Sample code:public class TUILinkCellData: TUIBubbleMessageCellData {var text: String = ""var link: String = ""// ...}
@interface TUILinkCellData : TUIMessageCellData@property NSString *text;@property NSString *link;@end
getCellData: method of the parent class to convert V2TIMMessage to the drawing data TUILinkCellData of the message list Cell. Sample code:public class TUILinkCellData: TUIBubbleMessageCellData {override public class func getCellData(message: V2TIMMessage) -> TUIMessageCellData {guard let data = message.customElem?.data,let param = try? JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String: Any]else {return TUILinkCellData(direction: .incoming)}let cellData = TUILinkCellData(direction: message.isSelf ? .outgoing : .incoming)cellData.msgID = message.msgIDcellData.text = param["text"] as? String ?? ""cellData.link = param["link"] as? String ?? ""cellData.avatarUrl = URL(string: message.faceURL ?? "")return cellData}}
@implementation TUILinkCellData+ (TUIMessageCellData *)getCellData:(V2TIMMessage *)message {NSDictionary *param = [NSJSONSerialization JSONObjectWithData:message.customElem.data options:NSJSONReadingAllowFragments error:nil];TUILinkCellData *cellData = [[TUILinkCellData alloc] initWithDirection:message.isSelf ? MsgDirectionOutgoing : MsgDirectionIncoming];cellData.innerMessage = message;cellData.msgID = message.msgID;cellData.text = param[@"text"];cellData.link = param[@"link"];cellData.avatarUrl = [NSURL URLWithString:message.faceURL];return cellData;}@end
getDisplayString: method of the parent class to convert V2TIMMessage to the lastMsg display text information of the conversation list.
The lastMsg display text of the conversation list indicates that the last message of the current conversation will be displayed for each conversation Cell. See the figure below:
public class TUILinkCellData: TUIBubbleMessageCellData {override public class func getDisplayString(message: V2TIMMessage) -> String {guard let data = message.customElem?.data,let param = try? JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String: Any]else {return ""}return param["text"] as? String ?? ""}}
@implementation TUILinkCellData+ (NSString *)getDisplayString:(V2TIMMessage *)message {NSDictionary *param = [NSJSONSerialization JSONObjectWithData:message.customElem.data options:NSJSONReadingAllowFragments error:nil];return param[@"text"];}@end
TUILinkCell_Minimalist in the TUIChat/UI_Minimalist/Cell/Custom folder, derived from TUIBubbleMessageCell_Minimalist, for drawing TUILinkCellData data. Sample code:class TUILinkCell_Minimalist: TUIBubbleMessageCell_Minimalist {var myTextLabel: UILabel!var myLinkLabel: UILabel!var customData: TUILinkCellData?override func fill(with data: TUICommonCellData) {super.fill(with: data)if let data = data as? TUILinkCellData {customData = datamyTextLabel.text = data.textsetNeedsUpdateConstraints()updateConstraintsIfNeeded()layoutIfNeeded()}}}
@interface TUILinkCell_Minimalist : TUIBubbleMessageCell_Minimalist@property UILabel *myTextLabel; // Display text@property UILabel *myLinkLabel; // Link redirection text- (void)fillWithData:(TUILinkCellData *)data; // Draw UI@end
initWithStyle:reuseIdentifier: method of the parent class to create myTextLabel and myLinkLabel text display objects and add them to the container container. Sample code:class TUILinkCell_Minimalist: TUIBubbleMessageCell {override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {super.init(style: style, reuseIdentifier: reuseIdentifier)setupViews()}private func setupViews() {myTextLabel = UILabel()myTextLabel.numberOfLines = 0myTextLabel.font = UIFont.systemFont(ofSize: 15)myTextLabel.textAlignment = TUISwift.isRTL() ? .right : .leftmyTextLabel.textColor = TUISwift.tuiChatDynamicColor("chat_link_message_title_color", defaultColor: "#000000")container.addSubview(myTextLabel)myLinkLabel = UILabel()myLinkLabel.text = TUISwift.timCommonLocalizableString("TUIKitMoreLinkDetails")myLinkLabel.font = UIFont.systemFont(ofSize: 15)myLinkLabel.textAlignment = TUISwift.isRTL() ? .right : .leftmyLinkLabel.textColor = TUISwift.tuiChatDynamicColor("chat_link_message_subtitle_color", defaultColor: "#0000FF")container.addSubview(myLinkLabel)}}
@implementation TUILinkCell_Minimalist- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];if (self) {self.myTextLabel = [[UILabel alloc] init];[self.container addSubview:self.myTextLabel];self.myLinkLabel = [[UILabel alloc] init];self.myLinkLabel.text = @"View details >>";[self.container addSubview:_myLinkLabel];}return self;}@end
fillWithData: method of the parent class to custom display TUILinkCellData data in TUILinkCell. Sample code:class TUILinkCell_Minimalist: TUIBubbleMessageCell_Minimalist {override func fill(with data: TUICommonCellData) {super.fill(with: data)if let data = data as? TUILinkCellData {customData = datamyTextLabel.text = data.textsetNeedsUpdateConstraints()updateConstraintsIfNeeded()layoutIfNeeded()}}}
@implementation TUILinkCell_Minimalist// Draw the cell based on cellData- (void)fillWithData:(TUILinkCellData *)data;{[super fillWithData:data];self.myTextLabel.text = data.text;}@end
layoutSubviews method of the parent class to custom layout the controls. Sample code:override func layoutSubviews() {super.layoutSubviews()// Custimization}
// Set the control coordinates- (void)layoutSubviews{[super layoutSubviews];self.myTextLabel.mm_top(10).mm_left(10).mm_flexToRight(10).mm_flexToBottom(50);self.myLinkLabel.mm_sizeToFit().mm_left(10).mm_bottom(10);}@end
override class func getContentSize(_ data: TUIMessageCellData) -> CGSize {guard let linkCellData = data as? TUILinkCellData else {assertionFailure("data must be kind of TUILinkCellData")return .zero}let textMaxWidth = 245let font = UIFont.systemFont(ofSize: 15)let attributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.font: font]var size = CGSize(width: textMaxWidth, height: Int.max)let rect = linkCellData.text.boundingRect(with: size,options: [.usesLineFragmentOrigin, .usesFontLeading],attributes: attributes,context: nil)size = CGSize(width: textMaxWidth + 15, height: Int(rect.size.height) + 56)return size}
+ (CGSize)getContentSize:(TUIMessageCellData *)data {NSAssert([data isKindOfClass:TUILinkCellData.class], @"data must be kind of TUILinkCellData");TUILinkCellData *linkCellData = (TUILinkCellData *)data;CGFloat textMaxWidth = 245.f;CGRect rect = [linkCellData.text boundingRectWithSize:CGSizeMake(textMaxWidth, MAXFLOAT)options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeadingattributes:@{NSFontAttributeName : [UIFont systemFontOfSize:15]}context:nil];CGSize size = CGSizeMake(textMaxWidth + 15, rect.size.height + 56);return size;}
public class TUIMessageCellConfig_Minimalist: NSObject {// ...static func registerExternalCustomMessageInfo() {/*Insert your own custom message UI here, your businessID can not be same with built-inExample:registerCustomMessageCell(#your message cell#, messageCellData: #your message cell data#, forBusinessID: #your id#)*/}}
@implementation TUIMessageCellConfig_Minimalist (CustomMessageRegister)+ (void)registerExternalCustomMessageInfo {// Insert your own custom message UI here, your businessID can not be same with built-in //// Example:[self registerCustomMessageCell:@"TUILinkCell_Minimalist" messageCellData:@"TUILinkCellData" forBusinessID:BussinessID_TextLink];}
cell and cellData information in the registerCustomMessage function of TUIChatConfig.// The custom message's businessID (note that there should not be a duplication)TUIChatConfig_Minimalist.shared.registerCustomMessage(businessID: "text_link", messageCellClassName: "TUIChat.TUILinkCell", messageCellDataClassName: "TUIChat.TUILinkCellData")
// The custom message's businessID (note that there should not be a duplication)#define BussinessID_TextLink @"text_link"/** Register custom message's to TUIChat. The three parameters are* @param businessID Custom message's businessID* @param messagellClass Custom message's NSString type* @param messageCellDataClassName Custom message's NSString type* @param styleType UI style corresponding to this custom message, for example TUIChatRegisterCustomMessageStyleTypeMinimalist*/- (void)registerCustomMessageCell {[TUIChatConfig.defaultConfig registerCustomMessage:BussinessID_TextLinkmessageCellClassName:@"TUILinkCell_Minimalist"messageCellDataClassName:@"TUILinkCellData"styleType:TUIChatRegisterCustomMessageStyleTypeMinimalist];}
title and an leftMark. You can add a custom button by adding TUICustomActionSheetItem object to the customInputMoreActionItemList attribute of TUIChatDataProvider.TUICustomActionSheetItem title leftMark attributes. If you need to adjust the order of the buttons, you can set the priority attribute, where a higher priority value means the button appears further to the front. You can also set actionHandler to respond to button clicks and implement your own business logic.
class TUIChatDataProvider: TUIChatBaseDataProvider {// ...private func createCustomInputMoreActionItemList(model: TUIChatConversationModel) -> [TUICustomActionSheetItem] {if self.customInputMoreActionItemList.isEmpty {var arrayM: [TUICustomActionSheetItem] = []let showCustom = TUIChatConfig.shared.enableWelcomeCustomMessage && model.enableWelcomeCustomMessageif showCustom {let link = TUICustomActionSheetItem(title: TUISwift.timCommonLocalizableString("TUIKitMoreLink"), leftMark: UIImage.safeImage(TUISwift.tuiChatImagePath_Minimalist("icon_more_custom"))) { [weak self] _ inguard let self else { return }let text = TUISwift.timCommonLocalizableString("TUIKitWelcome")var homePageLink = TUITencentCloudHomePageENlet language = TUIGlobalization.getPreferredLanguage() ?? ""if language.contains("zh-") {homePageLink = TUITencentCloudHomePageCN}do {let param: [String: Any] = ["businessID": "text_link", "text": text, "link": homePageLink]let data = try JSONSerialization.data(withJSONObject: param, options: [])let message = TUIMessageDataProvider.getCustomMessageWithJsonData(data, desc: text, extensionInfo: text)self.delegate?.dataProvider(self, sendMessage: message)} catch {print("[\\(self)] Post Json Error")}}link.priority = 100arrayM.append(link)}if let items = model.customizedNewItemsInMoreMenu as? [TUICustomActionSheetItem], items.count > 0 {arrayM.append(contentsOf: items)}self.customInputMoreActionItemList = arrayM}return self.customInputMoreActionItemList}// For Minimalist Edition.func getInputMoreActionItemList(userID: String, groupID: String, conversationModel: TUIChatConversationModel, pushVC: UINavigationController?, actionController: TIMInputViewMoreActionProtocol) -> [TUICustomActionSheetItem] {var result: [TUICustomActionSheetItem] = []result.append(contentsOf: self.createBuiltInInputMoreActionItemList(model: conversationModel))result.append(contentsOf: self.createCustomInputMoreActionItemList(model: conversationModel))// ...}}
@implementation TUIChatDataProvider- (NSArray<TUICustomActionSheetItem *> *)customInputMoreActionItemList {if (_customInputMoreActionItemList == nil) {NSMutableArray *arrayM = [NSMutableArray array];if (TUIChatConfig.defaultConfig.enableWelcomeCustomMessage) {__weak typeof(self) weakSelf = self;TUICustomActionSheetItem *link =[[TUICustomActionSheetItem alloc] initWithTitle:TIMCommonLocalizableString(TUIKitMoreLink)leftMark:[UIImage imageNamed:TUIChatImagePath_Minimalist(@"icon_more_custom")]withActionHandler:^(UIAlertAction *_Nonnull action) {link.priority = 100;NSString *text = TIMCommonLocalizableString(TUIKitWelcome);NSString *link = TUITencentCloudHomePageEN;NSString *language = [TUIGlobalization tk_localizableLanguageKey];if ([language containsString:@"zh-"]) {link = TUITencentCloudHomePageCN;}NSError *error = nil;NSDictionary *param = @{BussinessID : BussinessID_TextLink, @"text" : text, @"link" : link};NSData *data = [NSJSONSerialization dataWithJSONObject:param options:0 error:&error];if (error) {NSLog(@"[%@] Post Json Error", [self class]);return;}V2TIMMessage *message = [TUIMessageDataProvider getCustomMessageWithJsonData:data desc:text extension:text];if ([weakSelf.delegate respondsToSelector:@selector(dataProvider:sendMessage:)]) {[weakSelf.delegate dataProvider:weakSelf sendMessage:message];}}];[arrayM addObject:link];}_customInputMoreActionItemList = [NSArray arrayWithArray:arrayM];}return _customInputMoreActionItemList;}@end
Feedback