feat: 音量、亮度调节
This commit is contained in:
BIN
assets/images/run-pokemon.gif
Normal file
BIN
assets/images/run-pokemon.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 45 KiB |
@ -59,6 +59,7 @@ class _VideoDetailPageState extends State<VideoDetailPage>
|
|||||||
// 当只有1p或多p未打开自动播放时,播放完成还原进度条,展示控制栏
|
// 当只有1p或多p未打开自动播放时,播放完成还原进度条,展示控制栏
|
||||||
plPlayerController!.seekTo(Duration.zero);
|
plPlayerController!.seekTo(Duration.zero);
|
||||||
plPlayerController!.onLockControl(false);
|
plPlayerController!.onLockControl(false);
|
||||||
|
plPlayerController!.videoPlayerController!.pause();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -7,3 +7,4 @@ export './models/play_status.dart';
|
|||||||
export './models/data_status.dart';
|
export './models/data_status.dart';
|
||||||
export './widgets/common_btn.dart';
|
export './widgets/common_btn.dart';
|
||||||
export './models/play_speed.dart';
|
export './models/play_speed.dart';
|
||||||
|
export './widgets/app_bar_ani.dart';
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:audio_video_progress_bar/audio_video_progress_bar.dart';
|
import 'package:audio_video_progress_bar/audio_video_progress_bar.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||||
@ -10,6 +12,8 @@ import 'package:pilipala/plugin/pl_player/models/duration.dart';
|
|||||||
import 'package:pilipala/plugin/pl_player/models/play_status.dart';
|
import 'package:pilipala/plugin/pl_player/models/play_status.dart';
|
||||||
import 'package:pilipala/plugin/pl_player/utils.dart';
|
import 'package:pilipala/plugin/pl_player/utils.dart';
|
||||||
import 'package:pilipala/utils/feed_back.dart';
|
import 'package:pilipala/utils/feed_back.dart';
|
||||||
|
import 'package:screen_brightness/screen_brightness.dart';
|
||||||
|
import 'package:volume_controller/volume_controller.dart';
|
||||||
|
|
||||||
import 'widgets/backward_seek.dart';
|
import 'widgets/backward_seek.dart';
|
||||||
import 'widgets/bottom_control.dart';
|
import 'widgets/bottom_control.dart';
|
||||||
@ -43,6 +47,16 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
bool _hideSeekBackwardButton = false;
|
bool _hideSeekBackwardButton = false;
|
||||||
bool _hideSeekForwardButton = false;
|
bool _hideSeekForwardButton = false;
|
||||||
|
|
||||||
|
double _brightnessValue = 0.0;
|
||||||
|
bool _brightnessIndicator = false;
|
||||||
|
Timer? _brightnessTimer;
|
||||||
|
|
||||||
|
double _volumeValue = 0.0;
|
||||||
|
bool _volumeIndicator = false;
|
||||||
|
Timer? _volumeTimer;
|
||||||
|
|
||||||
|
bool _volumeInterceptEventStream = false;
|
||||||
|
|
||||||
void onDoubleTapSeekBackward() {
|
void onDoubleTapSeekBackward() {
|
||||||
setState(() {
|
setState(() {
|
||||||
_mountSeekBackwardButton = true;
|
_mountSeekBackwardButton = true;
|
||||||
@ -61,6 +75,70 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
animationController = AnimationController(
|
animationController = AnimationController(
|
||||||
vsync: this, duration: const Duration(milliseconds: 300));
|
vsync: this, duration: const Duration(milliseconds: 300));
|
||||||
videoController = widget.controller.videoController!;
|
videoController = widget.controller.videoController!;
|
||||||
|
|
||||||
|
Future.microtask(() async {
|
||||||
|
try {
|
||||||
|
VolumeController().showSystemUI = false;
|
||||||
|
_volumeValue = await VolumeController().getVolume();
|
||||||
|
VolumeController().listener((value) {
|
||||||
|
if (mounted && !_volumeInterceptEventStream) {
|
||||||
|
setState(() {
|
||||||
|
_volumeValue = value;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (_) {}
|
||||||
|
});
|
||||||
|
|
||||||
|
Future.microtask(() async {
|
||||||
|
try {
|
||||||
|
_brightnessValue = await ScreenBrightness().current;
|
||||||
|
ScreenBrightness().onCurrentBrightnessChanged.listen((value) {
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {
|
||||||
|
_brightnessValue = value;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (_) {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> setVolume(double value) async {
|
||||||
|
try {
|
||||||
|
VolumeController().setVolume(value);
|
||||||
|
} catch (_) {}
|
||||||
|
setState(() {
|
||||||
|
_volumeValue = value;
|
||||||
|
_volumeIndicator = true;
|
||||||
|
_volumeInterceptEventStream = true;
|
||||||
|
});
|
||||||
|
_volumeTimer?.cancel();
|
||||||
|
_volumeTimer = Timer(const Duration(milliseconds: 200), () {
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {
|
||||||
|
_volumeIndicator = false;
|
||||||
|
_volumeInterceptEventStream = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> setBrightness(double value) async {
|
||||||
|
try {
|
||||||
|
await ScreenBrightness().setScreenBrightness(value);
|
||||||
|
} catch (_) {}
|
||||||
|
setState(() {
|
||||||
|
_brightnessIndicator = true;
|
||||||
|
});
|
||||||
|
_brightnessTimer?.cancel();
|
||||||
|
_brightnessTimer = Timer(const Duration(milliseconds: 200), () {
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {
|
||||||
|
_brightnessIndicator = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -90,25 +168,6 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
clipBehavior: Clip.hardEdge,
|
clipBehavior: Clip.hardEdge,
|
||||||
fit: StackFit.passthrough,
|
fit: StackFit.passthrough,
|
||||||
children: [
|
children: [
|
||||||
// Wrap [Video] widget with [MaterialVideoControlsTheme].
|
|
||||||
// MaterialVideoControlsTheme(
|
|
||||||
// normal: MaterialVideoControlsThemeData(
|
|
||||||
// // Modify theme options:
|
|
||||||
// buttonBarButtonSize: 24.0,
|
|
||||||
// buttonBarButtonColor: Colors.white,
|
|
||||||
// ),
|
|
||||||
// fullscreen: const MaterialVideoControlsThemeData(
|
|
||||||
// // Modify theme options:
|
|
||||||
// displaySeekBar: false,
|
|
||||||
// automaticallyImplySkipNextButton: false,
|
|
||||||
// automaticallyImplySkipPreviousButton: false,
|
|
||||||
// ),
|
|
||||||
// child: Scaffold(
|
|
||||||
// body: Video(
|
|
||||||
// controller: videoController,
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
Video(
|
Video(
|
||||||
controller: videoController,
|
controller: videoController,
|
||||||
controls: NoVideoControls,
|
controls: NoVideoControls,
|
||||||
@ -118,55 +177,267 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
padding: const EdgeInsets.all(24.0),
|
padding: const EdgeInsets.all(24.0),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(top: 20, bottom: 15),
|
/// 长按倍速
|
||||||
child: GestureDetector(
|
Obx(
|
||||||
onTap: () {
|
() => Align(
|
||||||
_.controls = !_.showControls.value;
|
alignment: Alignment.topCenter,
|
||||||
},
|
child: FractionalTranslation(
|
||||||
// onDoubleTap: () {
|
translation: const Offset(0.0, 1), // 上下偏移量(负数向上偏移)
|
||||||
// if (_.playerStatus.status.value == PlayerStatus.playing) {
|
child: AnimatedOpacity(
|
||||||
// _.togglePlay();
|
curve: Curves.easeInOut,
|
||||||
// } else {
|
opacity: _.doubleSpeedStatus.value ? 1.0 : 0.0,
|
||||||
// _.play();
|
duration: const Duration(milliseconds: 150),
|
||||||
// }
|
child: Container(
|
||||||
// },
|
alignment: Alignment.center,
|
||||||
onDoubleTapDown: (details) {
|
decoration: BoxDecoration(
|
||||||
final totalWidth = MediaQuery.of(context).size.width;
|
color: const Color(0x88000000),
|
||||||
final tapPosition = details.localPosition.dx;
|
borderRadius: BorderRadius.circular(64.0),
|
||||||
final sectionWidth = totalWidth / 3;
|
),
|
||||||
if (tapPosition < sectionWidth) {
|
height: 34.0,
|
||||||
// 双击左边区域 👈
|
width: 86.0,
|
||||||
onDoubleTapSeekBackward();
|
child: Row(
|
||||||
} else if (tapPosition < sectionWidth * 2) {
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
if (_.playerStatus.status.value == PlayerStatus.playing) {
|
children: [
|
||||||
_.togglePlay();
|
const SizedBox(width: 3),
|
||||||
} else {
|
Image.asset(
|
||||||
_.play();
|
'assets/images/run-pokemon.gif',
|
||||||
}
|
height: 20,
|
||||||
} else {
|
),
|
||||||
// 双击右边区域 👈
|
const Text(
|
||||||
onDoubleTapSeekForward();
|
'倍速中',
|
||||||
}
|
style: TextStyle(color: Colors.white, fontSize: 12),
|
||||||
},
|
),
|
||||||
onLongPressStart: (detail) {
|
const SizedBox(width: 4),
|
||||||
feedBack();
|
],
|
||||||
double currentSpeed = _.playbackSpeed;
|
),
|
||||||
_.setDoubleSpeedStatus(true);
|
),
|
||||||
_.setPlaybackSpeed(currentSpeed * 2);
|
),
|
||||||
},
|
),
|
||||||
onLongPressEnd: (details) {
|
),
|
||||||
double currentSpeed = _.playbackSpeed;
|
|
||||||
_.setDoubleSpeedStatus(false);
|
|
||||||
_.setPlaybackSpeed(currentSpeed / 2);
|
|
||||||
},
|
|
||||||
// 水平位置 快进
|
|
||||||
onHorizontalDragUpdate: (DragUpdateDetails details) {},
|
|
||||||
onHorizontalDragEnd: (DragEndDetails details) {},
|
|
||||||
// 垂直方向 音量/亮度调节
|
|
||||||
onVerticalDragUpdate: (DragUpdateDetails details) {},
|
|
||||||
onVerticalDragEnd: (DragEndDetails details) {}),
|
|
||||||
),
|
),
|
||||||
|
|
||||||
|
/// 时间进度
|
||||||
|
Obx(
|
||||||
|
() => Align(
|
||||||
|
alignment: Alignment.topCenter,
|
||||||
|
child: FractionalTranslation(
|
||||||
|
translation: const Offset(0.0, 1.0), // 上下偏移量(负数向上偏移)
|
||||||
|
child: AnimatedOpacity(
|
||||||
|
curve: Curves.easeInOut,
|
||||||
|
opacity: _.isSliderMoving.value ? 1.0 : 0.0,
|
||||||
|
duration: const Duration(milliseconds: 150),
|
||||||
|
child: Container(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: const Color(0x88000000),
|
||||||
|
borderRadius: BorderRadius.circular(64.0),
|
||||||
|
),
|
||||||
|
height: 34.0,
|
||||||
|
width: 100.0,
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Obx(() {
|
||||||
|
return Text(
|
||||||
|
_.sliderTempPosition.value.inMinutes >= 60
|
||||||
|
? printDurationWithHours(
|
||||||
|
_.sliderTempPosition.value)
|
||||||
|
: printDuration(_.sliderTempPosition.value),
|
||||||
|
style: textStyle,
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
const SizedBox(width: 2),
|
||||||
|
const Text('/', style: textStyle),
|
||||||
|
const SizedBox(width: 2),
|
||||||
|
Obx(
|
||||||
|
() => Text(
|
||||||
|
_.duration.value.inMinutes >= 60
|
||||||
|
? printDurationWithHours(_.duration.value)
|
||||||
|
: printDuration(_.duration.value),
|
||||||
|
style: textStyle,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
/// 音量🔊 控制条展示
|
||||||
|
Align(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: AnimatedOpacity(
|
||||||
|
curve: Curves.easeInOut,
|
||||||
|
opacity: _volumeIndicator ? 1.0 : 0.0,
|
||||||
|
duration: const Duration(milliseconds: 150),
|
||||||
|
child: Container(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: const Color(0x88000000),
|
||||||
|
borderRadius: BorderRadius.circular(64.0),
|
||||||
|
),
|
||||||
|
height: 34.0,
|
||||||
|
width: 70.0,
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
height: 34.0,
|
||||||
|
width: 28.0,
|
||||||
|
alignment: Alignment.centerRight,
|
||||||
|
child: Icon(
|
||||||
|
_volumeValue == 0.0
|
||||||
|
? Icons.volume_off
|
||||||
|
: _volumeValue < 0.5
|
||||||
|
? Icons.volume_down
|
||||||
|
: Icons.volume_up,
|
||||||
|
color: const Color(0xFFFFFFFF),
|
||||||
|
size: 20.0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
'${(_volumeValue * 100.0).round()}%',
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 13.0,
|
||||||
|
color: Color(0xFFFFFFFF),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 6.0),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
/// 亮度🌞 控制条展示
|
||||||
|
Align(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: AnimatedOpacity(
|
||||||
|
curve: Curves.easeInOut,
|
||||||
|
opacity: _brightnessIndicator ? 1.0 : 0.0,
|
||||||
|
duration: const Duration(milliseconds: 150),
|
||||||
|
child: Container(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: const Color(0x88000000),
|
||||||
|
borderRadius: BorderRadius.circular(64.0),
|
||||||
|
),
|
||||||
|
height: 34.0,
|
||||||
|
width: 70.0,
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
height: 30.0,
|
||||||
|
width: 28.0,
|
||||||
|
alignment: Alignment.centerRight,
|
||||||
|
child: Icon(
|
||||||
|
_brightnessValue < 1.0 / 3.0
|
||||||
|
? Icons.brightness_low
|
||||||
|
: _brightnessValue < 2.0 / 3.0
|
||||||
|
? Icons.brightness_medium
|
||||||
|
: Icons.brightness_high,
|
||||||
|
color: const Color(0xFFFFFFFF),
|
||||||
|
size: 18.0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 2.0),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
'${(_brightnessValue * 100.0).round()}%',
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 13.0,
|
||||||
|
color: Color(0xFFFFFFFF),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 6.0),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
/// 手势
|
||||||
|
Positioned.fill(
|
||||||
|
left: 16,
|
||||||
|
top: 25,
|
||||||
|
right: 15,
|
||||||
|
bottom: 15,
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
_.controls = !_.showControls.value;
|
||||||
|
},
|
||||||
|
onDoubleTapDown: (details) {
|
||||||
|
final totalWidth = MediaQuery.of(context).size.width;
|
||||||
|
final tapPosition = details.localPosition.dx;
|
||||||
|
final sectionWidth = totalWidth / 3;
|
||||||
|
if (tapPosition < sectionWidth) {
|
||||||
|
// 双击左边区域 👈
|
||||||
|
onDoubleTapSeekBackward();
|
||||||
|
} else if (tapPosition < sectionWidth * 2) {
|
||||||
|
if (_.playerStatus.status.value == PlayerStatus.playing) {
|
||||||
|
_.togglePlay();
|
||||||
|
} else {
|
||||||
|
_.play();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 双击右边区域 👈
|
||||||
|
onDoubleTapSeekForward();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onLongPressStart: (detail) {
|
||||||
|
feedBack();
|
||||||
|
double currentSpeed = _.playbackSpeed;
|
||||||
|
_.setDoubleSpeedStatus(true);
|
||||||
|
_.setPlaybackSpeed(currentSpeed * 2);
|
||||||
|
},
|
||||||
|
onLongPressEnd: (details) {
|
||||||
|
double currentSpeed = _.playbackSpeed;
|
||||||
|
_.setDoubleSpeedStatus(false);
|
||||||
|
_.setPlaybackSpeed(currentSpeed / 2);
|
||||||
|
},
|
||||||
|
// 水平位置 快进
|
||||||
|
onHorizontalDragUpdate: (DragUpdateDetails details) {},
|
||||||
|
onHorizontalDragEnd: (DragEndDetails details) {},
|
||||||
|
// 垂直方向 音量/亮度调节
|
||||||
|
onVerticalDragUpdate: (DragUpdateDetails details) {
|
||||||
|
final totalWidth = MediaQuery.of(context).size.width;
|
||||||
|
final tapPosition = details.localPosition.dx;
|
||||||
|
final sectionWidth = totalWidth / 3;
|
||||||
|
|
||||||
|
if (tapPosition < sectionWidth) {
|
||||||
|
// 左边区域 👈
|
||||||
|
final delta = details.delta.dy;
|
||||||
|
final brightness = _brightnessValue - delta / 100.0;
|
||||||
|
final result = brightness.clamp(0.0, 1.0);
|
||||||
|
setBrightness(result);
|
||||||
|
} else if (tapPosition < sectionWidth * 2) {
|
||||||
|
// 全屏
|
||||||
|
print('全屏');
|
||||||
|
} else {
|
||||||
|
// 右边区域 👈
|
||||||
|
final delta = details.delta.dy;
|
||||||
|
final volume = _volumeValue - delta / 100.0;
|
||||||
|
final result = volume.clamp(0.0, 1.0);
|
||||||
|
setVolume(result);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onVerticalDragEnd: (DragEndDetails details) {},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
// 头部、底部控制条
|
// 头部、底部控制条
|
||||||
if (_.controlsEnabled)
|
if (_.controlsEnabled)
|
||||||
Obx(
|
Obx(
|
||||||
@ -245,26 +516,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
// 长按倍速
|
|
||||||
Obx(
|
|
||||||
() => Align(
|
|
||||||
alignment: Alignment.topCenter,
|
|
||||||
child: FractionalTranslation(
|
|
||||||
translation: const Offset(0.0, 1.5), // 上下偏移量(负数向上偏移)
|
|
||||||
child: Visibility(
|
|
||||||
visible: _.doubleSpeedStatus.value,
|
|
||||||
child: const Text(
|
|
||||||
'** 倍速中 **',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 13,
|
|
||||||
backgroundColor: Color(0xaa000000),
|
|
||||||
color: Colors.white,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
// 锁
|
// 锁
|
||||||
if (_.controlsEnabled)
|
if (_.controlsEnabled)
|
||||||
Obx(
|
Obx(
|
||||||
@ -301,44 +553,8 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
return Container();
|
return Container();
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
// 时间进度
|
|
||||||
/// TDDO 样式
|
/// 点击 快进/快退
|
||||||
Obx(
|
|
||||||
() => Align(
|
|
||||||
alignment: Alignment.topCenter,
|
|
||||||
child: FractionalTranslation(
|
|
||||||
translation: const Offset(0.0, 2.5), // 上下偏移量(负数向上偏移)
|
|
||||||
child: Visibility(
|
|
||||||
visible: _.isSliderMoving.value,
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
Obx(() {
|
|
||||||
return Text(
|
|
||||||
_.sliderTempPosition.value.inMinutes >= 60
|
|
||||||
? printDurationWithHours(_.sliderTempPosition.value)
|
|
||||||
: printDuration(_.sliderTempPosition.value),
|
|
||||||
style: textStyle,
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
const SizedBox(width: 2),
|
|
||||||
const Text('/', style: textStyle),
|
|
||||||
const SizedBox(width: 2),
|
|
||||||
Obx(
|
|
||||||
() => Text(
|
|
||||||
_.duration.value.inMinutes >= 60
|
|
||||||
? printDurationWithHours(_.duration.value)
|
|
||||||
: printDuration(_.duration.value),
|
|
||||||
style: textStyle,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
// 点击 快进/快退
|
|
||||||
if (_mountSeekBackwardButton || _mountSeekForwardButton)
|
if (_mountSeekBackwardButton || _mountSeekForwardButton)
|
||||||
Positioned.fill(
|
Positioned.fill(
|
||||||
child: Row(
|
child: Row(
|
||||||
|
Reference in New Issue
Block a user