mod: 视频播放器重构 - 基本功能

This commit is contained in:
guozhigq
2023-07-30 22:44:18 +08:00
parent ca12be5373
commit 636ff2b9ad
31 changed files with 1583 additions and 390 deletions

View File

@ -0,0 +1,57 @@
import 'package:flutter/material.dart';
class AppBarAni extends StatelessWidget implements PreferredSizeWidget {
const AppBarAni({
required this.child,
required this.controller,
required this.visible,
this.position,
Key? key,
}) : super(key: key);
final PreferredSizeWidget child;
final AnimationController controller;
final bool visible;
final String? position;
@override
Size get preferredSize => child.preferredSize;
@override
Widget build(BuildContext context) {
visible ? controller.reverse() : controller.forward();
return SlideTransition(
position: Tween<Offset>(
begin: Offset.zero,
end: Offset(0, position! == 'top' ? -1 : 1),
).animate(CurvedAnimation(
parent: controller,
curve: Curves.linear,
)),
child: Container(
decoration: BoxDecoration(
gradient: position! == 'top'
? const LinearGradient(
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
colors: <Color>[
Colors.transparent,
Colors.black54,
],
tileMode: TileMode.mirror,
)
: const LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: <Color>[
Colors.transparent,
Colors.black54,
],
tileMode: TileMode.mirror,
),
),
child: child,
),
);
}
}

View File

@ -0,0 +1,149 @@
import 'package:audio_video_progress_bar/audio_video_progress_bar.dart';
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:get/get.dart';
import 'package:pilipala/plugin/pl_player/index.dart';
import '../utils.dart';
import 'common_btn.dart';
class BottomControl extends StatelessWidget implements PreferredSizeWidget {
final PlPlayerController? controller;
const BottomControl({this.controller, Key? key}) : super(key: key);
@override
Size get preferredSize => const Size(double.infinity, kToolbarHeight);
@override
Widget build(BuildContext context) {
Color colorTheme = Theme.of(context).colorScheme.primary;
final _ = controller!;
const textStyle = TextStyle(
color: Colors.white,
fontSize: 12,
);
return AppBar(
backgroundColor: Colors.transparent,
foregroundColor: Colors.white,
elevation: 0,
scrolledUnderElevation: 0,
primary: false,
toolbarHeight: 73,
automaticallyImplyLeading: false,
titleSpacing: 14,
title: Column(
children: [
const SizedBox(height: 23),
Obx(
() {
final int value = _.sliderPosition.value.inSeconds;
final int max = _.duration.value.inSeconds;
final int buffer = _.buffered.value.inSeconds;
if (value > max || max <= 0) {
return Container();
}
return ProgressBar(
progress: Duration(seconds: value),
buffered: Duration(seconds: buffer),
total: Duration(seconds: max),
progressBarColor: colorTheme,
baseBarColor: Colors.white.withOpacity(0.2),
bufferedBarColor: colorTheme.withOpacity(0.4),
timeLabelLocation: TimeLabelLocation.none,
thumbColor: colorTheme,
barHeight: 3.0,
thumbRadius: 5.5,
onDragStart: (duration) {
_.onChangedSliderStart();
},
onSeek: (duration) {
_.onChangedSliderEnd();
_.onChangedSlider(duration.inSeconds.toDouble());
_.seekTo(Duration(seconds: duration.inSeconds));
},
);
},
),
Row(
children: [
Obx(
() => ComBtn(
icon: Icon(
_.playerStatus.paused
? FontAwesomeIcons.play
: _.playerStatus.playing
? FontAwesomeIcons.pause
: FontAwesomeIcons.rotateRight,
size: 15,
color: Colors.white,
),
fuc: () => _.togglePlay(),
),
),
const SizedBox(width: 6),
// 播放时间
Obx(() {
return Text(
_.duration.value.inMinutes >= 60
? printDurationWithHours(_.position.value)
: printDuration(_.position.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,
),
),
const Spacer(),
// 倍速
Obx(
() => SizedBox(
width: 45,
height: 34,
child: TextButton(
style: ButtonStyle(
padding: MaterialStateProperty.all(EdgeInsets.zero),
),
onPressed: () {
_.togglePlaybackSpeed();
},
child: Text(
'${_.playbackSpeed.toString()}X',
style: textStyle,
),
),
),
),
ComBtn(
icon: const Icon(
Icons.fit_screen_sharp,
size: 18,
color: Colors.white,
),
fuc: () => _.toggleVideoFit(),
),
const SizedBox(width: 4),
// 全屏
ComBtn(
icon: const Icon(
FontAwesomeIcons.expand,
size: 15,
color: Colors.white,
),
fuc: () => {},
),
],
),
],
),
);
}
}

View File

@ -0,0 +1,29 @@
import 'package:flutter/material.dart';
class ComBtn extends StatelessWidget {
final Widget? icon;
final Function? fuc;
const ComBtn({
this.icon,
this.fuc,
super.key,
});
@override
Widget build(BuildContext context) {
return SizedBox(
width: 34,
height: 34,
child: IconButton(
style: ButtonStyle(
padding: MaterialStateProperty.all(EdgeInsets.zero),
),
onPressed: () {
fuc!();
},
icon: icon!,
),
);
}
}

View File

@ -0,0 +1,67 @@
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:get/get.dart';
import 'package:pilipala/plugin/pl_player/index.dart';
import 'common_btn.dart';
class HeaderControl extends StatelessWidget implements PreferredSizeWidget {
final PlPlayerController? controller;
const HeaderControl({this.controller, Key? key}) : super(key: key);
@override
Size get preferredSize => const Size(double.infinity, kToolbarHeight);
@override
Widget build(BuildContext context) {
final _ = controller!;
return AppBar(
backgroundColor: Colors.transparent,
foregroundColor: Colors.white,
elevation: 0,
scrolledUnderElevation: 0,
primary: false,
centerTitle: false,
automaticallyImplyLeading: false,
titleSpacing: 14,
title: Row(
children: [
ComBtn(
icon: const Icon(
FontAwesomeIcons.arrowLeft,
size: 15,
color: Colors.white,
),
fuc: () => Get.back(),
),
const SizedBox(width: 4),
ComBtn(
icon: const Icon(
FontAwesomeIcons.house,
size: 15,
color: Colors.white,
),
fuc: () => Get.back(),
),
const Spacer(),
ComBtn(
icon: const Icon(
FontAwesomeIcons.cropSimple,
size: 15,
color: Colors.white,
),
fuc: () => _.screenshot(),
),
const SizedBox(width: 4),
ComBtn(
icon: const Icon(
FontAwesomeIcons.sliders,
size: 15,
color: Colors.white,
),
fuc: () => _.screenshot(),
),
],
),
);
}
}