Skip to main content

Chat UI

The chat UI refers to the messaging page within an application, primarily consisting of two components: the message list and the input area.
IMKit provides the conversation page class RCConversationViewController, which is implemented based on UIKit's UIViewController.

tip

To display user nicknames and avatars in conversations, you have two implementation options:

  • Set up a user info provider for IMKit, which will fetch the required display data. For details, see User Info.
  • Use the User Profile Hosting feature. For details, see User Profile Hosting.

Chat Interface

The chat interface typically consists of three parts: the title bar, message list, and input area.

tip

The default conversation page RCConversationViewController in IMKit does not include a title bar implementation. You need to set the conversation title manually.

conversation(width=250) conversation(width=250) conversation(width=250)

Initialization

tip
  • When developing with IMKit, it's recommended to subclass RCConversationViewController to create a custom conversation page.
  • For troubleshooting or reproducing issues related to the conversation page, you can directly use the RCConversationViewController class to verify whether the issue stems from subclass overrides.

You can initialize the conversation page by calling the RCConversationViewController constructor and setting the conversationType and targetId values to create a one-to-one or group chat page.

Parameter Description

ParameterTypeDescription
conversationTypeRCConversationTypeConversation type
targetIdNSStringConversation ID

Sample Code

if (self.navigationController) {  
RCConversationViewController *conversationVC = [[RCConversationViewController alloc] initWithConversationType:conversationType targetId:targetId];
[self presentViewController:navigationController animated:YES completion:nil];
}

Component Breakdown

In the RCConversationViewController class, the conversation page consists of three main components:

PropertyTypeDescription
navigationBarUINavigationBariOS system navigation bar
conversationMessageCollectionViewRCBaseCollectionViewMessage list
chatSessionInputBarControlRCChatSessionInputBarControlInput area

Title Bar

IMKit's RCConversationViewController uses the system navigation bar to display the conversation title, such as the group name for group chats or the other user's name for one-to-one chats. You can manually set the title using the UIViewController's title property.

When the Typing Status feature is enabled, the title bar in one-to-one chats will display the other user's typing status. During searches, IMKit sets the titleView of UINavigationItem.

The title bar includes a left button that calls the leftBarButtonItemPressed method to exit the current page when clicked. You can override this method in your app. The title bar has no right button by default, but you can add one in a custom page. Refer to the rightBarButtonItemClicked method in SealTalk's source code [RCDChatViewController.m].

Message List

IMKit's RCConversationViewController displays all messages in chronological order.

The message list view is created and customized in the display templates for various message types, using classes like RCTextMessageCell, RCFileMessageCell, and RCImageMessageCell, which subclass RCMessageCell.

You can customize each item in the list view through the provided callback methods or override the registerCustomCellsAndMessages method to register custom message display templates. For details, see Custom Messages.

Parameter Description

PropertyTypeDescription
conversationMessageCollectionViewRCBaseCollectionViewMessage list
conversationDataRepositoryNSMutableArrayData source containing the data models for message cells (RCMessageModel objects).
tip

For events related to the message list, see Page Event Listeners.

Input Component

RCChatSessionInputBarControl is IMKit's message input component, where users can type and send messages, including text, files, voice, images, and videos. The input area view is created and controlled in RCChatSessionInputBarControl.

IMKit provides some input component-related event callbacks in RCConversationViewController. For details, see Input Area.

Customization

You can customize the chat page by modifying IMKit's global configuration and RCConversationViewController.

Before customization, it's recommended to subclass the built-in RCConversationViewController to create your own conversation page View Controller.

Sample Code

#import <RongIMKit/RongIMKit.h>  

@interface RCDChatViewController : RCConversationViewController
@property (nonatomic, assign) BOOL needPopToRootView;
@end
tip

Some styles and behaviors in the conversation page are affected by IMKit's global configuration. For global configuration details, see Configuration Guide.

Modify Avatar Shape and Size

The user avatars displayed in the conversation page (on RCMessageCell) can be modified via IMKit's global configuration.

The default avatar size is 40x40 pixels. Modify it as follows:

Sample Code

RCKitConfigCenter.ui.globalMessagePortraitSize = CGSizeMake(40, 40);  

Avatars are rectangular by default but can be rounded. You can also adjust the corner radius via global configuration.

Sample Code

RCKitConfigCenter.ui.globalMessageAvatarStyle = RC_USER_AVATAR_CYCLE;  
tip

Modifying IMKit's global configuration affects all user avatars in IMKit.

Display User Nicknames

You can configure whether user nicknames are displayed for received messages in IMKit's conversation page.

This feature is enabled by default (YES). Apps can set the displayUserNameInCell property of RCConversationViewController to YES or NO before entering the conversation page.

@property (nonatomic, assign) BOOL displayUserNameInCell;  

Hide the Emoji Button in the Input Area

tip

SDK versions ≥ 5.2.3 support disabling built-in Emoji. When disabled, the Emoji tab is hidden from the emoticon panel.

For configuration details, see Emoticon Area.

Modify Default History Message Fetch Count

IMKit fetches history messages when entering the conversation page or pulling down, with a default count of 10. It first retrieves local messages. If the Cloud Storage for One-to-One and Group Messages feature is enabled, IMKit fetches remote history messages afterward. You can modify the default count before entering the conversation page.

// Fetch local conversations. This property is deprecated; use defaultMessageCount instead.  
@property (nonatomic, assign) int defaultLocalHistoryMessageCount;
// Fetch remote conversations. This property is deprecated; use defaultMessageCount instead.
@property (nonatomic, assign) int defaultRemoteHistoryMessageCount;

/*!
Set the number of messages fetched when entering the conversation page or pulling down. Default is 10. Valid range: 1 < count ≤ 100.
@discussion This property must be set before viewDidLoad.
*/
@property (nonatomic, assign) int defaultMessageCount;
tip

You can enable the Cloud Storage for One-to-One and Group Messages feature yourself. For details, see Enable Cloud Storage for One-to-One and Group Messages.

Modify Delete Behavior in Long-Press Message Menu

IMKit's conversation page includes a delete option in the long-press message menu by default.

alt(width=250)

  • For IMKit versions ≥ 5.6.3, the default delete function removes the local message. If the App Key has Cloud Storage for One-to-One and Group Messages enabled, the remote message is also deleted.
  • For IMKit versions < 5.6.3, the default delete function only removes the local message. If Cloud Storage for One-to-One and Group Messages is enabled, the message remains in the server's history. Users may see it again when fetching history messages or triggering offline message compensation (e.g., after reinstalling or switching devices). To delete remote messages, apps must modify the default delete behavior.

To modify the delete behavior in IMKit's conversation page:

  • For SDK versions ≥ 5.2.3, set the needDeleteRemoteMessage property of RCConversationViewController. YES means IMKit deletes both local and remote messages. NO means only local messages are deleted.

    /*!  
    Default is NO (long-press only deletes local messages). Set to YES to delete both local and remote messages.
    */
    @property (nonatomic, assign) BOOL needDeleteRemoteMessage;
  • For SDK versions < 5.2.3, override the deleteMessage method in RCConversationViewController. Call the super method to delete the local message, then call the deleteRemoteMessage API to delete the remote message.

    /*!  
    Delete a message and update the UI.

    @param model The data model of the message cell.
    @discussion
    For versions before 5.2.3, the conversation page only deletes local messages. To delete remote history messages:
    1. Override this method and call super to delete the local message.
    2. Call the deleteRemoteMessage API to delete the remote message.
    */
    - (void)deleteMessage:(RCMessageModel *)model;
tip

If existing implementations don't meet your needs, you can use IMLib's capabilities directly. For core classes, APIs, and usage, see IMLib's Delete Message documentation. Note: IMLib methods don't provide UI updates. You must implement custom notifications for UI refreshes based on business requirements.

Hide User Avatars on Message Cells

IMKit SDK displays user avatars by default. Starting with version 5.3.0, IMKit SDK supports hiding avatars on RCMessageCell subclasses.

Override the willDisplayMessageCell method in the conversation page and set the showPortrait property of RCMessageCell to NO to hide avatars.

Sample Code

- (void)willDisplayMessageCell:(RCMessageBaseCell *)cell atIndexPath:(NSIndexPath *)indexPath {  
...
if ([cell isKindOfClass:[RCMessageCell class]]) {
RCMessageCell *c = (RCMessageCell *)cell;
// Hide avatar
c.showPortrait = NO;
}
...
[super willDisplayMessageCell:cell atIndexPath:indexPath];
}

Customize Message Cell Display

Apps can override the willDisplayMessageCell method in RCConversationViewController to modify the UI before a message cell is displayed.

For example, the default read status UI for text messages in SDK's conversation page is a "checkmark" icon. To replace it with "Read" or "Unread," remove the SDK's default icon and add text labels during cell display. Apps must also monitor message status update notifications to refresh cells.

The following example demonstrates modifying a one-to-one text message cell:

  1. Override the cell display method to modify the UI:

    - (void)willDisplayMessageCell:(RCMessageBaseCell *)cell atIndexPath:(NSIndexPath *)indexPath {  
    RCMessageModel *model = [self.conversationDataRepository objectAtIndex:indexPath.row];
    if ([cell isKindOfClass:[RCTextMessageCell class]] && model.conversationType == ConversationType_PRIVATE) {
    if (model.content && (model.sentStatus == SentStatus_READ || model.sentStatus == SentStatus_SENT) && model.messageDirection == MessageDirection_SEND) {
    for (UIView *view in [((RCMessageCell *)cell).statusContentView subviews]) {
    if (view == ((RCMessageCell *)cell).messageFailedStatusView) {
    continue;
    }
    [view removeFromSuperview];
    }
    CGRect statusContentViewFrame = ((RCMessageCell *)cell).statusContentView.frame;
    UILabel *hasReadView = [[UILabel alloc] initWithFrame:CGRectMake(statusContentViewFrame.size.width-30, statusContentViewFrame.size.height-16, 30, 16)];
    hasReadView.textAlignment = NSTextAlignmentRight;
    hasReadView.font = [UIFont systemFontOfSize:12];
    hasReadView.textColor = [UIColor blackColor];
    hasReadView.tag = 1001;
    ((RCMessageCell *)cell).statusContentView.hidden = NO;
    if (model.sentStatus == SentStatus_READ) {
    hasReadView.text = @"Read";
    [((RCMessageCell *)cell).statusContentView addSubview:hasReadView];
    } else if (model.sentStatus == SentStatus_SENT) {
    hasReadView.text = @"Unread";
    [((RCMessageCell *)cell).statusContentView addSubview:hasReadView];
    }
    } else {
    UIView *tagView = [((RCMessageCell *)cell).statusContentView viewWithTag:1001];
    if (tagView) {
    [tagView removeFromSuperview];
    }
    }
    }
    }
  2. Monitor message status update notifications to refresh cells:

    [[NSNotificationCenter defaultCenter] addObserver:self  
    selector:@selector(messageCellUpdateSendingStatusEvent:)
    name:KNotificationMessageBaseCellUpdateSendingStatus
    object:nil];
    - (void)messageCellUpdateSendingStatusEvent:(NSNotification *)notification {  
    RCMessageCellNotificationModel *notifyModel = notification.object;
    if (notifyModel && ![notifyModel.actionName isEqualToString:CONVERSATION_CELL_STATUS_SEND_PROGRESS]) {
    [self reloadMessageCell:notifyModel.messageId];
    }
    }
    - (void)reloadMessageCell:(long)messageId {  
    __weak typeof(self) __weakself = self;
    dispatch_async(dispatch_get_main_queue(), ^{
    for (int i = 0; i < __weakself.conversationDataRepository.count; i++) {
    RCMessageModel *model = (__weakself.conversationDataRepository)[i];
    if (messageId == model.messageId) {
    NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];
    [__weakself hideCellReceiptView:indexPath withMessageModel:model];
    break;
    }
    }
    });
    }
    - (void)hideCellReceiptView:(NSIndexPath *)indexPath withMessageModel:(RCMessageModel *)model {  
    UICollectionViewCell *__cell = [self.conversationMessageCollectionView cellForItemAtIndexPath:indexPath];
    // If __cell is nil, the cell has been recycled. Re-dequeue a cell to fix read count flickering.
    if (__cell) {
    [self.conversationMessageCollectionView reloadItemsAtIndexPaths:@[indexPath]];
    if ([__cell isKindOfClass:[RCMessageCell class]]) {
    dispatch_async(dispatch_get_main_queue(), ^{
    ((RCMessageCell *)__cell).statusContentView.hidden = YES;
    });
    }
    }
    }

You can configure IMKit to navigate to a specific message when entering the conversation page, useful for scenarios like clicking a search result to open a conversation.

Before entering the conversation page, assign the sendTime of the target message to locatedMessageSentTime.

@property (nonatomic, assign) long long locatedMessageSentTime;  

Other Customizations

Explore more ways to customize the conversation page in these documents:

tip

Refer to IMKit's source code [RCConversationViewController.h] for more properties and methods of the RCConversationViewController class.