Flutter 实现网易云音乐字幕

一时失言乱红尘 2023-07-25 11:26 89阅读 0赞

20200414204602749.png

老孟导读:没有接触过音乐字幕方面知识的话,会对字幕的实现比较迷茫,什么时候转到下一句?看了这篇文章,你就会明白字幕so easy。

先来一张效果图:

subtitle\_1

字幕格式

目前市面上有很多种字幕格式,比如srt, ssa, ass(文本形式)和idx+sub(图形格式),但不管哪一种格式都会包含2个属性:时间戳和字幕内容,格式如下:

  1. 00:00 歌词:
  2. 00:25 我要穿越这片沙漠
  3. 00:28 找寻真的自我
  4. 00:30 身边只有一匹骆驼陪我
  5. 00:34 这片风儿吹过
  6. 00:36 那片云儿飘过

上面字幕的意思是:在25秒的时候跳转到下一句,在28秒的时候跳转到下一句…

字幕实现

了解了字幕文件的形式,字幕实现起来就比较简单了,使用ListWheelScrollView控件,然后通过ScrollController在合适的时机进行滚动,使当前字幕始终保持在屏幕中间。

解析字幕文件,获取字幕数据:

  1. loadData() async {
  2. var jsonStr =
  3. await DefaultAssetBundle.of(context).loadString('assets/subtitle.txt');
  4. var list = jsonStr.split(RegExp('\n'));
  5. list.forEach((f) {
  6. if (f.isNotEmpty) {
  7. var r = f.split(RegExp(' '));
  8. if (r.length >= 2) {
  9. _subtitleList.add(SubtitleEntry(r[0], r[1]));
  10. }
  11. }
  12. });
  13. setState(() {});
  14. }

设置字幕控件及背景图片:

  1. @override
  2. Widget build(BuildContext context) {
  3. return Scaffold(
  4. appBar: AppBar(
  5. title: Text('弹幕'),
  6. ),
  7. body: Stack(
  8. children: <Widget>[
  9. Positioned.fill(
  10. child: Image.asset(
  11. 'assets/imgs/background.png',
  12. fit: BoxFit.cover,
  13. )),
  14. Positioned.fill(
  15. child: Subtitle(
  16. _subtitleList,
  17. selectedTextStyle: TextStyle(color: Colors.white,fontSize: 18),
  18. unSelectedTextStyle: TextStyle(
  19. color: Colors.black.withOpacity(.6),
  20. ),
  21. diameterRatio: 5,
  22. itemExtent: 45,
  23. ))
  24. ],
  25. ),
  26. );
  27. }

字幕控件的构建:

  1. @override
  2. Widget build(BuildContext context) {
  3. if (widget.data == null || widget.data.length == 0) {
  4. return Container();
  5. }
  6. return ListWheelScrollView.useDelegate(
  7. controller: _controller,
  8. diameterRatio: widget.diameterRatio,
  9. itemExtent: widget.itemExtent,
  10. childDelegate: ListWheelChildBuilderDelegate(
  11. builder: (context, index) {
  12. return Container(
  13. alignment: Alignment.center,
  14. child: Text(
  15. '${widget.data[index].content}',
  16. style: _currentIndex == index
  17. ? widget.selectedTextStyle
  18. : widget.unSelectedTextStyle,
  19. ),
  20. );
  21. },
  22. childCount: widget.data.length),
  23. );
  24. }

字幕控件封装了选中字体和未选中字体样式参数,用法如下:

  1. Subtitle(
  2. _subtitleList,
  3. selectedTextStyle: TextStyle(color: Colors.white,fontSize: 18),
  4. unSelectedTextStyle: TextStyle(
  5. color: Colors.black.withOpacity(.6),
  6. )
  7. )

效果如下:

image-20200414164225470.png

设置圆筒直径和主轴渲染窗口的尺寸的比,默认值是2,越小表示圆筒越圆

  1. Subtitle(
  2. _subtitleList,
  3. diameterRatio: 5,
  4. )

下面是1和5的对比:

image-20200414164620947.png image-20200414164700859.png

Github地址:https://github.com/781238222/flutter-do/tree/master/flutter_subtitle_example

交流

Github地址:https://github.com/781238222/flutter-do

170+组件详细用法:http://laomengit.com

如果你对Flutter还有疑问或者技术方面的疑惑,欢迎加入Flutter交流群(微信:laomengit)。

同时也欢迎关注我的Flutter公众号【老孟程序员】,公众号首发Flutter的相关内容。

Flutter生态建设离不开你我他,需要大家共同的努力,点赞也是其中的一种,如果文章帮助到了你,希望点个赞。

发表评论

表情:
评论列表 (有 0 条评论,89人围观)

还没有评论,来说两句吧...

相关阅读