mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-20 00:56:31 +08:00
opt marquee
Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
@@ -3,47 +3,34 @@ import 'package:flutter/rendering.dart';
|
|||||||
import 'package:flutter/scheduler.dart';
|
import 'package:flutter/scheduler.dart';
|
||||||
|
|
||||||
class MarqueeText extends StatelessWidget {
|
class MarqueeText extends StatelessWidget {
|
||||||
final double maxWidth;
|
|
||||||
final String text;
|
final String text;
|
||||||
final TextStyle? style;
|
final TextStyle? style;
|
||||||
final double spacing;
|
final double spacing;
|
||||||
final double velocity;
|
final double velocity;
|
||||||
|
final MarqueeController? controller;
|
||||||
|
|
||||||
const MarqueeText(
|
const MarqueeText(
|
||||||
this.text, {
|
this.text, {
|
||||||
super.key,
|
super.key,
|
||||||
required this.maxWidth,
|
|
||||||
this.style,
|
this.style,
|
||||||
this.spacing = 0,
|
this.spacing = 0,
|
||||||
this.velocity = 25,
|
this.velocity = 25,
|
||||||
|
this.controller,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final textPainter = TextPainter(
|
return NormalMarquee(
|
||||||
text: TextSpan(
|
velocity: velocity,
|
||||||
text: text,
|
spacing: spacing,
|
||||||
|
controller: controller,
|
||||||
|
child: Text(
|
||||||
|
text,
|
||||||
style: style,
|
style: style,
|
||||||
|
maxLines: 1,
|
||||||
|
textDirection: TextDirection.ltr,
|
||||||
),
|
),
|
||||||
textDirection: TextDirection.ltr,
|
|
||||||
maxLines: 1,
|
|
||||||
)..layout();
|
|
||||||
final width = textPainter.width;
|
|
||||||
final child = Text(
|
|
||||||
text,
|
|
||||||
style: style,
|
|
||||||
maxLines: 1,
|
|
||||||
textDirection: TextDirection.ltr,
|
|
||||||
);
|
);
|
||||||
if (width > maxWidth) {
|
|
||||||
return NormalMarquee(
|
|
||||||
velocity: velocity,
|
|
||||||
spacing: spacing,
|
|
||||||
child: child,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return child;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,6 +39,7 @@ abstract class Marquee extends SingleChildRenderObjectWidget {
|
|||||||
final Clip clipBehavior;
|
final Clip clipBehavior;
|
||||||
final double spacing;
|
final double spacing;
|
||||||
final double velocity;
|
final double velocity;
|
||||||
|
final MarqueeController? controller;
|
||||||
|
|
||||||
const Marquee({
|
const Marquee({
|
||||||
super.key,
|
super.key,
|
||||||
@@ -60,6 +48,7 @@ abstract class Marquee extends SingleChildRenderObjectWidget {
|
|||||||
this.direction = Axis.horizontal,
|
this.direction = Axis.horizontal,
|
||||||
this.clipBehavior = Clip.hardEdge,
|
this.clipBehavior = Clip.hardEdge,
|
||||||
this.spacing = 0,
|
this.spacing = 0,
|
||||||
|
this.controller,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -83,6 +72,7 @@ class NormalMarquee extends Marquee {
|
|||||||
super.direction,
|
super.direction,
|
||||||
super.clipBehavior,
|
super.clipBehavior,
|
||||||
super.spacing,
|
super.spacing,
|
||||||
|
super.controller,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -91,6 +81,7 @@ class NormalMarquee extends Marquee {
|
|||||||
velocity: velocity,
|
velocity: velocity,
|
||||||
clipBehavior: clipBehavior,
|
clipBehavior: clipBehavior,
|
||||||
spacing: spacing,
|
spacing: spacing,
|
||||||
|
controller: controller,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,6 +111,7 @@ abstract class MarqueeRender extends RenderBox
|
|||||||
required double velocity,
|
required double velocity,
|
||||||
required double spacing,
|
required double spacing,
|
||||||
required this.clipBehavior,
|
required this.clipBehavior,
|
||||||
|
this.controller,
|
||||||
}) : _spacing = spacing,
|
}) : _spacing = spacing,
|
||||||
_velocity = velocity,
|
_velocity = velocity,
|
||||||
_direction = direction,
|
_direction = direction,
|
||||||
@@ -127,6 +119,8 @@ abstract class MarqueeRender extends RenderBox
|
|||||||
|
|
||||||
Clip clipBehavior;
|
Clip clipBehavior;
|
||||||
|
|
||||||
|
MarqueeController? controller;
|
||||||
|
|
||||||
Axis _direction;
|
Axis _direction;
|
||||||
Axis get direction => _direction;
|
Axis get direction => _direction;
|
||||||
set direction(Axis value) {
|
set direction(Axis value) {
|
||||||
@@ -140,7 +134,7 @@ abstract class MarqueeRender extends RenderBox
|
|||||||
if (_velocity == value) return;
|
if (_velocity == value) return;
|
||||||
_velocity = value;
|
_velocity = value;
|
||||||
_simulation = _simulation?.copyWith(initialValue: _delta, velocity: value);
|
_simulation = _simulation?.copyWith(initialValue: _delta, velocity: value);
|
||||||
ticker?.reset();
|
controller?.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
double _spacing;
|
double _spacing;
|
||||||
@@ -155,7 +149,7 @@ abstract class MarqueeRender extends RenderBox
|
|||||||
addSize: value - _spacing,
|
addSize: value - _spacing,
|
||||||
);
|
);
|
||||||
_spacing = value;
|
_spacing = value;
|
||||||
ticker?.reset();
|
controller?.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
double _delta = 0;
|
double _delta = 0;
|
||||||
@@ -167,27 +161,18 @@ abstract class MarqueeRender extends RenderBox
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void detach() {
|
void detach() {
|
||||||
ticker?.stop();
|
controller?.dispose();
|
||||||
super.detach();
|
super.detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
void attach(PipelineOwner owner) {
|
|
||||||
super.attach(owner);
|
|
||||||
ticker?.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
ticker?.dispose();
|
controller?.dispose();
|
||||||
ticker = null;
|
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
late double _distance;
|
late double _distance;
|
||||||
|
|
||||||
Ticker? ticker;
|
|
||||||
|
|
||||||
_MarqueeSimulation? _simulation;
|
_MarqueeSimulation? _simulation;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -218,10 +203,11 @@ abstract class MarqueeRender extends RenderBox
|
|||||||
|
|
||||||
if (_distance > 0) {
|
if (_distance > 0) {
|
||||||
updateSize();
|
updateSize();
|
||||||
ticker ??= Ticker(_onTick)..start();
|
(controller ??= MarqueeController())
|
||||||
|
..ticker ??= Ticker(_onTick)
|
||||||
|
..initStart();
|
||||||
} else {
|
} else {
|
||||||
ticker?.dispose();
|
controller?.dispose();
|
||||||
ticker = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -292,6 +278,7 @@ class _NormalMarqueeRender extends MarqueeRender {
|
|||||||
required super.velocity,
|
required super.velocity,
|
||||||
required super.clipBehavior,
|
required super.clipBehavior,
|
||||||
required super.spacing,
|
required super.spacing,
|
||||||
|
super.controller,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -395,3 +382,37 @@ extension on Ticker {
|
|||||||
..start();
|
..start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class MarqueeController {
|
||||||
|
MarqueeController({this.autoStart = true});
|
||||||
|
bool autoStart;
|
||||||
|
|
||||||
|
Ticker? ticker;
|
||||||
|
|
||||||
|
void initStart() {
|
||||||
|
if (autoStart) {
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void start() {
|
||||||
|
if (ticker != null) {
|
||||||
|
if (!ticker!.isTicking) {
|
||||||
|
ticker!.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void stop() {
|
||||||
|
ticker?.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset() {
|
||||||
|
ticker?.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void dispose() {
|
||||||
|
ticker?.dispose();
|
||||||
|
ticker = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -80,8 +80,9 @@ class _MusicDetailPageState extends CommonDynPageState<MusicDetailPage> {
|
|||||||
children: [
|
children: [
|
||||||
NetworkImgLayer(
|
NetworkImgLayer(
|
||||||
src: info.data.mvCover,
|
src: info.data.mvCover,
|
||||||
width: 40,
|
width: 36,
|
||||||
height: 40,
|
height: 36,
|
||||||
|
type: ImageType.avatar,
|
||||||
),
|
),
|
||||||
Text(info.data.musicTitle!),
|
Text(info.data.musicTitle!),
|
||||||
],
|
],
|
||||||
@@ -456,7 +457,7 @@ class _MusicDetailPageState extends CommonDynPageState<MusicDetailPage> {
|
|||||||
behavior: HitTestBehavior.opaque,
|
behavior: HitTestBehavior.opaque,
|
||||||
child: MarqueeText(
|
child: MarqueeText(
|
||||||
item.musicTitle!,
|
item.musicTitle!,
|
||||||
maxWidth: maxWidth - 136, // 80 + 16 + 32 + 8
|
spacing: 30,
|
||||||
style: textTheme.titleMedium,
|
style: textTheme.titleMedium,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -114,8 +114,9 @@ class MusicVideoCardH extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 3),
|
const SizedBox(height: 3),
|
||||||
BounceMarquee(
|
NormalMarquee(
|
||||||
velocity: 25,
|
velocity: 25,
|
||||||
|
spacing: 30,
|
||||||
child: Row(
|
child: Row(
|
||||||
spacing: 8,
|
spacing: 8,
|
||||||
children: [
|
children: [
|
||||||
|
|||||||
@@ -83,6 +83,9 @@ class HeaderControlState extends TripleState<HeaderControl> {
|
|||||||
Timer? clock;
|
Timer? clock;
|
||||||
bool get isFullScreen => plPlayerController.isFullScreen.value;
|
bool get isFullScreen => plPlayerController.isFullScreen.value;
|
||||||
Box setting = GStorage.setting;
|
Box setting = GStorage.setting;
|
||||||
|
MarqueeController? marqueeController;
|
||||||
|
MarqueeController get _marqueeController =>
|
||||||
|
marqueeController ??= MarqueeController(autoStart: false);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@@ -97,6 +100,8 @@ class HeaderControlState extends TripleState<HeaderControl> {
|
|||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
clock?.cancel();
|
clock?.cancel();
|
||||||
|
marqueeController?.dispose();
|
||||||
|
marqueeController = null;
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1911,35 +1916,30 @@ class HeaderControlState extends TripleState<HeaderControl> {
|
|||||||
padding: isPortrait
|
padding: isPortrait
|
||||||
? EdgeInsets.zero
|
? EdgeInsets.zero
|
||||||
: const EdgeInsets.only(right: 10),
|
: const EdgeInsets.only(right: 10),
|
||||||
child: LayoutBuilder(
|
child: Obx(
|
||||||
builder: (context, constraints) {
|
() {
|
||||||
return Obx(
|
final videoDetail = introController.videoDetail.value;
|
||||||
() {
|
final String title;
|
||||||
final videoDetail =
|
if (videoDetail.videos == 1) {
|
||||||
introController.videoDetail.value;
|
title = videoDetail.title!;
|
||||||
final String title;
|
} else {
|
||||||
if (videoDetail.videos == 1) {
|
title =
|
||||||
title = videoDetail.title!;
|
videoDetail.pages
|
||||||
} else {
|
?.firstWhereOrNull(
|
||||||
title =
|
(e) => e.cid == videoDetailCtr.cid.value,
|
||||||
videoDetail.pages
|
)
|
||||||
?.firstWhereOrNull(
|
?.pagePart ??
|
||||||
(e) =>
|
videoDetail.title!;
|
||||||
e.cid == videoDetailCtr.cid.value,
|
}
|
||||||
)
|
return MarqueeText(
|
||||||
?.pagePart ??
|
title,
|
||||||
videoDetail.title!;
|
spacing: 30,
|
||||||
}
|
velocity: 30,
|
||||||
return MarqueeText(
|
controller: _marqueeController,
|
||||||
title,
|
style: const TextStyle(
|
||||||
maxWidth: constraints.maxWidth,
|
color: Colors.white,
|
||||||
spacing: 30,
|
fontSize: 16,
|
||||||
style: const TextStyle(
|
),
|
||||||
color: Colors.white,
|
|
||||||
fontSize: 16,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -176,7 +176,23 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
|||||||
super.initState();
|
super.initState();
|
||||||
_controlsListener = plPlayerController.showControls.listen((bool val) {
|
_controlsListener = plPlayerController.showControls.listen((bool val) {
|
||||||
final visible = val && !plPlayerController.controlsLock.value;
|
final visible = val && !plPlayerController.controlsLock.value;
|
||||||
visible ? animationController.forward() : animationController.reverse();
|
if (visible) {
|
||||||
|
animationController.forward();
|
||||||
|
widget
|
||||||
|
.videoDetailController
|
||||||
|
?.headerCtrKey
|
||||||
|
.currentState
|
||||||
|
?.marqueeController
|
||||||
|
?.start();
|
||||||
|
} else {
|
||||||
|
animationController.reverse();
|
||||||
|
widget
|
||||||
|
.videoDetailController
|
||||||
|
?.headerCtrKey
|
||||||
|
.currentState
|
||||||
|
?.marqueeController
|
||||||
|
?.stop();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
animationController = AnimationController(
|
animationController = AnimationController(
|
||||||
vsync: this,
|
vsync: this,
|
||||||
|
|||||||
Reference in New Issue
Block a user