Skip to main content

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.canGoBack state to conditionally show a back button.