Customize Chat Message Bubble
When TapTalk.io framework is integrated to your app with the UI implementation method, you can add customized chat message bubbles to be used in chat.

Adding a Custom Chat Bubble

You can check the following example to add a custom bubble to your chat.
Note: To add a custom bubble, you need to implement recyclerView dependency to your app-level build.gradle file.
app module build.gradle
1
implementation 'com.android.support:recyclerview-v7:28.0.0'
Copied!

1. Create an XML layout file for the custom bubble

First, create a new XML layout resource file for your custom bubble, we will name it my_custom_bubble_layout.xml. You are free to customize the custom bubble layout as you wish. In this example, we will be using a simple image and text bubble.
my_custom_bubble_layout.xml
1
<?xml version="1.0" encoding="utf-8"?>
2
<android.support.constraint.ConstraintLayout
3
xmlns:android="http://schemas.android.com/apk/res/android"
4
xmlns:app="http://schemas.android.com/apk/res-auto"
5
xmlns:tools="http://schemas.android.com/tools"
6
android:layout_width="match_parent"
7
android:layout_height="wrap_content"
8
android:layout_marginStart="16dp"
9
android:layout_marginEnd="16dp"
10
android:layout_marginBottom="8dp"
11
android:background="@color/tapWhite">
12
13
<ImageView
14
android:id="@+id/imageView"
15
android:layout_width="match_parent"
16
android:layout_height="wrap_content"
17
android:adjustViewBounds="true"
18
android:src="@mipmap/ic_launcher"
19
app:layout_constraintTop_toTopOf="parent" />
20
21
<!--We are using TapTalk'io's default message body style for this TextView-->
22
<TextView
23
android:id="@+id/textView"
24
style="@style/tapLeftBubbleMessageBodyStyle"
25
android:layout_width="match_parent"
26
android:layout_height="wrap_content"
27
android:padding="8dp"
28
app:layout_constraintTop_toBottomOf="@id/imageView"
29
tools:text="Message body" />
30
31
</android.support.constraint.ConstraintLayout>
Copied!
my_custom_bubble_layout.xml
Note: TapTalk.io's default message bubble layouts generally have a 8dp bottom margin and no top margin.

2. Create a custom listener

In order to listen to event callbacks that happens in your custom bubble, we will create a custom interface that extends TapTalkBaseCustomInterface. We will name this interface MyCustomBubbleListener.
MyCustomBubbleListener.java
MyCustomBubbleListener.kt
1
import io.taptalk.TapTalk.Interface.TapTalkBaseCustomInterface;
2
import io.taptalk.TapTalk.Model.TAPMessageModel;
3
4
public interface MyCustomBubbleListener extends TapTalkBaseCustomInterface {
5
6
// Use this to notify that the user tapped your custom bubble
7
void onBubbleTapped(TAPMessageModel message);
8
}
Copied!
1
import io.taptalk.TapTalk.Interface.TapTalkBaseCustomInterface
2
import io.taptalk.TapTalk.Model.TAPMessageModel
3
4
interface MyCustomBubbleListener : TapTalkBaseCustomInterface {
5
6
// Use this to notify that the user tapped your custom bubble
7
fun onBubbleTapped(message: TAPMessageModel)
8
}
Copied!

3. Create a custom bubble ViewHolder

To display your custom bubble layout in a chat room, you will need to create a custom ViewHolder that extends TAPBaseChatViewHolder. We will name this class MyCustomBubbleViewHolder.
MyCustomBubbleListener.java
MyCustomBubbleListener.kt
1
import android.view.View;
2
import android.view.ViewGroup;
3
import android.widget.ImageView;
4
import android.widget.TextView;
5
6
import io.taptalk.TapTalk.Model.TAPMessageModel;
7
import io.taptalk.TapTalk.View.Adapter.TAPBaseChatViewHolder;
8
9
public class MyCustomBubbleViewHolder extends TAPBaseChatViewHolder {
10
11
private ImageView imageView;
12
private TextView textView;
13
14
private MyCustomBubbleListener listener; // The listener that you just created above will be used here
15
16
// Add MyCustomBubbleListener to the constructor parameter
17
MyCustomBubbleViewHolder(ViewGroup parent, int itemLayoutId, MyCustomBubbleListener listener) {
18
super(parent, itemLayoutId);
19
20
// Bind views on constructor
21
imageView = itemView.findViewById(R.id.imageView);
22
textView = itemView.findViewById(R.id.textView);
23
24
// Pass the listener from parameter
25
this.listener = listener;
26
}
27
28
@Override
29
protected void onBind(TAPMessageModel message, int index) {
30
super.onBind(message, index);
31
32
// Set message text
33
textView.setText(message.getBody());
34
35
// Set click listener
36
imageView.setOnClickListener(new View.OnClickListener() {
37
@Override
38
public void onClick(View view) {
39
// Trigger listener and pass the clicked message
40
listener.onBubbleTapped(message);
41
}
42
});
43
}
44
}
Copied!
1
import android.view.ViewGroup
2
import android.widget.ImageView
3
import android.widget.TextView
4
import io.taptalk.TapTalk.Model.TAPMessageModel
5
import io.taptalk.TapTalk.View.Adapter.TAPBaseChatViewHolder
6
7
class MyCustomBubbleViewHolder internal constructor(
8
parent: ViewGroup,
9
itemLayoutId: Int,
10
private val listener: MyCustomBubbleListener
11
) : TAPBaseChatViewHolder(parent, itemLayoutId) {
12
13
private val imageView: ImageView = itemView.findViewById(R.id.imageView)
14
private val textView: TextView = itemView.findViewById(R.id.textView)
15
16
override fun onBind(message: TAPMessageModel?, index: Int) {
17
super.onBind(message, index)
18
19
// Set message text
20
textView.text = message!!.body
21
22
// Pass the listener from parameter
23
imageView.setOnClickListener {
24
// Trigger listener and pass the clicked message
25
listener.onBubbleTapped(message)
26
}
27
}
28
}
Copied!

4. Create a custom bubble class

Using all the things you have created above, we will create a custom bubble class that extends TAPBaseCustomBubble. This class instance will then be added to the custom bubble list.
MyCustomBubbleClass.java
MyCustomBubbleClass.kt
1
import android.view.ViewGroup;
2
3
import io.taptalk.TapTalk.Helper.TAPBaseCustomBubble;
4
import io.taptalk.TapTalk.Model.TAPUserModel;
5
import io.taptalk.TapTalk.View.Adapter.TAPMessageAdapter;
6
7
public class MyCustomBubbleClass extends TAPBaseCustomBubble<MyCustomBubbleViewHolder, MyCustomBubbleListener> {
8
9
public MyCustomBubbleClass(int customBubbleLayoutRes, int messageType, MyCustomBubbleListener listener) {
10
super(customBubbleLayoutRes, messageType, listener);
11
}
12
13
@Override
14
public MyCustomBubbleViewHolder createCustomViewHolder(ViewGroup viewGroup, TAPMessageAdapter tapMessageAdapter, TAPUserModel tapUserModel, MyCustomBubbleListener listener) {
15
return new MyCustomBubbleViewHolder(viewGroup, getCustomBubbleLayoutRes(), listener);
16
}
17
}
Copied!
1
import android.view.ViewGroup
2
3
import io.taptalk.TapTalk.Helper.TAPBaseCustomBubble
4
import io.taptalk.TapTalk.Model.TAPUserModel
5
import io.taptalk.TapTalk.View.Adapter.TAPMessageAdapter
6
7
class MyCustomBubbleClass(
8
customBubbleLayoutRes: Int,
9
messageType: Int,
10
listener: MyCustomBubbleListener
11
) : TAPBaseCustomBubble<MyCustomBubbleViewHolder, MyCustomBubbleListener>(
12
customBubbleLayoutRes,
13
messageType,
14
listener
15
) {
16
17
override fun createCustomViewHolder(
18
viewGroup: ViewGroup,
19
tapMessageAdapter: TAPMessageAdapter,
20
tapUserModel: TAPUserModel,
21
listener: MyCustomBubbleListener
22
): MyCustomBubbleViewHolder {
23
return MyCustomBubbleViewHolder(viewGroup, customBubbleLayoutRes, listener)
24
}
25
}
Copied!

5. Add your custom bubble class

To add your custom bubble to TapTalk.io, use the TapUI class and call the addCustomBubble() method. This is typically done in your Application class, after init() has already been called.
Java
Kotlin
1
TapTalk.init(...);
2
3
// Insert the XML layout resource, message type, and your custom listener as parameter
4
TapUI.getInstance().addCustomBubble(new MyCustomBubbleClass(R.layout.my_custom_bubble_layout, 3001, new MyCustomBubbleListener() {
5
@Override
6
public void onBubbleTapped(TAPMessageModel message) {
7
// My custom bubble was tapped by user
8
}
9
}));
Copied!
1
TapTalk.init(...)
2
3
// Insert the XML layout resource, message type, and your custom listener as parameter
4
TapUI.getInstance().addCustomBubble(
5
MyCustomBubbleClass(R.layout.my_custom_bubble_layout,
6
3001,
7
object : MyCustomBubbleListener() {
8
fun onBubbleTapped(message: TAPMessageModel) {
9
// My custom bubble was tapped by user
10
}
11
})
12
)
Copied!
Note: Please note that the message type for custom bubbles should start with 3 as the prefix. For more information, check the message type page.
After completing all the steps above, your custom bubble will be ready to use.

Showing Your Custom Bubble in Chat

You can use your customized chat bubble in a chat room by constructing a custom TAPMessageModel with constructTapTalkMessageModel() method, then sending the constructed message to the chat room with sendCustomMessage(). Both methods can be accessed from the TapCoreMessageManager class.
To construct a message, you are required to have a TAPRoomModel as a parameter. You can use getPersonalChatRoom() or getGroupChatRoom() method in TapCoreChatRoomManager class to obtain a chat room model.
Below is an example to send a custom message with the steps mentioned above.
Java
Kotlin
1
// First, we will retrieve a TAPRoomModel required to construct a message
2
TapCoreChatRoomManager.getInstance().getPersonalChatRoom(RECIPIENT_USER, new TapCoreGetRoomListener() {
3
@Override
4
public void onSuccess(TAPRoomModel room) {
5
// Retrieved room data successfully, we will use this room to construct a TAPMessageModel
6
TAPMessageModel customBubbleMessage = TapCoreMessageManager.getInstance().constructTapTalkMessageModel(
7
"This is a custom message", // MESSAGE_BODY
8
room, // ROOM
9
3001, // MESSAGE_TYPE
10
null // MESSAGE_DATA
11
);
12
13
// We will then send the constructed message to its corresponding chat room
14
TapCoreMessageManager.getInstance().sendCustomMessage(customBubbleMessage, new TapCoreSendMessageListener() {
15
@Override
16
public void onSuccess(TAPMessageModel message) {
17
// Custom message was sent successfully
18
}
19
20
@Override
21
public void onError(String errorCode, String errorMessage) {
22
23
}
24
});
25
}
26
});
Copied!
1
// First, we will retrieve a TAPRoomModel required to construct a message
2
TapCoreChatRoomManager.getInstance().getPersonalChatRoom(RECIPIENT_USER, object : TapCoreGetRoomListener() {
3
override fun onSuccess(room: TAPRoomModel?) {
4
// Retrieved room data successfully, we will use this room to construct a TAPMessageModel
5
val customBubbleMessage = TapCoreMessageManager.getInstance().constructTapTalkMessageModel(
6
"This is a custom message", // MESSAGE_BODY
7
room!!, // ROOM
8
3001, // MESSAGE_TYPE
9
null // MESSAGE_DATA
10
)
11
12
// We will then send the constructed message to its corresponding chat room
13
TapCoreMessageManager.getInstance().sendCustomMessage(customBubbleMessage, object : TapCoreSendMessageListener() {
14
override fun onSuccess(message: TAPMessageModel?) {
15
// Custom message was sent successfully
16
}
17
18
override fun onError(errorCode: String?, errorMessage: String?) {
19
20
}
21
})
22
}
23
})
Copied!