feat: marquee title

This commit is contained in:
guozhigq
2024-11-28 23:05:02 +08:00
parent fbee18755d
commit 65c9027ef3
3 changed files with 246 additions and 189 deletions

View File

@ -7,6 +7,7 @@ import 'package:flutter_smart_dialog/flutter_smart_dialog.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:hive/hive.dart'; import 'package:hive/hive.dart';
import 'package:marquee/marquee.dart';
import 'package:ns_danmaku/ns_danmaku.dart'; import 'package:ns_danmaku/ns_danmaku.dart';
import 'package:pilipala/common/widgets/drag_handle.dart'; import 'package:pilipala/common/widgets/drag_handle.dart';
import 'package:pilipala/http/user.dart'; import 'package:pilipala/http/user.dart';
@ -62,6 +63,7 @@ class _HeaderControlState extends State<HeaderControl> {
late String heroTag; late String heroTag;
late VideoIntroController videoIntroController; late VideoIntroController videoIntroController;
late VideoDetailData videoDetail; late VideoDetailData videoDetail;
DateTime initialTime = DateTime.now();
@override @override
void initState() { void initState() {
@ -108,30 +110,6 @@ class _HeaderControlState extends State<HeaderControl> {
child: Material( child: Material(
child: ListView( child: ListView(
children: [ children: [
// ListTile(
// onTap: () {},
// dense: true,
// enabled: false,
// leading:
// const Icon(Icons.network_cell_outlined, size: 20),
// title: Text('省流模式', style: titleStyle),
// subtitle: Text('低画质 减少视频缓存', style: subTitleStyle),
// trailing: Transform.scale(
// scale: 0.75,
// child: Switch(
// thumbIcon: MaterialStateProperty.resolveWith<Icon?>(
// (Set<MaterialState> states) {
// if (states.isNotEmpty &&
// states.first == MaterialState.selected) {
// return const Icon(Icons.done);
// }
// return null; // All other states will use the default thumbIcon.
// }),
// value: false,
// onChanged: (value) => {},
// ),
// ),
// ),
ListTile( ListTile(
onTap: () async { onTap: () async {
final res = await UserHttp.toViewLater( final res = await UserHttp.toViewLater(
@ -1071,6 +1049,16 @@ class _HeaderControlState extends State<HeaderControl> {
); );
} }
Stream<DateTime> _getTimeStream() {
return Stream.periodic(const Duration(seconds: 60), (count) {
return DateTime.now();
});
}
String _formatTime(DateTime dateTime) {
return '${dateTime.hour}:${dateTime.minute < 10 ? '0${dateTime.minute}' : dateTime.minute}';
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final _ = widget.controller!; final _ = widget.controller!;
@ -1086,7 +1074,55 @@ class _HeaderControlState extends State<HeaderControl> {
primary: false, primary: false,
automaticallyImplyLeading: false, automaticallyImplyLeading: false,
titleSpacing: 14, titleSpacing: 14,
title: Row( title: Column(
children: [
if (isFullScreen.value && isLandscape) ...[
Row(
children: [
const SizedBox(width: 40),
if (videoIntroController.isShowOnlineTotal)
Text(
'${videoIntroController.total.value}人正在看',
style: const TextStyle(
color: Colors.white,
fontSize: 12,
),
),
const Spacer(),
Expanded(
child: Align(
alignment: Alignment.center,
child: StreamBuilder<DateTime>(
stream: _getTimeStream(),
builder: (context, snapshot) {
if (snapshot.hasData) {
String currentTime = _formatTime(snapshot.data!);
return Text(
currentTime,
style: const TextStyle(fontSize: 12),
);
} else if (snapshot.connectionState ==
ConnectionState.waiting) {
// 如果Stream还未发出数据先显示初始获取的时间
String currentTime = _formatTime(initialTime);
return Text(
currentTime,
style: const TextStyle(fontSize: 12),
);
} else {
return const SizedBox();
}
},
),
),
),
const Spacer(),
/// TODO 网络&电量
],
),
],
Row(
children: [ children: [
ComBtn( ComBtn(
icon: const Icon( icon: const Icon(
@ -1114,31 +1150,31 @@ class _HeaderControlState extends State<HeaderControl> {
if (isFullScreen.value && if (isFullScreen.value &&
isLandscape && isLandscape &&
widget.videoType == SearchType.video) ...[ widget.videoType == SearchType.video) ...[
Column( Expanded(
crossAxisAlignment: CrossAxisAlignment.start, child: LayoutBuilder(builder: (context, constraints) {
children: [ return SizedBox(
ConstrainedBox( width: constraints.maxWidth,
constraints: const BoxConstraints(maxWidth: 200), height: 25,
child: Obx( child: Obx(
() => Text( () => Marquee(
videoIntroController.videoDetail.value.title ?? '', text: videoIntroController.videoDetail.value.title ??
style: const TextStyle( '',
color: Colors.white, style: const TextStyle(fontSize: 16),
fontSize: 16, scrollAxis: Axis.horizontal,
crossAxisAlignment: CrossAxisAlignment.center,
blankSpace: constraints.maxWidth,
velocity: 100,
pauseAfterRound: const Duration(seconds: 1),
startPadding: 0,
accelerationDuration: const Duration(seconds: 1),
accelerationCurve: Curves.linear,
decelerationDuration: const Duration(seconds: 1),
decelerationCurve: Curves.easeOut,
), ),
), ),
);
}),
), ),
),
if (videoIntroController.isShowOnlineTotal)
Text(
'${videoIntroController.total.value}人正在看',
style: const TextStyle(
color: Colors.white,
fontSize: 12,
),
)
],
)
] else ...[ ] else ...[
ComBtn( ComBtn(
icon: const Icon( icon: const Icon(
@ -1234,7 +1270,8 @@ class _HeaderControlState extends State<HeaderControl> {
if (canUsePiP) { if (canUsePiP) {
final Rational aspectRatio = Rational( final Rational aspectRatio = Rational(
widget.videoDetailCtr!.data.dash!.video!.first.width!, widget.videoDetailCtr!.data.dash!.video!.first.width!,
widget.videoDetailCtr!.data.dash!.video!.first.height!, widget
.videoDetailCtr!.data.dash!.video!.first.height!,
); );
await widget.floating!.enable(aspectRatio: aspectRatio); await widget.floating!.enable(aspectRatio: aspectRatio);
} else {} } else {}
@ -1271,6 +1308,8 @@ class _HeaderControlState extends State<HeaderControl> {
), ),
], ],
), ),
],
),
); );
} }
} }

View File

@ -497,6 +497,14 @@ packages:
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "6.2.1" version: "6.2.1"
fading_edge_scrollview:
dependency: transitive
description:
name: fading_edge_scrollview
sha256: c25c2231652ce774cc31824d0112f11f653881f43d7f5302c05af11942052031
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.0.0"
fake_async: fake_async:
dependency: transitive dependency: transitive
description: description:
@ -990,6 +998,14 @@ packages:
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "6.1.0" version: "6.1.0"
marquee:
dependency: "direct main"
description:
name: marquee
sha256: "4b5243d2804373bdc25fc93d42c3b402d6ec1f4ee8d0bb72276edd04ae7addb8"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.2.3"
matcher: matcher:
dependency: transitive dependency: transitive
description: description:

View File

@ -152,6 +152,8 @@ dependencies:
re_highlight: ^0.0.3 re_highlight: ^0.0.3
# 图片选择器 # 图片选择器
image_picker: ^1.1.2 image_picker: ^1.1.2
# 跑马灯
marquee: ^2.2.3
dev_dependencies: dev_dependencies:
flutter_test: flutter_test: