flutter如何实现歌词滚动显示
在Flutter中如何实现类似音乐播放器的歌词滚动显示效果?目前需要实现以下功能:1. 根据当前播放时间自动滚动到对应的歌词行;2. 高亮显示当前播放的歌词;3. 支持上下滑动查看歌词。请问有没有推荐的实现方案或现成的插件可以使用?最好能提供一些示例代码或实现思路。
2 回复
Flutter中实现歌词滚动显示,可以这样做:
-
解析歌词:将LRC格式歌词解析为时间戳和歌词内容的列表
-
使用ListView.builder:
ListView.builder(
itemCount: lyrics.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(lyrics[index].text),
// 高亮当前播放的歌词行
tileColor: index == currentIndex ? Colors.blue : null,
);
},
)
- 滚动控制:
// 滚动到指定位置
_scrollController.animateTo(
offset,
duration: Duration(milliseconds: 500),
curve: Curves.easeInOut,
);
-
定时器监听:通过Timer或AnimationController监听播放进度,更新currentIndex并触发滚动
-
优化:可添加歌词缓存、平滑滚动动画、字体大小变化等效果
核心思路是监听播放时间,匹配对应歌词索引,然后控制ListView滚动到相应位置。
更多关于flutter如何实现歌词滚动显示的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
在Flutter中实现歌词滚动显示,可以通过以下步骤完成:
- 解析歌词文件:将LRC格式的歌词解析为时间戳和歌词文本的列表。
- 监听音频播放进度:使用音频播放插件(如
audioplayers)获取当前播放时间。 - 高亮当前歌词:根据当前时间匹配对应的歌词行,并高亮显示。
- 自动滚动:使用
ScrollController或ListView的scrollToIndex方法实现滚动效果。
示例代码
1. 歌词数据模型
class Lyric {
final Duration time;
final String text;
Lyric(this.time, this.text);
}
2. 解析歌词
List<Lyric> parseLyrics(String lrcContent) {
final lines = lrcContent.split('\n');
final List<Lyric> lyrics = [];
final RegExp regex = RegExp(r'\[(\d+):(\d+).(\d+)\](.*)');
for (var line in lines) {
final match = regex.firstMatch(line);
if (match != null) {
final min = int.parse(match.group(1)!);
final sec = int.parse(match.group(2)!);
final hundred = int.parse(match.group(3)!);
final text = match.group(4)!.trim();
final duration = Duration(
minutes: min,
seconds: sec,
milliseconds: hundred * 10,
);
lyrics.add(Lyric(duration, text));
}
}
return lyrics;
}
3. 实现滚动歌词组件
class LyricWidget extends StatefulWidget {
final List<Lyric> lyrics;
final Duration currentTime;
const LyricWidget({
Key? key,
required this.lyrics,
required this.currentTime,
}) : super(key: key);
@override
_LyricWidgetState createState() => _LyricWidgetState();
}
class _LyricWidgetState extends State<LyricWidget> {
final ScrollController _scrollController = ScrollController();
int _currentIndex = 0;
@override
void didUpdateWidget(covariant LyricWidget oldWidget) {
super.didUpdateWidget(oldWidget);
_updateLyricIndex();
}
void _updateLyricIndex() {
for (int i = 0; i < widget.lyrics.length; i++) {
if (widget.currentTime >= widget.lyrics[i].time &&
(i == widget.lyrics.length - 1 ||
widget.currentTime < widget.lyrics[i + 1].time)) {
if (_currentIndex != i) {
setState(() {
_currentIndex = i;
});
_scrollToCurrentLyric();
}
break;
}
}
}
void _scrollToCurrentLyric() {
final context = _scrollController.position.context;
if (context != null) {
_scrollController.animateTo(
_currentIndex * 50.0, // 假设每行高度为50
duration: const Duration(milliseconds: 300),
curve: Curves.easeInOut,
);
}
}
@override
Widget build(BuildContext context) {
return ListView.builder(
controller: _scrollController,
itemCount: widget.lyrics.length,
itemBuilder: (context, index) {
final lyric = widget.lyrics[index];
return Container(
padding: const EdgeInsets.symmetric(vertical: 8),
alignment: Alignment.center,
child: Text(
lyric.text,
style: TextStyle(
fontSize: _currentIndex == index ? 20 : 16,
color: _currentIndex == index ? Colors.blue : Colors.grey,
fontWeight: _currentIndex == index ? FontWeight.bold : FontWeight.normal,
),
),
);
},
);
}
}
使用方式
LyricWidget(
lyrics: parseLyrics(lrcString),
currentTime: currentAudioPosition, // 从音频播放器获取
)
说明
- 歌词解析:支持标准LRC格式,提取时间戳和歌词文本。
- 滚动控制:通过
ScrollController实现平滑滚动到当前歌词。 - 样式高亮:当前播放的歌词会放大并改变颜色,其他歌词显示为灰色。
如果需要更精确的滚动定位,可以考虑使用scrollable_positioned_list包替代默认的ListView。

