Recipes for using the RADChatRoom component and customizing it to suit your needs.
1. Customizing Chat Bubbles using CSS
Problem
You want customize the look of the chat bubbles using CSS. E.g. Change the shape, color, border, etc.. of the chat bubble.
Solution
You can use CSS to customize many aspects of the chat room view. You just need to override the styles of the relevant UIIDs in your application’s theme.css stylesheet.
Tip
|
You can find the "theme.css" file inside the "css" directory of your project. |
The relevant UIIDs for the chat bubbles are:
UIID | Description |
---|---|
|
The Border/Wrapper around the chat bubbles that the user posts. (I.e. on the right-hand side of the chat room view). Set background, border, padding on this UIID. |
|
The text inside the chat bubbles that the user posts. |
|
The Border/Wrapper around the chat bubbles that "other" users post. (I.e. on the left-hand side of the chat room view). Set background, border, padding on this UIID. |
|
The text inside the chat bubbles that other users post. |
|
The text inside the chat bubbles that other users post on the desktop. |
|
The text inside the chat bubbles that the user posts on the desktop. |
Changing The Bubble Color
The default shape of chat bubbles is generated by RoundRect borders. If all you want to do is change the color of the chat bubbles, then you can simply set the background color on ChatBubbleSpanLabelOwn
and ChatBubbleSpanLabelOther
.
/* Set the color of the "Other" users' chat bubbles to red */
ChatBubbleSpanLabelOther {
background-color: red;
}
/* Set text color on "Other" users' chat bubbles. */
ChatBubbleTextOther {
color: white;
}
/* Set the color of the app user's chat bubbles to green */
ChatBubbleSpanLabelOwn {
background-color: green;
}
/* Set color of app user's chat bubble text to white. */
ChatBubbleTextOwn {
color: white;
}
And the result:


Using a 9-Piece Border
For more complex chat bubble looks you may want to use a 9-piece border, as this will allow you to design any bubble you like in Photoshop, or find an existing chat bubble graphic online. For this example, we’re going to use the following images:


Copy these images into your css/images directory, and then add the following snippet into your project’s css/theme.css file:
ChatBubbleSpanLabelOther {
border-image: url(images/chat-bubble-left.png); (1)
cn1-source-dpi: 480; (2)
border-image-slice: 5% 1% 94% 5%; (3)
padding-left:1mm;
padding-right:0;
}
ChatBubbleTextOther {
margin: 2mm;
color: black;
}
ChatBubbleSpanLabelOwn {
border-image: url(images/chat-bubble-right.png);
cn1-source-dpi: 480;
border-image-slice: 5% 5% 94% 1%;
padding-right: 1mm;
padding-left:0;
}
ChatBubbleTextOwn {
color: black;
margin:2mm;
}
-
The
border-image
property specifies the image to use as the background-image. -
The
cn1-source-dpi
directive allows you to specify the "source" DPI of the image. The CSS compiler scales the image to various sizes for use on devices with different densities. The most commonly used values here are 160, 320, and 480. You can experiment with values here. A large value will result in the image appearing smaller in the app. -
The
border-image-slice
specifies how the image should be "sliced" to make the 9-piece border. These values were arrived at using trial and error. When using 4 values, they are interpreted as<top> <right> <bottom> <left>
. E.g the first value specifies the distance from the top edge to slice the image as a percentage of the image height. See the Codename One manual’s discussion on 9-piece borders for more details on this directive.
The result:

2. Disabling Swipe Left to Reveal Time Posted
Problem

By default the ChatRoomView allows users to swipe a chat bubble to the left to see the time that is was posted. In some cases this swiping behaviour may interfere with other gestures in your app, so you may wish to disable the behaviour.
Solution
Use the ChatBubbleView.USE_OVERFLOW_CONTAINER view property in your view node to disable this behaviour as follows:
import static com.codename1.rad.ui.UI.param;
...
Entity viewModel = ....;
Form f = ...;
ViewNode viewNode = new ViewNode(
param(ChatBubbleView.USE_OVERFLOW_CONTAINER, false),
// .. Other attributes in the view node...
);
ChatRoomView chatView = new ChatRoomView(viewModel, viewNode, f);
...
See the complete example code here.
Discussion
The ViewProperty is used throughout CodeRAD to add customization of components via the view node hierarchy. Generally components will declare the view properties that they support in their javadocs, as public static final properties. That is how the USE_OVERFLOW_CONTAINER
property is defined in the ChatBubbleView
component. This particular view property allows us to "switch" off the swipe left behaviour in the chat room.
Further Reading
3. Using An Entity for The "Posted By" Property of Chat Message
Problem
You want to use an Entity for the ChatMessage.creator
property in your chat message view model, rather than just incorporating "icon" and "posted by" string properties directly.
Solution
Note
|
The Getting Started Tutorial uses the reference class ChatBubbleView.ViewModel as the view model for its chat bubbles. This recipe assumes that you’re already using a custom entity class for your Chat message view model. This class may look something like: A sample view model for a ChatMessage.
|
First, let’s change this view model to use an entity for the creator
instead of a string. I.e., change:
string(ChatMessage.icon);
string(ChatMessage.creator);
to
entity(ChatAccount.class, ChatMessage.creator);
This says that the "creator" property will be an Entity of type ChatAccount
. ChatAccount will be another customer view model class that we’ll create next which encapsulates an account in your chat app.
package com.codename1.cn1chat;
import com.codename1.rad.models.Entity;
import com.codename1.rad.models.EntityType;
import static com.codename1.rad.models.EntityType.tags;
import com.codename1.rad.models.StringProperty;
import com.codename1.rad.schemas.Person;
import com.codename1.rad.schemas.Thing;
/**
* View model for an account profile.
* @author shannah
*/
public class ChatAccount extends Entity {
private static final EntityType TYPE = new EntityType() {{
name = string(Thing.name); (1)
thumbnailUrl = string(Thing.thumbnailUrl); (2)
phone = string(Person.telephone); (3)
}};
{
setEntityType(TYPE);
}
public ChatAccount(String nm, String thumb, String phoneNum) { (4)
set(name, nm);
set(thumbnailUrl, thumb);
set(phone, phoneNum);
}
}
-
We use the
Thing.name
tag for the field that stores the user name. -
We use the
Thing.thumbnailUrl
tag for the field that stores the avatar. -
We add a telephone field here as an example of one of the extra metadata fields that you may want to use.
Tip
|
For the ChatAccount entity, we use mostly tags from the Person schema. Though we are referencing Thing.name and Thing.thumbnailUrl, these could have equivalently been referenced as Person.name and Person.thumbnailUrl since Thing is a super-interface of Person and all fields are inherited.
|
After this adjustment, you’ll need to make a few changes to your app in places where you interact with the view model. In the Adding Text Messages from other users section of the Getting Started Tutorial, we created demo messages using the following method:
// Create a single demo message
private Entity createDemoMessage(String text,
Date datePosted,
String participant,
String iconUrl) {
ChatBubbleView.ViewModel msg = new ChatBubbleView.ViewModel();
msg.messageText(text)
.date(datePosted)
.iconUrl(iconUrl)
.isOwn(participant == null);
if (participant != null) {
msg.postedBy(participant);
}
return msg;
}
Let’s change this method to accept a ChatAccount
object instead of the name and icon Url of the participant. At the same time, we’ll update it to use our custom view model for the demo message.
private Entity createDemoMessage(String text, Date datePosted, ChatAccount participant) {
ChatMessageModel msg = new ChatMessageModel();
msg.set(ChatMessage.text, text);
msg.set(ChatMessage.datePublished, datePosted);
msg.set(ChatMessage.creator, participant);
msg.set(ChatMessage.isOwnMessage, participant == null);
return msg;
}
The following is the method that creates the view model for my demo chat room. It demostrates how our view models are used:
private Entity createViewModel() {
String georgeThumb = "https://weblite.ca/cn1tests/radchat/george.jpg";
String kramerThumb = "https://weblite.ca/cn1tests/radchat/kramer.jpg";
ChatAccount george = new ChatAccount("George", georgeThumb, "712-555-1234");
ChatAccount kramer = new ChatAccount("Kramer", kramerThumb, null);
ChatRoomView.ViewModel room = new ChatRoomView.ViewModel();
long SECOND = 1000l;
long MINUTE = SECOND * 60;
long HOUR = MINUTE * 60;
long DAY = HOUR * 24;
long t = System.currentTimeMillis() - 2 * DAY;
room.addMessages(createDemoMessage("Why couldn't you have made me an architect? You know I always wanted to pretend that I was an architect. "
+ "Well I'm supposed to see her tomorrow, I'm gonna tell her what's goin on. Maybe she likes me for me.",
new Date(t), george));
t += HOUR;
room.addMessages(createDemoMessage("Hey", new Date(t),kramer));
t += MINUTE;
room.addMessages(createDemoMessage("Hey", new Date(t), null));
Entity vm = createDemoMessage("Hey ya want these? I don't want em!", new Date(t), kramer);
vm.setText(ChatMessage.attachmentPlaceholderImage, "https://weblite.ca/cn1tests/radchat/golf-clubs.jpg");
room.addMessages(vm);
room.addParticipants(george, kramer);
return room;
}