Flutter 實現網易雲音樂字幕

老孟導讀:沒有接觸過音樂字幕方面知識的話,會對字幕的實現比較迷茫,什麼時候轉到下一句?看了這篇文章,你就會明白字幕so easy。

先來一張效果圖:

subtitle_1

字幕格式

目前市面上有很多種字幕格式,比如srt, ssa, ass(文本形式)和idx+sub(圖形格式),但不管哪一種格式都會包含2個屬性:時間戳和字幕內容,格式如下:

00:00 歌詞:
00:25 我要穿越這片沙漠
00:28 找尋真的自我
00:30 身邊只有一匹駱駝陪我
00:34 這片風兒吹過
00:36 那片雲兒飄過

上面字幕的意思是:在25秒的時候跳轉到下一句,在28秒的時候跳轉到下一句...

字幕實現

瞭解了字幕文件的形式,字幕實現起來就比較簡單了,使用ListWheelScrollView控件,然後通過ScrollController在合適的時機進行滾動,使當前字幕始終保持在屏幕中間。

解析字幕文件,獲取字幕數據:

loadData() async {
  var jsonStr =
      await DefaultAssetBundle.of(context).loadString('assets/subtitle.txt');
  var list = jsonStr.split(RegExp('\n'));
  list.forEach((f) {
    if (f.isNotEmpty) {
      var r = f.split(RegExp(' '));
      if (r.length >= 2) {
        _subtitleList.add(SubtitleEntry(r[0], r[1]));
      }
    }
  });
  setState(() {});
}

設置字幕控件及背景圖片:

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text('彈幕'),
    ),
    body: Stack(
      children: <Widget>[
        Positioned.fill(
            child: Image.asset(
          'assets/imgs/background.png',
          fit: BoxFit.cover,
        )),
        Positioned.fill(
            child: Subtitle(
          _subtitleList,
          selectedTextStyle: TextStyle(color: Colors.white,fontSize: 18),
          unSelectedTextStyle: TextStyle(
            color: Colors.black.withOpacity(.6),
          ),
          diameterRatio: 5,
          itemExtent: 45,
        ))
      ],
    ),
  );
}

字幕控件的構建:

@override
Widget build(BuildContext context) {
  if (widget.data == null || widget.data.length == 0) {
    return Container();
  }
  return ListWheelScrollView.useDelegate(
    controller: _controller,
    diameterRatio: widget.diameterRatio,
    itemExtent: widget.itemExtent,
    childDelegate: ListWheelChildBuilderDelegate(
        builder: (context, index) {
          return Container(
            alignment: Alignment.center,
            child: Text(
              '${widget.data[index].content}',
              style: _currentIndex == index
                  ? widget.selectedTextStyle
                  : widget.unSelectedTextStyle,
            ),
          );
        },
        childCount: widget.data.length),
  );
}

字幕控件封裝了選中字體和未選中字體樣式參數,用法如下:

Subtitle(
    _subtitleList,
    selectedTextStyle: TextStyle(color: Colors.white,fontSize: 18),
    unSelectedTextStyle: TextStyle(
      color: Colors.black.withOpacity(.6),
    )
)

效果如下:

設置圓筒直徑和主軸渲染窗口的尺寸的比,默認值是2,越小表示圓筒越圓

Subtitle(
    _subtitleList,
    diameterRatio: 5,
)

下面是1和5的對比:

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生態建設離不開你我他,需要大家共同的努力,點贊也是其中的一種,如果文章幫助到了你,希望點個贊。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章