mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-06 09:13:48 +08:00
fix: obx不能返回nil,无障碍适配
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:audio_video_progress_bar/audio_video_progress_bar.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter_volume_controller/flutter_volume_controller.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:get/get.dart';
|
||||
@@ -17,6 +17,8 @@ import 'package:PiliPalaX/utils/feed_back.dart';
|
||||
import 'package:PiliPalaX/utils/storage.dart';
|
||||
import 'package:screen_brightness/screen_brightness.dart';
|
||||
|
||||
import '../../common/widgets/audio_video_progress_bar.dart';
|
||||
import '../../utils/utils.dart';
|
||||
import 'models/bottom_progress_behavior.dart';
|
||||
import 'widgets/app_bar_ani.dart';
|
||||
import 'widgets/backward_seek.dart';
|
||||
@@ -79,6 +81,11 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
||||
DateTime? lastFullScreenToggleTime;
|
||||
// 记录上一次音量调整值作平均,避免音量调整抖动
|
||||
double lastVolume = -1.0;
|
||||
// 是否在调整固定进度条
|
||||
RxBool draggingFixedProgressBar = false.obs;
|
||||
// 阅读器限制
|
||||
Timer? _accessibilityDebounce;
|
||||
double _lastAnnouncedValue = -1;
|
||||
|
||||
void onDoubleTapSeekBackward() {
|
||||
_ctr.onDoubleTapSeekBackward();
|
||||
@@ -127,8 +134,8 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
||||
defaultValue: BtmProgresBehavior.values.first.code);
|
||||
enableQuickDouble =
|
||||
setting.get(SettingBoxKey.enableQuickDouble, defaultValue: true);
|
||||
fullScreenGestureReverse = setting.get(SettingBoxKey.fullScreenGestureReverse,
|
||||
defaultValue: false);
|
||||
fullScreenGestureReverse = setting
|
||||
.get(SettingBoxKey.fullScreenGestureReverse, defaultValue: false);
|
||||
enableBackgroundPlay =
|
||||
setting.get(SettingBoxKey.enableBackgroundPlay, defaultValue: false);
|
||||
Future.microtask(() async {
|
||||
@@ -281,10 +288,8 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
||||
children: [
|
||||
Obx(() {
|
||||
return Text(
|
||||
_.sliderTempPosition.value.inMinutes >= 60
|
||||
? printDurationWithHours(
|
||||
_.sliderTempPosition.value)
|
||||
: printDuration(_.sliderTempPosition.value),
|
||||
Utils.timeFormat(
|
||||
_.sliderTempPosition.value.inSeconds),
|
||||
style: textStyle,
|
||||
);
|
||||
}),
|
||||
@@ -439,6 +444,8 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
||||
top: 25,
|
||||
right: 15,
|
||||
bottom: 15,
|
||||
child: Semantics(
|
||||
label: '双击开关播放控件,左右滑动调整进度',
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
_.controls = !_.showControls.value;
|
||||
@@ -448,7 +455,8 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
||||
if (_.videoType.value == 'live' || _.controlsLock.value) {
|
||||
return;
|
||||
}
|
||||
RenderBox renderBox = _playerKey.currentContext!.findRenderObject() as RenderBox;
|
||||
RenderBox renderBox =
|
||||
_playerKey.currentContext!.findRenderObject() as RenderBox;
|
||||
final double totalWidth = renderBox.size.width;
|
||||
final double tapPosition = details.localPosition.dx;
|
||||
final double sectionWidth = totalWidth / 3;
|
||||
@@ -479,7 +487,8 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
||||
// final double tapPosition = details.localPosition.dx;
|
||||
final int curSliderPosition =
|
||||
_.sliderPosition.value.inMilliseconds;
|
||||
RenderBox renderBox = _playerKey.currentContext!.findRenderObject() as RenderBox;
|
||||
RenderBox renderBox =
|
||||
_playerKey.currentContext!.findRenderObject() as RenderBox;
|
||||
final double scale = 90000 / renderBox.size.width;
|
||||
final Duration pos = Duration(
|
||||
milliseconds:
|
||||
@@ -499,16 +508,17 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
||||
},
|
||||
// 垂直方向 音量/亮度调节
|
||||
onVerticalDragUpdate: (DragUpdateDetails details) async {
|
||||
RenderBox renderBox = _playerKey.currentContext!.findRenderObject() as RenderBox;
|
||||
final double totalWidth = renderBox.size.width;
|
||||
final double tapPosition = details.localPosition.dx;
|
||||
final double sectionWidth = totalWidth / 3;
|
||||
final double delta = details.delta.dy;
|
||||
RenderBox renderBox =
|
||||
_playerKey.currentContext!.findRenderObject() as RenderBox;
|
||||
|
||||
/// 锁定时禁用
|
||||
if (_.controlsLock.value) {
|
||||
return;
|
||||
}
|
||||
final double totalWidth = renderBox.size.width;
|
||||
final double tapPosition = details.localPosition.dx;
|
||||
final double sectionWidth = totalWidth / 3;
|
||||
final double delta = details.delta.dy;
|
||||
if (lastFullScreenToggleTime != null &&
|
||||
DateTime.now().difference(lastFullScreenToggleTime!) <
|
||||
const Duration(milliseconds: 500)) {
|
||||
@@ -529,6 +539,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
||||
lastFullScreenToggleTime = DateTime.now();
|
||||
await widget.controller.triggerFullScreen(status: status);
|
||||
}
|
||||
|
||||
if (dy > _distance && dy > threshold) {
|
||||
// 下滑退出全屏/进入全屏
|
||||
if (_.isFullScreen.value ^ fullScreenGestureReverse) {
|
||||
@@ -546,10 +557,11 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
||||
} else {
|
||||
// 右边区域 👈
|
||||
final double level = renderBox.size.height * 0.5;
|
||||
if(lastVolume < 0) {
|
||||
if (lastVolume < 0) {
|
||||
lastVolume = _ctr.volumeValue.value;
|
||||
}
|
||||
final double volume = (lastVolume + _ctr.volumeValue.value - delta / level)/2;
|
||||
final double volume =
|
||||
(lastVolume + _ctr.volumeValue.value - delta / level) / 2;
|
||||
final double result = volume.clamp(0.0, 1.0);
|
||||
lastVolume = result;
|
||||
setVolume(result);
|
||||
@@ -558,6 +570,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
||||
onVerticalDragEnd: (DragEndDetails details) {},
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// 头部、底部控制条
|
||||
SafeArea(
|
||||
@@ -605,28 +618,32 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
||||
}
|
||||
if (defaultBtmProgressBehavior ==
|
||||
BtmProgresBehavior.alwaysHide.code) {
|
||||
return nil;
|
||||
return Container();
|
||||
}
|
||||
if (defaultBtmProgressBehavior ==
|
||||
BtmProgresBehavior.onlyShowFullScreen.code &&
|
||||
!_.isFullScreen.value) {
|
||||
return nil;
|
||||
return Container();
|
||||
} else if (defaultBtmProgressBehavior ==
|
||||
BtmProgresBehavior.onlyHideFullScreen.code &&
|
||||
_.isFullScreen.value) {
|
||||
return nil;
|
||||
return Container();
|
||||
}
|
||||
|
||||
if (_.videoType.value == 'live') {
|
||||
return const SizedBox();
|
||||
return Container();
|
||||
}
|
||||
if (value > max || max <= 0) {
|
||||
return nil;
|
||||
return Container();
|
||||
}
|
||||
return Positioned(
|
||||
bottom: -1.5,
|
||||
bottom: -1,
|
||||
left: 0,
|
||||
right: 0,
|
||||
child: Semantics(
|
||||
// label: '${(value / max * 100).round()}%',
|
||||
value: '${(value / max * 100).round()}%',
|
||||
// enabled: false,
|
||||
child: ProgressBar(
|
||||
progress: Duration(seconds: value),
|
||||
buffered: Duration(seconds: buffer),
|
||||
@@ -637,22 +654,37 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
||||
Theme.of(context).colorScheme.primary.withOpacity(0.4),
|
||||
timeLabelLocation: TimeLabelLocation.none,
|
||||
thumbColor: colorTheme,
|
||||
barHeight: 3,
|
||||
thumbRadius: 0.0,
|
||||
// onDragStart: (duration) {
|
||||
// _.onChangedSliderStart();
|
||||
// },
|
||||
// onDragEnd: () {
|
||||
// _.onChangedSliderEnd();
|
||||
// },
|
||||
// onDragUpdate: (details) {
|
||||
// print(details);
|
||||
// },
|
||||
// onSeek: (duration) {
|
||||
// feedBack();
|
||||
// _.onChangedSlider(duration.inSeconds.toDouble());
|
||||
// _.seekTo(duration);
|
||||
// },
|
||||
barHeight: 3.5,
|
||||
thumbRadius: draggingFixedProgressBar.value ? 7 : 4,
|
||||
onDragStart: (duration) {
|
||||
draggingFixedProgressBar.value = true;
|
||||
feedBack();
|
||||
_.onChangedSliderStart();
|
||||
},
|
||||
onDragUpdate: (duration) {
|
||||
double newProgress = duration.timeStamp.inSeconds / max;
|
||||
if ((newProgress - _lastAnnouncedValue).abs() > 0.02) {
|
||||
_accessibilityDebounce?.cancel();
|
||||
_accessibilityDebounce =
|
||||
Timer(const Duration(milliseconds: 200), () {
|
||||
SemanticsService.announce(
|
||||
"${(newProgress * 100).round()}%",
|
||||
TextDirection.ltr);
|
||||
_lastAnnouncedValue = newProgress;
|
||||
});
|
||||
}
|
||||
_.onUpdatedSliderProgress(duration.timeStamp);
|
||||
},
|
||||
onSeek: (duration) {
|
||||
draggingFixedProgressBar.value = false;
|
||||
_.onChangedSliderEnd();
|
||||
_.onChangedSlider(duration.inSeconds.toDouble());
|
||||
_.seekTo(Duration(seconds: duration.inSeconds),
|
||||
type: 'slider');
|
||||
SemanticsService.announce(
|
||||
"${(duration.inSeconds / max * 100).round()}%",
|
||||
TextDirection.ltr);
|
||||
},
|
||||
),
|
||||
// SlideTransition(
|
||||
// position: Tween<Offset>(
|
||||
@@ -663,7 +695,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
||||
// curve: Curves.easeInOut,
|
||||
// )),
|
||||
// child: ),
|
||||
);
|
||||
));
|
||||
},
|
||||
),
|
||||
|
||||
@@ -678,6 +710,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
||||
child: Visibility(
|
||||
visible: _.showControls.value,
|
||||
child: ComBtn(
|
||||
tooltip: _.controlsLock.value ? '解锁' : '锁定',
|
||||
icon: Icon(
|
||||
_.controlsLock.value
|
||||
? FontAwesomeIcons.lock
|
||||
|
||||
Reference in New Issue
Block a user