repeat_video_widget.dart 5.66 KB
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:video_player/video_player.dart';
import 'package:wow_english/models/read_content_entity.dart';

import '../bloc/repeat_after_content_bloc.dart';

class RepeatVideoWidget extends StatefulWidget {
  const RepeatVideoWidget({super.key, this.videoUrl, required this.videoUrls});
  final String? videoUrl;
  final List<ReadContentEntity?> videoUrls;

  @override
  State<StatefulWidget> createState() {
    return _RepeatVideoWidgetState();
  }
}

class _RepeatVideoWidgetState extends State<RepeatVideoWidget> {
  VideoPlayerController? _controller;
  String _currentTime = '00:00';
  String _totalTime = '00:00';
  double _playDegree = 0.5;
  int _currentPlayIndex = 0;

  String formatDuration(Duration duration) {
    String minutes = duration.inMinutes.remainder(60).toString().padLeft(2, '0');
    String seconds = duration.inSeconds.remainder(60).toString().padLeft(2, '0');
    return "$minutes:$seconds";
  }

  void _addListener() {
    _controller!.addListener(() {
      if(_controller!.value.isInitialized) {
        if (_controller!.value.isPlaying) {
          setState(() {
            double currentSecond = (_controller!.value.position.inMinutes.remainder(60)*60+_controller!.value.position.inSeconds.remainder(60)).toDouble();
            int totalSecond = _controller!.value.duration.inMinutes.remainder(60)*60+_controller!.value.duration.inSeconds.remainder(60);
            _currentTime = formatDuration(_controller!.value.position);
            _playDegree = currentSecond/totalSecond;
            if(_playDegree < 0) {
              _playDegree = 0.0;
            }

            if(_playDegree > 1) {
              _playDegree = 1.0;
            }
          });
        }
      }
    });
  }

  @override
  void initState() {
    super.initState();
    var videoUrl = '';
    if(widget.videoUrls.isNotEmpty) {
      videoUrl = widget.videoUrls[_currentPlayIndex]?.videoUrl??'';
    }
    _initVideo(videoUrl);
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: _controller!.value.isInitialized ?  BlocListener<RepeatAfterContentBloc,RepeatAfterContentState>(
        listener: (context, state){
          if (state is VideoPlayChangeState) {
            if (context.read<RepeatAfterContentBloc>().videoPlaying) {
              _controller!.play();
            } else {
              _controller!.pause();
            }
          }

          if (state is ChangeVideoPlayIndexState) {
            if(state.isNext) {
              if (_currentPlayIndex != (widget.videoUrls.length-1)) {
                _currentPlayIndex++;
                _destroyVideo();
                _initVideo(widget.videoUrls[_currentPlayIndex]!.videoUrl!);
              }
            } else {
              if (_currentPlayIndex > 0) {
                _currentPlayIndex--;
                _destroyVideo();
                _initVideo(widget.videoUrls[_currentPlayIndex]!.videoUrl!);
              }
            }
          }
        },
        child: SizedBox(
          child: Column(
            children: [
              Expanded(
                child: Stack(
                  children: [
                    Container(
                      width: double.infinity,
                      height: double.infinity,
                      alignment: Alignment.center,
                      decoration: BoxDecoration(
                          color: Colors.black,
                          border: Border.all(
                            width: 1.0,
                            color: const Color(0xFF140C10),
                          ),
                          borderRadius: BorderRadius.circular(5.r)
                      ),
                      child: AspectRatio(
                        aspectRatio: _controller!.value.aspectRatio,
                        child: VideoPlayer(_controller!),
                      ),
                    ),
                    Positioned(
                        left: 0,
                        right: 0,
                        bottom: 0,
                        child: LinearProgressIndicator(
                          color: const Color(0xFF78B72D),
                          backgroundColor: const Color(0xFF7E756C),
                          value: _playDegree,
                        ))
                  ],
                ),
              ),
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  Text(_currentTime),
                  Text(_totalTime),
                ],
              )
            ],
          ),
        )
      )
          :
      Container(
        color: Colors.white,
        child: const CircularProgressIndicator(),
        // Text(
        //   '视频加载中....',
        //   style: TextStyle(
        //       fontSize: 20.sp,
        //       color: Colors.black
        //   ),
        // ),
      ),
    );
  }

  void _initVideo(String videoUrl) {
    if(videoUrl.isNotEmpty) {
      Uri uri = Uri.parse(videoUrl);
      _controller = VideoPlayerController.networkUrl(uri)
        ..initialize().then((_){
          setState(() {
            _currentTime = formatDuration(_controller!.value.position);
            _totalTime = formatDuration(_controller!.value.duration);
            _controller!.setLooping(false);
            _controller!.setVolume(100);
            _controller!.play();
          });
          _addListener();
        });
    }
  }

  void _destroyVideo() {
    _controller?.dispose();
    _controller?.removeListener(() {});
  }

  @override
  void dispose() {
    _destroyVideo();
    super.dispose();
  }
}