Flutter 视频列表的简单实现

Flutter 视频列表的简单实现

参考 https://resocoder.com/2019/04/13/flutter-video-player-chewie-tutorial/
视频的播放插件是用chewie
chewie的使用:
1. 引入 chewie: ^0.9.7
2. AndroidManifest.xml 里面加上  <uses-permission android:name="android.permission.INTERNET"/>
3. ios里面的Runner->Info.plist->
<key>NSAppTransportSecurity</key>
<dict>
  <key>NSAllowsArbitraryLoads</key>
  <true/>
</dict>

//视频列表页面
//videos/IntroVideo.mp4  视频源 也可以设置为网络资源
class MainPage extends StatefulWidget {
  @override
  _MainPageState createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
  List<VideoBean> videolist = [];
  //itemHight  向上滑动的距离
  double itemHight = 0;
  //点击item的 角标
  int clickPosition = 0;
  //滚动控制器
  ScrollController _scrollController =
      new ScrollController(initialScrollOffset: 0);
  //列表滑动的距离的初始值
  double initPosition = 0;
  //向下滑动的距离
  double upHight = 0;
  //   initPosition  记录点击时候列表滑动的高度
  @override
  void initState() {
    super.initState();
    //设置滚动监听  为了实现滑动到一定位置的时候视频关闭
    _scrollController.addListener(() {
      //_scrollController.position.pixels - initPosition   列表从当前位置向上滑动的距离
      //itemHight  视频应该向上滑动的距离  才能消失
      //initPosition - _scrollController.position.pixels   列表从当前位置向下滑动的距离
      //upHight    视频应该向下滑动的距离  才能消失
      if (itemHight > 0) {
        if (_scrollController.position.pixels - initPosition > itemHight ||
            initPosition - _scrollController.position.pixels > upHight) {
          print('控件该隐藏了');
          //获取点击的视频 然后隐藏   并且itemHight =0
          VideoBean bean = videolist[clickPosition];
          setState(() {
            bean.isSeeVideo = false;
            itemHight = 0;
          });
        }
      }
    });
    //获取列表数据
    getApiData();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Video Player'),
      ),
      body: getListView(context),
    );
  }

//获取列表
  getListView(BuildContext context) {
    return ListView.builder(
      controller: _scrollController,
      itemBuilder: (context, i) {
        GlobalKey firstKey = GlobalKey();
        GlobalKey secondKey = GlobalKey();
        return GestureDetector(
          onTap: () {
            itemClick(secondKey, i);
          },
          child: buildItems(videolist[i], firstKey, secondKey),
        );
      },
      itemCount: videolist.length,
    );
  }

  buildItems(
    VideoBean bean,
    GlobalKey firstKey,
    GlobalKey secondKey,
  ) {
    var item;
    if (bean.isSeeVideo) {
      item = Container(
        key: firstKey,
        child: ChewiePage(
          videoPlayerController:
              VideoPlayerController.asset('videos/IntroVideo.mp4'),
        ),
      );
    } else {
      item = Container(
        key: secondKey,
        height: MediaQuery.of(context).size.width * 9 / 16,
        width: MediaQuery.of(context).size.width,
        margin: EdgeInsets.all(10),
        color: Colors.orange,
        child: Center(
          child: Text(
            'data',
            style: TextStyle(color: Colors.black, fontSize: 17),
          ),
        ),
      );
    }
    return item;
  }

  getApiData() {
    for (int i = 0; i < 6; i++) {
      VideoBean bean = new VideoBean();
      bean.id = i;
      bean.url = '';
      bean.name = '';
      videolist.add(bean);
    }
  }

  itemClick(GlobalKey secondKey, int position) {
    RenderBox renderBox = secondKey.currentContext.findRenderObject();
    var offset = renderBox.localToGlobal(Offset(0.0, renderBox.size.height));
    setState(() {
      //获取当前列表滚动的距离
      itemHight = offset.dy;
      clickPosition = position;
    });
    print('$itemHight');
    for (int j = 0; j < videolist.length; j++) {
      VideoBean videoBean = videolist[j];
      setState(() {
        videoBean.isSeeVideo = false;
      });
    }
    //  bus.sendBroadcast('ChewieListItem');
    VideoBean bean = videolist[position];
    setState(() {
      bean.isSeeVideo = true;
      initPosition = _scrollController.position.pixels;
      //屏幕的高度-视频所处的高度 +视频的高度
      upHight = MediaQuery.of(context).size.height -
          itemHight +
          MediaQuery.of(context).size.width * 9 / 16;
    });
  }
}
//视频的item页面
class ChewiePage extends StatefulWidget {
  final VideoPlayerController videoPlayerController;
  final bool looping;

  ChewiePage({
    @required this.videoPlayerController,
    this.looping,
    Key key,
  }) : super(key: key);

  @override
  _ChewiePageState createState() => _ChewiePageState();
}

class _ChewiePageState extends State<ChewiePage> {
  ChewieController _chewieController;

  @override
  void initState() {
    super.initState();
    //创建Chewie 的控制器
    _chewieController = ChewieController(
      videoPlayerController: widget.videoPlayerController,
      aspectRatio: 16 / 9,
      autoInitialize: true,
      looping: widget.looping,
      errorBuilder: (context, errorMessage) {
        return Center(
          child: Text(
            errorMessage,
            style: TextStyle(color: Colors.white),
          ),
        );
      },
    );

    print('控制器设置');
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: Chewie(
        controller: _chewieController,
      ),
    );
  }

  @override
  void dispose() {
    //为了满足全屏时候 控制器不被直接销毁 判断只有不是全屏的时候 才允许控制器被销毁
    if (_chewieController != null && !_chewieController.isFullScreen) {
      widget.videoPlayerController.dispose();
      _chewieController.dispose();
      print('控制器销毁');
    }
    super.dispose();
  }
}

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值