Skip to main content

Custom Message Items

By default, the embedded messaging UI uses a built-in message item component to display each message in the list. You can replace this with your own custom component to match your application's design or to add additional functionality.

Custom message items are rendered within the same list infrastructure as built-in items. Therefore, pagination, loading states, and scrolling work identically.

When to Use Custom Message Items

Custom message items let you:

  • Match your app's visual design language.
  • Display additional message properties.
  • Add custom interactions such as swiping actions and long-press menus.
  • Integrate with your existing component library.

Available Message Properties

Your custom component receives a view model called CustomMessageItemViewModelApi with the following properties:

PropertyTypeDescription
titleStringThe message headline
leadStringPreview text for the message
imageUrlStringURL for the thumbnail image
imageAltTextStringAlternative text for the thumbnail image
receivedAtLongTimestamp when the message was received
isNotOpenedBooleanIndicates if the user has not opened the message
isPinnedBooleanIndicates if the message is pinned
categoriesList<Category>Categories assigned to the message

An additional isSelected Boolean argument determines whether the message is currently selected.

Implementing Custom Message Items

To implement custom message items, pass a custom composable function to EmbeddedMessagingView or EmbeddedMessagingCompactView.

import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import com.sap.ec.mobileengage.embeddedmessaging.ui.item.CustomMessageItemViewModelApi
import com.sap.ec.mobileengage.embeddedmessaging.ui.EmbeddedMessagingView

@Composable
fun MessagingScreen() {
EmbeddedMessagingView(
showFilters = true,
customMessageItem = { viewModel, isSelected ->
CustomMessageItem(viewModel, isSelected)
}
)
}

@Composable
fun CompactMessagingScreen() {
EmbeddedMessagingCompactView(
onNavigate = {
// onNavigate logic
},
customMessageItem = { viewModel, isSelected ->
CustomMessageItem(viewModel, isSelected)
}
)
}

@Composable
fun CustomMessageItem(
viewModel: CustomMessageItemViewModelApi,
isSelected: Boolean
) {
Card(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp),
colors = CardDefaults.cardColors(
containerColor = if (isSelected)
MaterialTheme.colorScheme.primaryContainer
else
MaterialTheme.colorScheme.surface
)
) {
Column(modifier = Modifier.padding(16.dp)) {
Text(
text = viewModel.title,
style = MaterialTheme.typography.titleMedium,
fontWeight = if (viewModel.isNotOpened) FontWeight.Bold else FontWeight.Normal
)
Spacer(modifier = Modifier.height(4.dp))
Text(
text = viewModel.lead,
style = MaterialTheme.typography.bodyMedium,
maxLines = 2
)
if (viewModel.isPinned) {
Spacer(modifier = Modifier.height(8.dp))
Text(
text = "📌 Pinned",
style = MaterialTheme.typography.labelSmall
)
}
}
}
}

Parameters:

  • viewModel: CustomMessageItemViewModelApi - The message data.
  • isSelected: Boolean - Whether the message is currently selected.

Best Practices

  1. Handle the selected state by visually indicating when a message is selected to maintain clear user feedback.
  2. Show unread indicator by using bold text or a visual indicator for isNotOpened = true messages.
  3. Optimize image loading by considering lazy loading for better performance.
  4. Maintain accessibility by ensuring your custom component includes proper ARIA labels and keyboard navigation.
  5. Keep it clickable by ensuring your component does not block pointer events.