Embedded Integration
Embed the channel within your app's existing UI — alongside custom headers, footers, or inside a navigation structure.
With Custom Header
@Composable
fun EmbeddedChannelScreen() {
val viewModel = remember { BBChannelViewModel() }
var canGoBack by remember { mutableStateOf(false) }
Column(modifier = Modifier.fillMaxSize().background(Color.Black)) {
// Custom header
Row(
modifier = Modifier
.fillMaxWidth()
.background(Color(0xFF1A1A1A))
.padding(horizontal = 16.dp, vertical = 12.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
if (canGoBack) {
TextButton(onClick = { viewModel.goBack() }) {
Text("← Back", color = Color(0xFF00AAFF))
}
} else {
Spacer(Modifier.width(50.dp))
}
Text("Videos", color = Color.White, fontWeight = FontWeight.Bold)
TextButton(onClick = { viewModel.navigateTo("main") }) {
Text("Home", color = Color(0xFF00AAFF))
}
}
// Channel fills remaining space
BBChannelView(
channelUrl = "https://demo.bbvms.com/ch/channel_name.json",
viewModel = viewModel,
callbacks = BBChannelCallbacks(
onCanGoBackChange = { canGoBack = it }
),
modifier = Modifier.weight(1f)
)
// Footer
Text(
"Powered by Blue Billywig",
modifier = Modifier.fillMaxWidth().background(Color(0xFF1A1A1A)).padding(8.dp),
color = Color.Gray,
fontSize = 12.sp,
textAlign = TextAlign.Center
)
}
}
Dynamic Height
Give the channel a fixed height when it doesn't fill the screen:
Column(modifier = Modifier.fillMaxSize()) {
Text("Featured Content", style = MaterialTheme.typography.headlineMedium)
BBChannelView(
channelUrl = "https://demo.bbvms.com/ch/channel_name.json",
viewModel = viewModel,
callbacks = callbacks,
modifier = Modifier.height(400.dp)
)
Text("Other Content")
}
warning
A fixed-height channel is scrollable internally. The channel handles its own scrolling, so avoid nesting it inside a vertically scrollable container.
Bottom Navigation Integration
@Composable
fun MainScreen() {
var selectedTab by remember { mutableIntStateOf(0) }
Scaffold(
bottomBar = {
NavigationBar {
NavigationBarItem(
selected = selectedTab == 0,
onClick = { selectedTab = 0 },
icon = { Icon(Icons.Default.Home, "Home") },
label = { Text("Home") }
)
NavigationBarItem(
selected = selectedTab == 1,
onClick = { selectedTab = 1 },
icon = { Icon(Icons.Default.PlayArrow, "Videos") },
label = { Text("Videos") }
)
}
}
) { padding ->
Box(modifier = Modifier.padding(padding)) {
when (selectedTab) {
0 -> HomeScreen()
1 -> VideoTabScreen()
}
}
}
}
@Composable
fun VideoTabScreen() {
val viewModel = remember { BBChannelViewModel() }
BBChannelView(
channelUrl = "https://demo.bbvms.com/ch/channel_name.json",
viewModel = viewModel,
callbacks = BBChannelCallbacks(),
modifier = Modifier.fillMaxSize()
)
}
Key Points
- When you provide your own header, the channel doesn't need to handle insets — your parent layout does.
- The channel handles its own scrolling; don't nest it in a scrollable container.
- Use
viewModel.canGoBackstate to conditionally show a back button.