mod: 滑动手势进入/退出全屏模式
This commit is contained in:
@ -2,6 +2,7 @@ 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:flutter/services.dart';
|
||||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:media_kit/media_kit.dart';
|
import 'package:media_kit/media_kit.dart';
|
||||||
@ -15,11 +16,11 @@ import 'package:pilipala/utils/feed_back.dart';
|
|||||||
import 'package:screen_brightness/screen_brightness.dart';
|
import 'package:screen_brightness/screen_brightness.dart';
|
||||||
import 'package:volume_controller/volume_controller.dart';
|
import 'package:volume_controller/volume_controller.dart';
|
||||||
|
|
||||||
|
import 'utils/fullscreen.dart';
|
||||||
import 'widgets/backward_seek.dart';
|
import 'widgets/backward_seek.dart';
|
||||||
import 'widgets/bottom_control.dart';
|
import 'widgets/bottom_control.dart';
|
||||||
import 'widgets/common_btn.dart';
|
import 'widgets/common_btn.dart';
|
||||||
import 'widgets/forward_seek.dart';
|
import 'widgets/forward_seek.dart';
|
||||||
import 'widgets/play_pause_btn.dart';
|
|
||||||
|
|
||||||
class PLVideoPlayer extends StatefulWidget {
|
class PLVideoPlayer extends StatefulWidget {
|
||||||
final PlPlayerController controller;
|
final PlPlayerController controller;
|
||||||
@ -55,6 +56,8 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
bool _volumeIndicator = false;
|
bool _volumeIndicator = false;
|
||||||
Timer? _volumeTimer;
|
Timer? _volumeTimer;
|
||||||
|
|
||||||
|
double _distance = 0.0;
|
||||||
|
|
||||||
bool _volumeInterceptEventStream = false;
|
bool _volumeInterceptEventStream = false;
|
||||||
|
|
||||||
void onDoubleTapSeekBackward() {
|
void onDoubleTapSeekBackward() {
|
||||||
@ -142,15 +145,65 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> triggerFullScreen() async {
|
||||||
|
PlPlayerController _ = widget.controller;
|
||||||
|
if (!_.isFullScreen.value) {
|
||||||
|
/// 按照视频宽高比决定全屏方向
|
||||||
|
if (_.direction.value == 'horizontal') {
|
||||||
|
/// 进入全屏
|
||||||
|
await enterFullScreen();
|
||||||
|
// 横屏
|
||||||
|
await landScape();
|
||||||
|
} else {
|
||||||
|
// 竖屏
|
||||||
|
await verticalScreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
_.toggleFullScreen(true);
|
||||||
|
var result = await showDialog(
|
||||||
|
context: Get.context!,
|
||||||
|
useSafeArea: false,
|
||||||
|
builder: (context) => Dialog.fullscreen(
|
||||||
|
child: Scaffold(
|
||||||
|
backgroundColor: Colors.black,
|
||||||
|
appBar: AppBar(
|
||||||
|
primary: false,
|
||||||
|
toolbarHeight: 0,
|
||||||
|
backgroundColor: Colors.black,
|
||||||
|
systemOverlayStyle: SystemUiOverlayStyle.light,
|
||||||
|
),
|
||||||
|
body: SafeArea(
|
||||||
|
bottom: true,
|
||||||
|
child: PLVideoPlayer(
|
||||||
|
controller: _,
|
||||||
|
headerControl: _.headerControl,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
if (result == null) {
|
||||||
|
// 退出全屏
|
||||||
|
exitFullScreen();
|
||||||
|
await verticalScreen();
|
||||||
|
_.toggleFullScreen(false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Get.back();
|
||||||
|
exitFullScreen();
|
||||||
|
await verticalScreen();
|
||||||
|
_.toggleFullScreen(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
super.dispose();
|
|
||||||
animationController.dispose();
|
animationController.dispose();
|
||||||
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
print('🌹🌹🌹🌹🌹:33333');
|
|
||||||
final _ = widget.controller;
|
final _ = widget.controller;
|
||||||
Color colorTheme = Theme.of(context).colorScheme.primary;
|
Color colorTheme = Theme.of(context).colorScheme.primary;
|
||||||
TextStyle subTitleStyle = const TextStyle(
|
TextStyle subTitleStyle = const TextStyle(
|
||||||
@ -389,7 +442,6 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
// 双击左边区域 👈
|
// 双击左边区域 👈
|
||||||
onDoubleTapSeekBackward();
|
onDoubleTapSeekBackward();
|
||||||
} else if (tapPosition < sectionWidth * 2) {
|
} else if (tapPosition < sectionWidth * 2) {
|
||||||
print('🌹🌹🌹🌹🌹:333356555553');
|
|
||||||
if (_.playerStatus.status.value == PlayerStatus.playing) {
|
if (_.playerStatus.status.value == PlayerStatus.playing) {
|
||||||
_.togglePlay();
|
_.togglePlay();
|
||||||
} else {
|
} else {
|
||||||
@ -415,23 +467,36 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
onHorizontalDragUpdate: (DragUpdateDetails details) {},
|
onHorizontalDragUpdate: (DragUpdateDetails details) {},
|
||||||
onHorizontalDragEnd: (DragEndDetails details) {},
|
onHorizontalDragEnd: (DragEndDetails details) {},
|
||||||
// 垂直方向 音量/亮度调节
|
// 垂直方向 音量/亮度调节
|
||||||
onVerticalDragUpdate: (DragUpdateDetails details) {
|
onVerticalDragUpdate: (DragUpdateDetails details) async {
|
||||||
final totalWidth = MediaQuery.of(context).size.width;
|
final totalWidth = MediaQuery.of(context).size.width;
|
||||||
final tapPosition = details.localPosition.dx;
|
final tapPosition = details.localPosition.dx;
|
||||||
final sectionWidth = totalWidth / 3;
|
final sectionWidth = totalWidth / 3;
|
||||||
|
final delta = details.delta.dy;
|
||||||
if (tapPosition < sectionWidth) {
|
if (tapPosition < sectionWidth) {
|
||||||
// 左边区域 👈
|
// 左边区域 👈
|
||||||
final delta = details.delta.dy;
|
|
||||||
final brightness = _brightnessValue - delta / 100.0;
|
final brightness = _brightnessValue - 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) {
|
||||||
// 全屏
|
// 全屏
|
||||||
print('全屏');
|
final double dy = details.delta.dy;
|
||||||
|
const double threshold = 7.0; // 滑动阈值
|
||||||
|
if (dy > _distance && dy > threshold) {
|
||||||
|
if (!_.isFullScreen.value) {
|
||||||
|
await triggerFullScreen();
|
||||||
|
}
|
||||||
|
_distance = 0.0;
|
||||||
|
} else if (dy < _distance && dy < -threshold) {
|
||||||
|
if (_.isFullScreen.value) {
|
||||||
|
await triggerFullScreen();
|
||||||
|
}
|
||||||
|
_distance = 0.0;
|
||||||
|
}
|
||||||
|
_distance = dy;
|
||||||
|
|
||||||
|
// triggerFullScreen();
|
||||||
} else {
|
} else {
|
||||||
// 右边区域 👈
|
// 右边区域 👈
|
||||||
final delta = details.delta.dy;
|
|
||||||
final volume = _volumeValue - delta / 100.0;
|
final volume = _volumeValue - delta / 100.0;
|
||||||
final result = volume.clamp(0.0, 1.0);
|
final result = volume.clamp(0.0, 1.0);
|
||||||
setVolume(result);
|
setVolume(result);
|
||||||
@ -463,7 +528,9 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
controller: animationController,
|
controller: animationController,
|
||||||
visible: !_.controlsLock.value && _.showControls.value,
|
visible: !_.controlsLock.value && _.showControls.value,
|
||||||
position: 'bottom',
|
position: 'bottom',
|
||||||
child: BottomControl(controller: widget.controller),
|
child: BottomControl(
|
||||||
|
controller: widget.controller,
|
||||||
|
triggerFullScreen: triggerFullScreen),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -660,18 +727,3 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MSliderTrackShape extends RoundedRectSliderTrackShape {
|
|
||||||
@override
|
|
||||||
Rect getPreferredRect({
|
|
||||||
required RenderBox parentBox,
|
|
||||||
Offset offset = Offset.zero,
|
|
||||||
SliderThemeData? sliderTheme,
|
|
||||||
bool isEnabled = false,
|
|
||||||
bool isDiscrete = false,
|
|
||||||
}) {
|
|
||||||
final double trackLeft = offset.dx;
|
|
||||||
final double trackWidth = parentBox.size.width;
|
|
||||||
return Rect.fromLTWH(trackLeft, -1, trackWidth, 3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -7,7 +7,9 @@ import 'package:pilipala/plugin/pl_player/widgets/play_pause_btn.dart';
|
|||||||
|
|
||||||
class BottomControl extends StatelessWidget implements PreferredSizeWidget {
|
class BottomControl extends StatelessWidget implements PreferredSizeWidget {
|
||||||
final PlPlayerController? controller;
|
final PlPlayerController? controller;
|
||||||
const BottomControl({this.controller, Key? key}) : super(key: key);
|
final Function? triggerFullScreen;
|
||||||
|
const BottomControl({this.controller, this.triggerFullScreen, Key? key})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Size get preferredSize => const Size(double.infinity, kToolbarHeight);
|
Size get preferredSize => const Size(double.infinity, kToolbarHeight);
|
||||||
@ -136,52 +138,18 @@ class BottomControl extends StatelessWidget implements PreferredSizeWidget {
|
|||||||
// ),
|
// ),
|
||||||
// const SizedBox(width: 4),
|
// const SizedBox(width: 4),
|
||||||
// 全屏
|
// 全屏
|
||||||
Obx(() => ComBtn(
|
Obx(
|
||||||
icon: Icon(
|
() => ComBtn(
|
||||||
_.isFullScreen.value
|
icon: Icon(
|
||||||
? FontAwesomeIcons.a
|
_.isFullScreen.value
|
||||||
: FontAwesomeIcons.expand,
|
? FontAwesomeIcons.a
|
||||||
size: 15,
|
: FontAwesomeIcons.expand,
|
||||||
color: Colors.white,
|
size: 15,
|
||||||
),
|
color: Colors.white,
|
||||||
fuc: () async {
|
),
|
||||||
if (!_.isFullScreen.value) {
|
fuc: () => triggerFullScreen!(),
|
||||||
/// 按照视频宽高比决定全屏方向
|
),
|
||||||
if (_.direction.value == 'horizontal') {
|
),
|
||||||
/// 进入全屏
|
|
||||||
await enterFullScreen();
|
|
||||||
// 横屏
|
|
||||||
await landScape();
|
|
||||||
} else {
|
|
||||||
// 竖屏
|
|
||||||
await verticalScreen();
|
|
||||||
}
|
|
||||||
|
|
||||||
_.toggleFullScreen(true);
|
|
||||||
var result = await showDialog(
|
|
||||||
context: Get.context!,
|
|
||||||
builder: (context) => Dialog.fullscreen(
|
|
||||||
backgroundColor: Colors.black,
|
|
||||||
child: PLVideoPlayer(
|
|
||||||
controller: _,
|
|
||||||
headerControl: _.headerControl,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
if (result == null) {
|
|
||||||
// 退出全屏
|
|
||||||
exitFullScreen();
|
|
||||||
await verticalScreen();
|
|
||||||
_.toggleFullScreen(false);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Get.back();
|
|
||||||
exitFullScreen();
|
|
||||||
await verticalScreen();
|
|
||||||
_.toggleFullScreen(false);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
Reference in New Issue
Block a user