fix(lyrics): keep the active line anchored during language transitions

This commit is contained in:
zarzet
2026-09-27 00:20:02 +07:00
parent 3f111b5ea6
commit 3e6bb3bba4
4 changed files with 178 additions and 73 deletions
+14 -19
View File
@@ -1,6 +1,7 @@
import 'dart:math' as math;
import 'package:flutter/material.dart';
import 'package:spotiflac_android/widgets/lyric_supplement_transition.dart';
import 'package:spotiflac_android/utils/lyrics_parser.dart';
/// Keeps each pronunciation phrase under the lyric with the same start time.
@@ -234,25 +235,19 @@ class AlignedLyricPronunciation extends StatelessWidget {
),
),
if (visibility > 0)
ClipRect(
child: Align(
alignment: Alignment.topLeft,
heightFactor: visibility,
child: Opacity(
opacity: visibility,
child: Padding(
padding: const EdgeInsets.only(
top: LyricPronunciationLayout._pronunciationGap,
),
child: SizedBox(
width: double.infinity,
height: row.pronunciationHeight,
child: (pronunciationBuilder ?? textBuilder)(
group.pronunciation.map((word) => word.text).join(),
group.pronunciation,
pronunciationStyle,
),
),
LyricSupplementTransition(
visibility: visibility,
child: Padding(
padding: const EdgeInsets.only(
top: LyricPronunciationLayout._pronunciationGap,
),
child: SizedBox(
width: double.infinity,
height: row.pronunciationHeight,
child: (pronunciationBuilder ?? textBuilder)(
group.pronunciation.map((word) => word.text).join(),
group.pronunciation,
pronunciationStyle,
),
),
),
@@ -0,0 +1,30 @@
import 'package:flutter/widgets.dart';
/// The painted text and its reserved height follow the same progress. Cropping
/// full-size text while only shrinking its container makes toggles look jerky.
class LyricSupplementTransition extends StatelessWidget {
const LyricSupplementTransition({
super.key,
required this.visibility,
required this.child,
this.alignment = Alignment.topLeft,
});
final double visibility;
final Widget child;
final Alignment alignment;
@override
Widget build(BuildContext context) => Align(
alignment: alignment,
heightFactor: visibility,
child: Opacity(
opacity: visibility,
child: Transform.scale(
scale: visibility,
alignment: alignment,
child: child,
),
),
);
}