fix: audio null 、 播放器面板响应式优化

This commit is contained in:
guozhigq
2023-09-11 23:21:13 +08:00
parent 74ec4cccea
commit 6d2e0f2049
2 changed files with 238 additions and 221 deletions

View File

@ -317,13 +317,15 @@ class VideoDetailController extends GetxController
closestNumber = 30280; closestNumber = 30280;
} }
firstAudio = audiosList.firstWhere((e) => e.id == closestNumber); firstAudio = audiosList.firstWhere((e) => e.id == closestNumber);
} else {
firstAudio = AudioItem();
} }
} catch (err) { } catch (err) {
firstAudio = audiosList.first; firstAudio = audiosList.isNotEmpty ? audiosList.first : AudioItem();
SmartDialog.showToast('firstAudio error: $err'); SmartDialog.showToast('firstAudio error: $err');
} }
audioUrl = firstAudio!.baseUrl ?? ''; audioUrl = firstAudio.baseUrl ?? '';
// //
if (firstAudio.id != null) { if (firstAudio.id != null) {
currentAudioQa = AudioQualityCode.fromCode(firstAudio.id!)!; currentAudioQa = AudioQualityCode.fromCode(firstAudio.id!)!;

View File

@ -48,25 +48,26 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
with TickerProviderStateMixin { with TickerProviderStateMixin {
late AnimationController animationController; late AnimationController animationController;
late VideoController videoController; late VideoController videoController;
final PLVideoPlayerController _ctr = Get.put(PLVideoPlayerController());
bool _mountSeekBackwardButton = false; // bool _mountSeekBackwardButton = false;
bool _mountSeekForwardButton = false; // bool _mountSeekForwardButton = false;
bool _hideSeekBackwardButton = false; // bool _hideSeekBackwardButton = false;
bool _hideSeekForwardButton = false; // bool _hideSeekForwardButton = false;
double _brightnessValue = 0.0; // double _brightnessValue = 0.0;
bool _brightnessIndicator = false; // bool _brightnessIndicator = false;
Timer? _brightnessTimer; Timer? _brightnessTimer;
double _volumeValue = 0.0; // double _volumeValue = 0.0;
bool _volumeIndicator = false; // bool _volumeIndicator = false;
Timer? _volumeTimer; Timer? _volumeTimer;
double _distance = 0.0; double _distance = 0.0;
// 初始手指落下位置 // 初始手指落下位置
double _initTapPositoin = 0.0; double _initTapPositoin = 0.0;
bool _volumeInterceptEventStream = false; // bool _volumeInterceptEventStream = false;
Box setting = GStrorage.setting; Box setting = GStrorage.setting;
late FullScreenMode mode; late FullScreenMode mode;
@ -75,15 +76,11 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
late bool enableBackgroundPlay; late bool enableBackgroundPlay;
void onDoubleTapSeekBackward() { void onDoubleTapSeekBackward() {
setState(() { _ctr.onDoubleTapSeekBackward();
_mountSeekBackwardButton = true;
});
} }
void onDoubleTapSeekForward() { void onDoubleTapSeekForward() {
setState(() { _ctr.onDoubleTapSeekForward();
_mountSeekForwardButton = true;
});
} }
// 双击播放、暂停 // 双击播放、暂停
@ -135,12 +132,10 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
Future.microtask(() async { Future.microtask(() async {
try { try {
FlutterVolumeController.showSystemUI = true; FlutterVolumeController.showSystemUI = true;
_volumeValue = (await FlutterVolumeController.getVolume())!; _ctr.volumeValue.value = (await FlutterVolumeController.getVolume())!;
FlutterVolumeController.addListener((value) { FlutterVolumeController.addListener((value) {
if (mounted && !_volumeInterceptEventStream) { if (mounted && !_ctr.volumeInterceptEventStream.value) {
setState(() { _ctr.volumeValue.value = value;
_volumeValue = value;
});
} }
}); });
} catch (_) {} } catch (_) {}
@ -148,12 +143,10 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
Future.microtask(() async { Future.microtask(() async {
try { try {
_brightnessValue = await ScreenBrightness().current; _ctr.brightnessValue.value = await ScreenBrightness().current;
ScreenBrightness().onCurrentBrightnessChanged.listen((value) { ScreenBrightness().onCurrentBrightnessChanged.listen((value) {
if (mounted) { if (mounted) {
setState(() { _ctr.brightnessValue.value = value;
_brightnessValue = value;
});
} }
}); });
} catch (_) {} } catch (_) {}
@ -165,18 +158,14 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
FlutterVolumeController.showSystemUI = false; FlutterVolumeController.showSystemUI = false;
await FlutterVolumeController.setVolume(value); await FlutterVolumeController.setVolume(value);
} catch (_) {} } catch (_) {}
setState(() { _ctr.volumeValue.value = value;
_volumeValue = value; _ctr.volumeIndicator.value = true;
_volumeIndicator = true; _ctr.volumeInterceptEventStream.value = true;
_volumeInterceptEventStream = true;
});
_volumeTimer?.cancel(); _volumeTimer?.cancel();
_volumeTimer = Timer(const Duration(milliseconds: 200), () { _volumeTimer = Timer(const Duration(milliseconds: 200), () {
if (mounted) { if (mounted) {
setState(() { _ctr.volumeIndicator.value = false;
_volumeIndicator = false; _ctr.volumeInterceptEventStream.value = false;
_volumeInterceptEventStream = false;
});
} }
}); });
} }
@ -185,15 +174,11 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
try { try {
await ScreenBrightness().setScreenBrightness(value); await ScreenBrightness().setScreenBrightness(value);
} catch (_) {} } catch (_) {}
setState(() { _ctr.brightnessIndicator.value = true;
_brightnessIndicator = true;
});
_brightnessTimer?.cancel(); _brightnessTimer?.cancel();
_brightnessTimer = Timer(const Duration(milliseconds: 200), () { _brightnessTimer = Timer(const Duration(milliseconds: 200), () {
if (mounted) { if (mounted) {
setState(() { _ctr.brightnessIndicator.value = false;
_brightnessIndicator = false;
});
} }
}); });
widget.controller.brightness.value = value; widget.controller.brightness.value = value;
@ -322,103 +307,107 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
), ),
/// 音量🔊 控制条展示 /// 音量🔊 控制条展示
Align( Obx(
alignment: Alignment.center, () => Align(
child: AnimatedOpacity( alignment: Alignment.center,
curve: Curves.easeInOut, child: AnimatedOpacity(
opacity: _volumeIndicator ? 1.0 : 0.0, curve: Curves.easeInOut,
duration: const Duration(milliseconds: 150), opacity: _ctr.volumeIndicator.value ? 1.0 : 0.0,
child: Container( duration: const Duration(milliseconds: 150),
alignment: Alignment.center, child: Container(
decoration: BoxDecoration( alignment: Alignment.center,
color: const Color(0x88000000), decoration: BoxDecoration(
borderRadius: BorderRadius.circular(64.0), color: const Color(0x88000000),
), borderRadius: BorderRadius.circular(64.0),
height: 34.0, ),
width: 70.0, height: 34.0,
child: Row( width: 70.0,
mainAxisSize: MainAxisSize.min, child: Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ crossAxisAlignment: CrossAxisAlignment.center,
Container( children: [
height: 34.0, Container(
width: 28.0, height: 34.0,
alignment: Alignment.centerRight, width: 28.0,
child: Icon( alignment: Alignment.centerRight,
_volumeValue == 0.0 child: Icon(
? Icons.volume_off _ctr.volumeValue.value == 0.0
: _volumeValue < 0.5 ? Icons.volume_off
? Icons.volume_down : _ctr.volumeValue.value < 0.5
: Icons.volume_up, ? Icons.volume_down
color: const Color(0xFFFFFFFF), : Icons.volume_up,
size: 20.0, 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),
), ),
), ),
), Expanded(
const SizedBox(width: 6.0), child: Text(
], '${(_ctr.volumeValue.value * 100.0).round()}%',
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: 13.0,
color: Color(0xFFFFFFFF),
),
),
),
const SizedBox(width: 6.0),
],
),
), ),
), ),
), ),
), ),
/// 亮度🌞 控制条展示 /// 亮度🌞 控制条展示
Align( Obx(
alignment: Alignment.center, () => Align(
child: AnimatedOpacity( alignment: Alignment.center,
curve: Curves.easeInOut, child: AnimatedOpacity(
opacity: _brightnessIndicator ? 1.0 : 0.0, curve: Curves.easeInOut,
duration: const Duration(milliseconds: 150), opacity: _ctr.brightnessIndicator.value ? 1.0 : 0.0,
child: Container( duration: const Duration(milliseconds: 150),
alignment: Alignment.center, child: Container(
decoration: BoxDecoration( alignment: Alignment.center,
color: const Color(0x88000000), decoration: BoxDecoration(
borderRadius: BorderRadius.circular(64.0), color: const Color(0x88000000),
), borderRadius: BorderRadius.circular(64.0),
height: 34.0, ),
width: 70.0, height: 34.0,
child: Row( width: 70.0,
mainAxisSize: MainAxisSize.min, child: Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ crossAxisAlignment: CrossAxisAlignment.center,
Container( children: [
height: 30.0, Container(
width: 28.0, height: 30.0,
alignment: Alignment.centerRight, width: 28.0,
child: Icon( alignment: Alignment.centerRight,
_brightnessValue < 1.0 / 3.0 child: Icon(
? Icons.brightness_low _ctr.brightnessValue.value < 1.0 / 3.0
: _brightnessValue < 2.0 / 3.0 ? Icons.brightness_low
? Icons.brightness_medium : _ctr.brightnessValue.value < 2.0 / 3.0
: Icons.brightness_high, ? Icons.brightness_medium
color: const Color(0xFFFFFFFF), : Icons.brightness_high,
size: 18.0, 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: 2.0),
const SizedBox(width: 6.0), Expanded(
], child: Text(
'${(_ctr.brightnessValue.value * 100.0).round()}%',
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: 13.0,
color: Color(0xFFFFFFFF),
),
),
),
const SizedBox(width: 6.0),
],
),
), ),
), ),
), ),
@ -525,7 +514,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
} }
if (tapPosition < sectionWidth) { if (tapPosition < sectionWidth) {
// 左边区域 👈 // 左边区域 👈
final brightness = _brightnessValue - delta / 100.0; final brightness = _ctr.brightnessValue.value - delta / 100.0;
final result = brightness.clamp(0.0, 1.0); final result = brightness.clamp(0.0, 1.0);
setBrightness(result); setBrightness(result);
} else if (tapPosition < sectionWidth * 2) { } else if (tapPosition < sectionWidth * 2) {
@ -548,7 +537,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
_distance = dy; _distance = dy;
} else { } else {
// 右边区域 👈 // 右边区域 👈
final volume = _volumeValue - delta / 100.0; final volume = _ctr.volumeValue.value - delta / 100.0;
final result = volume.clamp(0.0, 1.0); final result = volume.clamp(0.0, 1.0);
setVolume(result); setVolume(result);
} }
@ -704,103 +693,129 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
}), }),
/// 点击 快进/快退 /// 点击 快进/快退
if (_mountSeekBackwardButton || _mountSeekForwardButton) Obx(
Positioned.fill( () => Visibility(
child: Row( visible: _ctr.mountSeekBackwardButton.value ||
children: [ _ctr.mountSeekForwardButton.value,
Expanded( child: Positioned.fill(
child: _mountSeekBackwardButton child: Row(
? TweenAnimationBuilder<double>( children: [
tween: Tween<double>( Expanded(
begin: 0.0, child: _ctr.mountSeekBackwardButton.value
end: _hideSeekBackwardButton ? 0.0 : 1.0, ? TweenAnimationBuilder<double>(
), tween: Tween<double>(
duration: const Duration(milliseconds: 500), begin: 0.0,
builder: (context, value, child) => Opacity( end:
opacity: value, _ctr.hideSeekBackwardButton.value ? 0.0 : 1.0,
child: child, ),
), duration: const Duration(milliseconds: 500),
onEnd: () { builder: (context, value, child) => Opacity(
if (_hideSeekBackwardButton) { opacity: value,
setState(() { child: child,
_hideSeekBackwardButton = false; ),
_mountSeekBackwardButton = false; onEnd: () {
}); if (_ctr.hideSeekBackwardButton.value) {
} _ctr.hideSeekBackwardButton.value = false;
}, _ctr.mountSeekBackwardButton.value = false;
child: BackwardSeekIndicator( }
onChanged: (value) {
// _seekBarDeltaValueNotifier.value = -value;
}, },
onSubmitted: (value) { child: BackwardSeekIndicator(
setState(() { onChanged: (value) {
_hideSeekBackwardButton = true; // _seekBarDeltaValueNotifier.value = -value;
}); },
Player player = onSubmitted: (value) {
widget.controller.videoPlayerController!; _ctr.hideSeekBackwardButton.value = true;
var result = player.state.position - value; Player player =
result = result.clamp( widget.controller.videoPlayerController!;
Duration.zero, var result = player.state.position - value;
player.state.duration, result = result.clamp(
); Duration.zero,
player.seek(result); player.state.duration,
widget.controller.play(); );
}, player.seek(result);
), widget.controller.play();
) },
: const SizedBox(), ),
), )
Expanded( : const SizedBox(),
child: SizedBox(
width: MediaQuery.of(context).size.width / 4,
), ),
), Expanded(
Expanded( child: SizedBox(
child: _mountSeekForwardButton width: MediaQuery.of(context).size.width / 4,
? TweenAnimationBuilder<double>( ),
tween: Tween<double>( ),
begin: 0.0, Expanded(
end: _hideSeekForwardButton ? 0.0 : 1.0, child: _ctr.mountSeekForwardButton.value
), ? TweenAnimationBuilder<double>(
duration: const Duration(milliseconds: 500), tween: Tween<double>(
builder: (context, value, child) => Opacity( begin: 0.0,
opacity: value, end: _ctr.hideSeekForwardButton.value ? 0.0 : 1.0,
child: child, ),
), duration: const Duration(milliseconds: 500),
onEnd: () { builder: (context, value, child) => Opacity(
if (_hideSeekForwardButton) { opacity: value,
setState(() { child: child,
_hideSeekForwardButton = false; ),
_mountSeekForwardButton = false; onEnd: () {
}); if (_ctr.hideSeekForwardButton.value) {
} _ctr.hideSeekForwardButton.value = false;
}, _ctr.mountSeekForwardButton.value = false;
child: ForwardSeekIndicator( }
onChanged: (value) {
// _seekBarDeltaValueNotifier.value = value;
}, },
onSubmitted: (value) { child: ForwardSeekIndicator(
setState(() { onChanged: (value) {
_hideSeekForwardButton = true; // _seekBarDeltaValueNotifier.value = value;
}); },
Player player = onSubmitted: (value) {
widget.controller.videoPlayerController!; _ctr.hideSeekForwardButton.value = true;
var result = player.state.position + value; Player player =
result = result.clamp( widget.controller.videoPlayerController!;
Duration.zero, var result = player.state.position + value;
player.state.duration, result = result.clamp(
); Duration.zero,
player.seek(result); player.state.duration,
widget.controller.play(); );
}, player.seek(result);
), widget.controller.play();
) },
: const SizedBox(), ),
), )
], : const SizedBox(),
),
],
),
), ),
), ),
),
], ],
); );
} }
} }
class PLVideoPlayerController extends GetxController {
RxBool mountSeekBackwardButton = false.obs;
RxBool mountSeekForwardButton = false.obs;
RxBool hideSeekBackwardButton = false.obs;
RxBool hideSeekForwardButton = false.obs;
RxDouble brightnessValue = 0.0.obs;
RxBool brightnessIndicator = false.obs;
RxDouble volumeValue = 0.0.obs;
RxBool volumeIndicator = false.obs;
RxDouble distance = 0.0.obs;
// 初始手指落下位置
RxDouble initTapPositoin = 0.0.obs;
RxBool volumeInterceptEventStream = false.obs;
// 双击快进 展示样式
void onDoubleTapSeekForward() {
mountSeekForwardButton.value = true;
}
void onDoubleTapSeekBackward() {
mountSeekBackwardButton.value = true;
}
}