feat: marquee title
This commit is contained in:
@ -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> {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
16
pubspec.lock
16
pubspec.lock
@ -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:
|
||||||
|
|||||||
@ -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:
|
||||||
|
|||||||
Reference in New Issue
Block a user