flutter video_player pageView 视频分页播放自适应视频宽高

1、新建播放组件(预览图和文案可以删除也可以重新自定义,主要是视频地址)

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:midou_ee/car_video/page/car_video_page.dart';
import 'package:midou_ee/common/event_bus.dart';
import 'package:midou_ee/mall/mall_router.dart';
import 'package:midou_ee/routers/navigator_util.dart';
import 'package:midou_ee/utils/screen_util.dart';
import 'package:midou_ee/utils/toast.dart';
import 'package:midou_ee/widgets/load_image.dart';
import 'package:video_player/video_player.dart';

class CarShortVideo extends StatefulWidget {
  final String url;
  final String previewImageUrl; //预览图片的地址
  final bool showProgressBar; //是否显示进度条
  final bool showProgressText; //是否显示进度文本
  final int positionTag;
  final String title;
  final int carId;
  final int productId;
  final int putawayForm;

  const CarShortVideo(
    this.url, {
    Key key,
    this.previewImageUrl: '',
    this.showProgressBar: true,
    this.showProgressText: true,
    this.positionTag,
    this.title,
    this.carId,
    this.productId,
    this.putawayForm,
  }) : super(key: key);

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

class _CarShortVideoState extends State<CarShortVideo> {
  VideoPlayerController _controller;
  bool _hideActionButton = true;
  bool videoPrepared = false; //视频是否初始化
  double aspectRatio = 1;
  Future _initializeVideoPlayerFuture;
  @override
  void initState() {
    super.initState();
    eventBus.on(EventVideoPlayPosition + widget.positionTag.toString(), (arg) {
      setState(() {
        if (arg == widget.positionTag) {
          _controller.play();
          videoPrepared = true;
        } else {
          _controller.pause();
        }
      });
    });
    _controller = VideoPlayerController.network(widget.url)
      ..setLooping(true).then((_) {
        if (widget.positionTag == 0 && CarVideoPage.firstInitTimes == 1) {
          CarVideoPage.firstInitTimes = 2;

          _controller.play();
          videoPrepared = true;
          setState(() {});
        }
      });
    _initializeVideoPlayerFuture = _controller.initialize();
  }

  @override
  Widget build(BuildContext context) {
    aspectRatio = _controller.value.aspectRatio;
    return Stack(
      children: <Widget>[
        Container(
          // padding: EdgeInsets.only(top: 20),
          color: Color(0XFF333333),
          // padding: EdgeInsets.all(20),
          child: GestureDetector(
            child: Stack(
              children: <Widget>[
                FutureBuilder(
                  future: _initializeVideoPlayerFuture,
                  builder: (context, snapshot) {
                    // print(snapshot.connectionState);
                    if (snapshot.connectionState == ConnectionState.done) {
                      return Center(
                        child: AspectRatio(
                          aspectRatio: _controller.value.aspectRatio,
                          child: VideoPlayer(_controller),
                        ),
                      );
                    } else {
                      return Center(
                        child: CircularProgressIndicator(),
                      );
                    }
                  },
                ),
                _getPauseView(),
              ],
            ),
            onTap: () {
              if (_controller.value.isPlaying) {
                _controller.pause();
                _hideActionButton = false;
                setState(() {});
              } else {
                _controller.play();
                videoPrepared = true;
                _hideActionButton = true;
                setState(() {});
              }
            },
          ),
        ),
        _getPreviewImage(), //预览图
        _getRightActionView(), //右侧转发,评论按钮
        _getLeftActionView(), //左侧文案
      ],
    );
  }

  Widget _getPreviewImage() {
    return Offstage(
      offstage: videoPrepared,
      child: Container(
        width: ScreenUtil.screenWidth,
        height: ScreenUtil.screenHeight,
        color: Color(0XFF333333),
        child: Center(
          child: Image.network(
            widget.previewImageUrl,
            fit: BoxFit.fill,
            width: ScreenUtil.screenWidth,
            // height: ScreenUtil.screenHeight,
          ),
        ),
      ),
    );
  }

  Widget _getPauseView() {
    return Offstage(
      offstage: _hideActionButton,
      child: Stack(
        children: <Widget>[
          Align(
            child: Container(
              height: 50.0,
              width: 50.0,
              child: LoadAssetImage('icon/icon_video_playing'),
            ),
            alignment: Alignment.center,
          ),
        ],
      ),
    );
  }

  //分享、转发等功能按钮
  Widget _getRightActionView() {
    return Positioned(
      bottom: 0,
      right: 0,
      child: Container(
          // margin: const EdgeInsets.fromLTRB(0, 0, 15, 120.0),
          // child: Column(
          //   children: <Widget>[
          //     Container(
          //       child: Column(children: <Widget>[
          //         LoadAssetImage('icon/icon_video_praise',
          //             width: 36, height: 36),
          //         Text(
          //           "1.6w",
          //           style: TextStyle(
          //               fontSize: 15,
          //               color: Colors.white,
          //               decoration: TextDecoration.none),
          //         ),
          //       ]),
          //     ),
          //     SizedBox(height: 8),
          //     Container(
          //       child: Column(children: <Widget>[
          //         LoadAssetImage('icon/icon_video_msg',
          //             width: 36, height: 36),
          //         Text(
          //           "1.3w",
          //           style: TextStyle(
          //               fontSize: 15,
          //               color: Colors.white,
          //               decoration: TextDecoration.none),
          //         ),
          //       ]),
          //     ),
          //     SizedBox(height: 8),
          //     Container(
          //       child: Column(children: <Widget>[
          //         LoadAssetImage('icon/icon_video_share',
          //             width: 36, height: 36),
          //         Text(
          //           "2.1w",
          //           style: TextStyle(
          //               fontSize: 15,
          //               color: Colors.white,
          //               decoration: TextDecoration.none),
          //         ),
          //       ]),
          //     ),
          //   ],
          // ),
          ),
    );
  }

  //左侧文案
  Widget _getLeftActionView() {
    return Positioned(
      bottom: 0,
      child: Container(
        padding: EdgeInsets.all(30),
        width: ScreenUtil.screenWidth,
        child: Row(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Expanded(
              child: Text(
                widget.title,
                style: TextStyle(fontSize: 16, color: Colors.white),
                overflow: TextOverflow.ellipsis,
              ),
            ),
            GestureDetector(
              child: Container(
                padding: EdgeInsets.symmetric(horizontal: 11, vertical: 6),
                alignment: Alignment.center,
                decoration: BoxDecoration(
                    color: Color(0XFF000000),
                    borderRadius: BorderRadius.all(Radius.circular(5))),
                margin: const EdgeInsets.only(left: 1.0),
                child: Text(
                  '查看详情',
                  style: TextStyle(
                      fontSize: 12.0,
                      color: Color(0XFFF36926),
                      decoration: TextDecoration.none),
                ),
              ),
              onTap: () {
                if (widget.putawayForm == 1) {
                  //一口价
                  NavigatorUtil.push(context,
                      '${MallRouter.goodDetailPage}?productId=${widget.productId}&carId=${widget.carId}');
                } else if (widget.putawayForm == 2) {
                  //拍卖
                  NavigatorUtil.push(context,
                      '${MallRouter.auctionDetailsPage}?productId=${widget.productId}&carId=${widget.carId}');
                }
              },
            ),
            SizedBox(
              width: 20,
            ),
            GestureDetector(
              child: LoadAssetImage('icon/icon_video_praise',
                  width: 21, height: 20),
              onTap: () {
                Toast.show('该功能暂未开放敬请期待!');
              },
            ),
          ],
        ),
      ),
    );
  }

  @override
  void dispose() {
    super.dispose();
    eventBus.off(EventVideoPlayPosition + widget.positionTag.toString());
    _controller.dispose(); //释放播放器资源
  }
}

2.分页功能实现(positionTag ,是当前滚动视频自动播放的下标一定要有,否则无法自动播放)


import 'package:flutter/material.dart';
import 'package:midou_ee/car_video/model/car_videos_entity.dart';
import 'package:midou_ee/car_video/widget/car_short_video.dart';
import 'package:midou_ee/common/constants.dart';
import 'package:midou_ee/common/event_bus.dart';
import 'package:midou_ee/net/dio_util.dart';
import 'package:midou_ee/net/http_api.dart';

class CarVideoPage extends StatefulWidget {
  static int firstInitTimes = 1;
  @override
  _CarVideoPageState createState() => _CarVideoPageState();
}

class _CarVideoPageState extends State<CarVideoPage> {
  // SwiperController _controller = SwiperController();
  PageController _controller = PageController();
  List<CarVideosEntity> carList = [];
  
   
   int pageNum = 1;
   bool _pageState = true;
  @override
  void initState() {
    super.initState();
    // _controller.addListener(() {
      
    //   if (_controller.page.floor() == _controller.page) {
    //    if(_controller.page%9 == 0){
    //         _loadData();
    //       }
    //     eventBus.emit(
    //         EventVideoPlayPosition + _controller.page.floor().toString(),
    //         _controller.page.floor());
         
    //   }
    // });
    // _pageController = PageController(initialPage: 0);
    setState(() {
       _loadData();
    });
   
  }

  List<Widget> _buildListItem() {
   List<Widget> items = List<Widget>();

    if (carList.length > 0) {
      var _i = 0;
      carList.forEach((value) {
          items.add(CarShortVideo(
            value.playURL,
            previewImageUrl: value.imageUrl,
            positionTag: _i,
            title: value.productName,
            productId:value.productId,
            carId: value.carId,
            putawayForm: value.putawayForm,
          ));
          _i++;
      });

    }
    // carList = [];
    return items;
  }

  @override
  Widget build(BuildContext context) {
    return carList.length > 0
        ? Scaffold(
            // body: Swiper(
            //   autoStart: false,
            //   circular: false,
            //   direction: Axis.vertical,
            //   children: _buildListItem(),
            //   controller: _controller,

            // ),
            body: PageView(
              children: _buildListItem(),
              controller: _controller,
              scrollDirection: Axis.vertical,
              onPageChanged: (int index){
                if(_pageState){
                  if(index%9 == 0){
                    _loadData();
                  }
                }
                eventBus.emit(
                  EventVideoPlayPosition + index.toString(),
                  index);
                  setState(() {
                    
                  });
              },
            ),
          )
        :Scaffold(
          body: Container(),
        ) ;
  }

  Future _loadData() async {
    
    var params = {
      "pageNum": pageNum,
      "pageSize": Constants.pageSize,
    };
    
    await DioUtil.instance.requestNetWork<CarVideosEntity>(
        Method.post, '${HttpApi.PRODUCT_QUERYBYVIDEO}',
        params: params, isList: true, onSuccessList: (data) {
      if (data != null) {
        setState(() {
          if(data.length > 0){
            var i = 0;
            data.forEach((item){
              item.index = (pageNum-1)*10+i;
              carList.add(item);
              i++; 
            });
            pageNum ++;
            // carList;
          }else{
            // setState(() {
                _pageState = false;
            // });
          }
        });
      }
    });
  }

  @override
  void dispose() {
    super.dispose();
    CarVideoPage.firstInitTimes = 1;
  }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335

推荐阅读更多精彩内容