LiveCoreWidget is a cross-platform core component for live video streaming, delivering essential features such as hosting, audience viewing, co-hosting, and host PK. Through its widget system, this component enables real-time display of custom information within the video area—such as usernames, user levels, and PK progress bars. This guide provides step-by-step instructions for Flutter developers to quickly implement and customize dedicated video widget components using provided interfaces.Co-hosting Video Widget | PK Video Widget |
![]() | ![]() |
LiveCoreWidget enables custom view rendering through the VideoWidgetBuilder delegate. When the live room state changes—for example, when a user takes a mic seat or a PK session starts—LiveCoreWidget automatically invokes delegate methods to determine which view to display. As a developer, you implement these interface methods and return your custom Widget instances.Callback | Description | Related Business Scenario |
CoGuestWidgetBuilder | Builds the widget for audience co-hosting views. | Audience co-hosting, invite to mic |
CoHostWidgetBuilder | Builds the widget for cross-room co-hosting (host co-hosting) views. | Host co-hosting |
BattleWidgetBuilder | Builds the widget for individual users in PK scenarios (e.g., avatar, score). | Host PK |
BattleContainerWidgetBuilder | Builds the overall container for PK scenarios (e.g., background, PK score bar). | Host PK |

import 'package:flutter/material.dart';class CustomInfoWidget extends StatelessWidget {final String name;final bool isMuted;const CustomInfoWidget({super.key,required this.name,required this.isMuted,});@overrideWidget build(BuildContext context) {return Stack(children: [Text(name),if (isMuted) const Icon(Icons.mic_off),// Layout parameter code omitted here],);}}
import 'package:flutter/material.dart';class EmptySeatWidget extends StatelessWidget {const EmptySeatWidget({super.key});@overrideWidget build(BuildContext context) {return Column(mainAxisAlignment: MainAxisAlignment.center,children: const [Icon(Icons.add),Text('Invite to co-host'),// Image resource loading and layout parameter code omitted here],);}}
import 'package:flutter/material.dart';class CustomAvatarWidget extends StatelessWidget {final String avatarURL;const CustomAvatarWidget({super.key,required this.avatarURL,});@overrideWidget build(BuildContext context) {// In production, use an image loading library (e.g., CachedNetworkImage) to load avatarURLreturn Image.network(avatarURL);// Layout parameter code omitted here}}
VideoWidgetBuilder callbacks coGuestWidgetBuilder (for audience co-hosting) and coHostWidgetBuilder (for host co-hosting), returning your custom widgets as needed.coGuestWidgetBuilder callback to return the audience co-hosting video widget:import 'package:flutter/material.dart';import 'package:atomic_x_core/atomicxcore.dart';VideoWidgetBuilder(coGuestWidgetBuilder: (context, seatInfo, viewLayer) {final isUserOnSeat = seatInfo.userInfo.userID.isNotEmpty;if (viewLayer == ViewLayer.foreground) {if (isUserOnSeat) {// Occupied mic seat: return custom foreground widgetreturn CustomInfoWidget(name: seatInfo.userInfo.userName,isMuted: seatInfo.userInfo.microphoneStatus == DeviceStatus.off);} else {// Empty mic seat: return custom empty seat widgetreturn EmptySeatWidget();}} else {if (isUserOnSeat) {// User camera is off: display custom background widgetreturn CustomAvatarWidget(avatarURL: seatInfo.userInfo.avatarURL);} else {return SizedBox.shrink();}}})
coHostWidgetBuilder callback for host co-hosting video widgets:import 'package:flutter/material.dart';import 'package:atomic_x_core/atomicxcore.dart';VideoWidgetBuilder(coHostWidgetBuilder: (context, seatInfo, viewLayer) {final isUserOnSeat = seatInfo.userInfo.userID.isNotEmpty;if (viewLayer == ViewLayer.foreground) {if (isUserOnSeat) {// Return custom foreground widget; can use a style different from audience co-hostingreturn CustomInfoWidget(name: seatInfo.userInfo.userName,isMuted: seatInfo.userInfo.microphoneStatus == DeviceStatus.off);} else {// Return custom empty seat widget; can use a style different from audience co-hostingreturn EmptySeatWidget();}} else {if (isUserOnSeat) {// Return custom background widget (shown when camera is off); can use a style different from audience co-hostingreturn CustomAvatarWidget(avatarURL: seatInfo.userInfo.avatarURL);} else {return SizedBox.shrink();}}})
Parameter | Type | Description |
seatInfo | SeatInfo | Mic seat information object containing details about the user occupying the mic seat. |
seatInfo.userInfo.userName | String | The nickname of the user on the mic seat. |
seatInfo.userInfo.avatarURL | String | The avatar URL of the user on the mic seat. |
seatInfo.userInfo.microphoneStatus | DeviceStatus | The microphone status of the user on the mic seat. |
seatInfo.userInfo.cameraStatus | DeviceStatus | The camera status of the user on the mic seat. |
viewLayer | ViewLayer | View layer enum. .foreground: The foreground widget, always displayed above the video..background: The background widget, displayed below the foreground view and shown only when the user has no video stream (e.g., camera is off). Typically used to display a default avatar or placeholder image. |

import 'package:flutter/material.dart';// Example: Single-user score barclass MyBattleScoreWidget extends StatelessWidget {const MyBattleScoreWidget({super.key});@overrideWidget build(BuildContext context) {// Internal score display logicreturn const Placeholder();}}// Example: Global VS panelclass MyBattleContainer extends StatelessWidget {const MyBattleContainer({super.key});@overrideWidget build(BuildContext context) {// Internal countdown and VS animation logicreturn const Placeholder();}}
VideoWidgetBuilder, implement the remaining PK view builder methods as follows:import 'package:flutter/material.dart';import 'package:atomic_x_core/atomicxcore.dart';VideoWidgetBuilder(// Omitted coGuestWidgetBuilder / coHostWidgetBuilder for brevity...// 1. Build the PK single-user info widget (displayed above each host's video)battleWidgetBuilder: (context, seatInfo) {return MyBattleScoreWidget();},// 2. Build the PK global container widget (displayed above the entire video area)battleContainerWidgetBuilder: (context) {return MyBattleContainer();})
VideoWidgetBuilder—with your custom delegate logic—into the core live streaming workflow.LiveCoreWidget and set the VideoWidgetBuilder via the videoWidgetBuilder parameter.import 'package:flutter/material.dart';import 'package:atomic_x_core/atomicxcore.dart';class AnchorWidget extends StatefulWidget {const AnchorWidget({super.key});@overrideState<AnchorWidget> createState() => _AnchorWidgetState();}class _AnchorWidgetState extends State<AnchorWidget> {// Assume liveInfo is already obtained herefinal LiveInfo liveInfo = LiveInfo();late final LiveCoreController _liveCoreController;@overridevoid initState() {super.initState();// 1. Initialize the LiveCoreWidget controller_liveCoreController = LiveCoreController.create(CoreViewType.pushView);_liveCoreController.setLiveID(liveInfo.liveID);}@overrideWidget build(BuildContext context) {return LiveCoreWidget(// 2. Place the core video component in the parent widget and pass in the controllercontroller: _liveCoreController,// 3. Pass the VideoWidgetBuilder with your custom implementationvideoWidgetBuilder: VideoWidgetBuilder(coGuestWidgetBuilder: (context, seatInfo, viewLayer) {// Insert your coGuestWidgetBuilder implementation herereturn Placeholder();},coHostWidgetBuilder: (context, seatInfo, viewLayer) {// Insert your coHostWidgetBuilder implementation herereturn Placeholder();},battleWidgetBuilder: (context, seatInfo) {// Insert your battleWidgetBuilder implementation herereturn Placeholder();},battleContainerWidgetBuilder: (context) {// Insert your battleContainerWidgetBuilder implementation herereturn Placeholder();}));}}
CoreViewType for LiveCoreController to CoreViewType.pushView.import 'package:flutter/material.dart';import 'package:atomic_x_core/atomicxcore.dart';class AudienceWidget extends StatefulWidget {const AudienceWidget({super.key});@overrideState<AudienceWidget> createState() => _AudienceWidgetState();}class _AudienceWidgetState extends State<AudienceWidget> {// Assume liveInfo is already obtained herefinal LiveInfo liveInfo = LiveInfo();late final LiveCoreController _liveCoreController;@overridevoid initState() {super.initState();// 1. Initialize the LiveCoreWidget controller_liveCoreController = LiveCoreController.create(CoreViewType.pushView);_liveCoreController.setLiveID(liveInfo.liveID);}@overrideWidget build(BuildContext context) {return LiveCoreWidget(// 2. Place the core video component in the parent widget and pass in the controllercontroller: _liveCoreController,// 3. Pass the VideoWidgetBuilder with your custom implementationvideoWidgetBuilder: VideoWidgetBuilder(coGuestWidgetBuilder: (context, seatInfo, viewLayer) {// Insert your coGuestWidgetBuilder implementation herereturn Placeholder();},coHostWidgetBuilder: (context, seatInfo, viewLayer) {// Insert your coHostWidgetBuilder implementation herereturn Placeholder();},battleWidgetBuilder: (context, seatInfo) {// Insert your battleWidgetBuilder implementation herereturn Placeholder();},battleContainerWidgetBuilder: (context) {// Insert your battleContainerWidgetBuilder implementation herereturn Placeholder();}));}}
SeatInfo provides only basic mic seat data. If your custom widgets require real-time business data—such as countdowns or PK scores—connect your widgets to the relevant data stores in AtomicXCore.Store/Component | Function Description | API Documentation |
CoGuestStore | Audience co-hosting data: list of co-hosted users, invitation list, application list, etc. | |
CoHostStore | Host co-hosting data: list of co-hosted users, invitation list, application list, etc. | |
BattleStore | PK data: current PK info, PK user list, PK score list. |
coGuestWidgetBuilder in your VideoWidgetBuilder implementation to return your custom widget, and leave the PK-related builders unchanged..foreground) is always rendered above the video layer, ensure your CustomWidget is assigned to the .foreground layer and that its parent widget does not block user interactions.Esta página foi útil?
Você também pode entrar em contato com a Equipe de vendas ou Enviar um tíquete em caso de ajuda.
comentários