Control the call layout and UI elements during an active session. These methods allow you to change the call layout, enable Picture-in-Picture mode, and update UI badges.
Prerequisites
Get CallSession Instance
Layout and UI methods are called on the CallSession singleton:
val callSession = CallSession.getInstance()
CallSession callSession = CallSession.getInstance();
Set Layout
Change the call layout during an active session.
// Switch to tile layout (grid view)
callSession.setLayout(LayoutType.TILE)
// Switch to spotlight layout (active speaker focus)
callSession.setLayout(LayoutType.SPOTLIGHT)
// Switch to sidebar layout
callSession.setLayout(LayoutType.SIDEBAR)
// Switch to tile layout (grid view)
callSession.setLayout(LayoutType.TILE);
// Switch to spotlight layout (active speaker focus)
callSession.setLayout(LayoutType.SPOTLIGHT);
// Switch to sidebar layout
callSession.setLayout(LayoutType.SIDEBAR);
LayoutType Enum
| Value | Description |
|---|
TILE | Grid layout showing all participants equally sized |
SPOTLIGHT | Focus on the active speaker with others in smaller tiles |
SIDEBAR | Main speaker with participants in a sidebar |
When the layout changes, the onCallLayoutChanged(LayoutType) callback is triggered on your LayoutListener.
Picture-in-Picture Mode
Enable Picture-in-Picture (PiP) mode to allow users to continue viewing the call while using other apps.
Enable PiP
callSession.enablePictureInPictureLayout()
callSession.enablePictureInPictureLayout();
Disable PiP
callSession.disablePictureInPictureLayout()
callSession.disablePictureInPictureLayout();
Android PiP Integration
To fully support PiP on Android, you need to handle the activity lifecycle:
class CallActivity : AppCompatActivity() {
private var isInPipMode = false
override fun onPictureInPictureModeChanged(
isInPictureInPictureMode: Boolean,
newConfig: Configuration
) {
super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig)
isInPipMode = isInPictureInPictureMode
if (isInPictureInPictureMode) {
CallSession.getInstance().enablePictureInPictureLayout()
} else {
CallSession.getInstance().disablePictureInPictureLayout()
}
}
override fun onUserLeaveHint() {
super.onUserLeaveHint()
// Enter PiP when user presses home button
if (CallSession.getInstance().isSessionActive()) {
enterPictureInPictureMode(
PictureInPictureParams.Builder()
.setAspectRatio(Rational(16, 9))
.build()
)
}
}
override fun onStop() {
super.onStop()
if (isInPipMode && !isChangingConfigurations) {
// PiP window was closed, end the call
CallSession.getInstance().leaveSession()
}
}
}
public class CallActivity extends AppCompatActivity {
private boolean isInPipMode = false;
@Override
public void onPictureInPictureModeChanged(
boolean isInPictureInPictureMode,
Configuration newConfig) {
super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig);
isInPipMode = isInPictureInPictureMode;
if (isInPictureInPictureMode) {
CallSession.getInstance().enablePictureInPictureLayout();
} else {
CallSession.getInstance().disablePictureInPictureLayout();
}
}
@Override
protected void onUserLeaveHint() {
super.onUserLeaveHint();
// Enter PiP when user presses home button
if (CallSession.getInstance().isSessionActive()) {
enterPictureInPictureMode(
new PictureInPictureParams.Builder()
.setAspectRatio(new Rational(16, 9))
.build()
);
}
}
@Override
protected void onStop() {
super.onStop();
if (isInPipMode && !isChangingConfigurations()) {
// PiP window was closed, end the call
CallSession.getInstance().leaveSession();
}
}
}
Don’t forget to add android:supportsPictureInPicture="true" to your activity in the AndroidManifest.xml.
Update the badge count on the chat button to show unread messages.
// Set unread count
callSession.setChatButtonUnreadCount(5)
// Clear unread count
callSession.setChatButtonUnreadCount(0)
// Set unread count
callSession.setChatButtonUnreadCount(5);
// Clear unread count
callSession.setChatButtonUnreadCount(0);
| Parameter | Type | Description |
|---|
count | int | Number of unread messages to display on the badge |
The chat button must be visible (hideChatButton(false)) for the badge to appear.
Listen for Layout Events
Register a LayoutListener to receive callbacks when layout changes occur:
callSession.addLayoutListener(this, object : LayoutListener {
override fun onCallLayoutChanged(layoutType: LayoutType) {
Log.d(TAG, "Layout changed to: ${layoutType.value}")
}
override fun onParticipantListVisible() {
Log.d(TAG, "Participant list is now visible")
}
override fun onParticipantListHidden() {
Log.d(TAG, "Participant list is now hidden")
}
override fun onPictureInPictureLayoutEnabled() {
Log.d(TAG, "PiP mode enabled")
}
override fun onPictureInPictureLayoutDisabled() {
Log.d(TAG, "PiP mode disabled")
}
})
callSession.addLayoutListener(this, new LayoutListener() {
@Override
public void onCallLayoutChanged(LayoutType layoutType) {
Log.d(TAG, "Layout changed to: " + layoutType.getValue());
}
@Override
public void onParticipantListVisible() {
Log.d(TAG, "Participant list is now visible");
}
@Override
public void onParticipantListHidden() {
Log.d(TAG, "Participant list is now hidden");
}
@Override
public void onPictureInPictureLayoutEnabled() {
Log.d(TAG, "PiP mode enabled");
}
@Override
public void onPictureInPictureLayoutDisabled() {
Log.d(TAG, "PiP mode disabled");
}
});
Initial Layout Settings
Configure the initial layout when joining a session:
val sessionSettings = CometChatCalls.SessionSettingsBuilder()
.setLayout(LayoutType.TILE) // Start with tile layout
.build()
SessionSettings sessionSettings = new CometChatCalls.SessionSettingsBuilder()
.setLayout(LayoutType.TILE) // Start with tile layout
.build();
Hide UI Elements
Control the visibility of various UI elements:
val sessionSettings = CometChatCalls.SessionSettingsBuilder()
// Panels
.hideControlPanel(false) // Show bottom control bar
.hideHeaderPanel(false) // Show top header bar
.hideSessionTimer(false) // Show session duration timer
// Buttons
.hideChangeLayoutButton(false) // Show layout toggle button
.hideChatButton(false) // Show chat button
.hideParticipantListButton(false) // Show participant list button
.build()
SessionSettings sessionSettings = new CometChatCalls.SessionSettingsBuilder()
// Panels
.hideControlPanel(false) // Show bottom control bar
.hideHeaderPanel(false) // Show top header bar
.hideSessionTimer(false) // Show session duration timer
// Buttons
.hideChangeLayoutButton(false) // Show layout toggle button
.hideChatButton(false) // Show chat button
.hideParticipantListButton(false) // Show participant list button
.build();
Listen for UI button clicks to implement custom behavior:
callSession.addButtonClickListener(this, object : ButtonClickListener {
override fun onChangeLayoutButtonClicked() {
Log.d(TAG, "Layout button clicked")
}
override fun onChatButtonClicked() {
Log.d(TAG, "Chat button clicked")
// Open your chat UI
}
override fun onParticipantListButtonClicked() {
Log.d(TAG, "Participant list button clicked")
}
// Other callbacks...
override fun onLeaveSessionButtonClicked() {}
override fun onRaiseHandButtonClicked() {}
override fun onShareInviteButtonClicked() {}
override fun onToggleAudioButtonClicked() {}
override fun onToggleVideoButtonClicked() {}
override fun onSwitchCameraButtonClicked() {}
override fun onRecordingToggleButtonClicked() {}
})
callSession.addButtonClickListener(this, new ButtonClickListener() {
@Override
public void onChangeLayoutButtonClicked() {
Log.d(TAG, "Layout button clicked");
}
@Override
public void onChatButtonClicked() {
Log.d(TAG, "Chat button clicked");
// Open your chat UI
}
@Override
public void onParticipantListButtonClicked() {
Log.d(TAG, "Participant list button clicked");
}
// Other callbacks...
@Override
public void onLeaveSessionButtonClicked() {}
@Override
public void onRaiseHandButtonClicked() {}
@Override
public void onShareInviteButtonClicked() {}
@Override
public void onToggleAudioButtonClicked() {}
@Override
public void onToggleVideoButtonClicked() {}
@Override
public void onSwitchCameraButtonClicked() {}
@Override
public void onRecordingToggleButtonClicked() {}
});
Next Steps