buildBottomBarSlot function
构建底部栏插槽的默认实现。 Builds the default bottom bar slot content.
监听播放状态、进度、缓冲、总时长、字幕等状态变化, 提供完整的底部播放控制栏 UI。
Listens to play state, position, buffering, duration, and subtitle state; provides the full bottom playback control bar UI.
Implementation
Widget buildBottomBarSlot(
SlotBuildContext ctx,
double width,
double height,
) {
// 监听播放状态、当前播放位置、缓冲位置、总时长、场景类型等
final listenable = Listenable.merge([
ctx.controller.playStateNotifier,
ctx.controller.currentPositionNotifier,
ctx.controller.bufferedPositionNotifier,
ctx.controller.totalDurationNotifier,
ctx.controller.externalSubtitleAvailableNotifier,
ctx.controller.showExternalSubtitleNotifier,
ctx.controller.sceneTypeNotifier,
]);
return ListenableBuilder(
listenable: listenable,
builder: (context, _) {
final sceneType = ctx.controller.sceneTypeNotifier.value;
final enableDrag = isNotSceneType(sceneType, [
SceneType.live,
SceneType.restricted,
]);
final enableSeek = isNotSceneType(sceneType, [
SceneType.live,
SceneType.restricted,
]);
// 获取播放状态
final playState = ctx.controller.playStateNotifier.value;
// 获取当前播放位置、缓冲位置、总时长
final currentPosition = ctx.controller.currentPositionNotifier.value;
final bufferedPosition = ctx.controller.bufferedPositionNotifier.value;
final totalDuration = ctx.controller.totalDurationNotifier.value;
// 初始化章节信息(章节数需 >= 2 才展示)
final chapters = ctx.controller.widgetData?.chapters ?? const [];
final chapterInfoList =
chapters.length >= 2 ? chapters : const <ChapterInfo>[];
return BottomBarWidget(
animationManager: ctx.animationManager,
controller: ctx.controller,
sceneType: sceneType,
chapterInfoList: chapterInfoList,
orientation: MediaQuery.of(context).orientation,
isPlaying: playState == FlutterAvpdef.started,
currentPosition: currentPosition,
bufferedPosition: bufferedPosition,
totalDuration: totalDuration,
onPlayIconPressed: () {
if (ctx.controller.isDraggingNotifier.value) return;
final wasVisible = ctx.animationManager.isVisible;
ctx.animationManager.toggle();
ctx.controller.controlBarVisibleNotifier.value = !wasVisible;
ctx.controller.togglePlayState();
},
onReplayIconPressed: ctx.controller.replay,
onFullScreenPressed: ctx.controller.toggleFullscreen,
onSubtitlePressed: () => _toggleSubtitleShow(
context,
ctx.controller,
),
onDragUpdate:
enableDrag ? (duration) => _onDragUpdate(ctx, duration) : null,
onDragEnd: enableDrag ? (duration) => _onDragEnd(ctx, duration) : null,
onSeekEnd:
enableSeek ? (duration) => ctx.controller.seek(duration) : null,
isShowExternalSubtitle:
ctx.controller.showExternalSubtitleNotifier.value,
isShowExternalSubtitleBtn:
ctx.controller.externalSubtitleAvailableNotifier.value,
);
},
);
}