본문 바로가기
프로그래밍/Flutter-Dart

[Flutter] Vlc Player & Circular Percent Indicator

by 채연2 2021. 3. 24.

영상 플레이와 현재 재생 시간의 circular percent indicator를 해보았다.

 

 

pubspec.yaml

dependencies:
  flutter:
    sdk: flutter
  percent_indicator:
  flutter_vlc_player: ^4.0.1

 

 

 

영상 play

그 전에 포스팅했던 video_player는 현재 재생 시간을 보는 방법을 몰라서,, flutter_vlc_player로 대체하려고 한다.

class _VideoDemoState extends State<VideoDemo> {

  Key _key = GlobalKey<ScaffoldState>();

  String url ="https://www.learningcontainer.com/wp-content/uploads/2020/05/sample-mp4-file.mp4";
  late VlcPlayerController vlcPlayerController;
  bool isPlaying = true;
  bool isBuffering = true;
  String position = '';
  String duration = '';
  double sliderValue = 0.0;
  double startValue = 0.0;
  double volume = 80;


  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    vlcPlayerController = new VlcPlayerController(onInit: (){
      vlcPlayerController.play();
    });
    vlcPlayerController.addListener(() {
      if(!this.mounted){
        return;
      }
      if(vlcPlayerController.initialized){
        var Position = vlcPlayerController.position;
        var Duration = vlcPlayerController.duration;
        if(Duration.inHours == 0) {
          var startPosition = Position.toString().split('.')[0];
          var startDuration = Duration.toString().split('.')[0];
          position =
          '${startPosition.split(':')[1]}:${startPosition.split(':')[2]}';
          duration =
          '${startDuration.split(':')[1]};${startDuration.split(':')[2]}';
        }else{
          position = Position.toString().split('.')[0];
          duration = Duration.toString().split('.')[0];
        }
        sliderValue = vlcPlayerController.position.inSeconds.toDouble();


        switch(vlcPlayerController.playingState){

          case PlayingState.PLAYING:
            setState(() {
              isBuffering = false;
            });
            break;
          case PlayingState.BUFFERING:
            setState(() {
              isBuffering = true;
            });
            break;

          case PlayingState.STOPPED:
            setState(() {
              isBuffering = false;
              isPlaying = false;
            });
            break;

          case PlayingState.PAUSED:
            setState(() {
              isPlaying = false;
              isBuffering = false;
            });
            break;

          case PlayingState.ERROR:
            setState(() {
            });
            print('Error cant play');
            break;

          default:
            setState((){});
            break;
        }
      }
    });
  }

  @override
  void dispose() {
    // TODO: implement dispose
    super.dispose();
    vlcPlayerController.dispose();
  }

  void playAndPause(){
    String state = vlcPlayerController.playingState.toString();

    if(state == 'PlayingState.PLAYING'){
      vlcPlayerController.pause();
      setState(() {
        isPlaying = false;
      });
    }
    else{
      vlcPlayerController.play();
      setState(() {
        isPlaying = true;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: _key,
      appBar: AppBar(
        title: Text('Demo'),
      ),
      body: Builder(builder:(context){
        return Container(
          padding: EdgeInsets.all(10.0),
          child: ListView(
            shrinkWrap: true,
            children: [
              SizedBox(
                height: 250,
                child: new VlcPlayer(
                  controller: vlcPlayerController,
                  aspectRatio: 16 / 9,
                  url: url,
                  isLocalMedia: false,
                  placeholder: Container(
                    height: 250.0,
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: <Widget>[
                        CircularProgressIndicator(),
                      ],
                    ),
                  ),
                ),
              ),
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceAround,
                mainAxisSize: MainAxisSize.max,
                children: [
                  Flexible(
                    flex: 1,
                    child: FlatButton(
                      onPressed: (){playAndPause();},
                      child: isPlaying ? Icon(Icons.pause_circle_outline) :
                      Icon(Icons.play_circle_outline),
                    ),),
                  Flexible(
                    flex: 3,
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      mainAxisSize: MainAxisSize.max,
                      children: [
                        Text(position),
                        Expanded(
                          child: Slider(
                              value: sliderValue,
                              activeColor: Colors.red,
                              min: 0.0,
                              max: vlcPlayerController.duration == null ? 1.0
                                  : vlcPlayerController.duration.inSeconds.toDouble(),
                              onChanged: (progress){
                                setState(() {
                                  sliderValue = progress.floor().toDouble();
                                });
                                vlcPlayerController.setTime(sliderValue.toInt()* 1000);
                              }
                          ),
                        ),
                        Text(duration),
                      ],
                    ),
                  ),
                ],
              ),
              Divider(height: 1,),
              Row(
                crossAxisAlignment: CrossAxisAlignment.center,
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                children: [
                  Text('Volume Level'),
                  Slider(
                    min: 0,
                    max: 100,
                    value: volume,
                    onChanged: (value){
                      setState(() {
                        volume = value;
                      });

                      vlcPlayerController.setVolume(volume.toInt());
                    },
                  ),
                ],
              ),
            ],
          ),
        );
      }),
    );
  }
}

 

 

 

CircularPercentIndicator

CircularPercentIndicator(
   radius: 180.0,
   lineWidth: 13.0,
   animation: true,
   percent: sliderValue * 100 / vlcPlayerController.duration.inSeconds.toDouble() * 0.01,
   center: new Text(
      (sliderValue * 100 / vlcPlayerController.duration.inSeconds.toDouble()).toString() + "%",
      style: new TextStyle(fontWeight: FontWeight.bold, fontSize: 30.0),
   ),
   circularStrokeCap: CircularStrokeCap.round,
   progressColor: Colors.black,
   animateFromLastPercent: true,
)

- animateFromLastPercent가 true가 아니면 계속 처음부터 애니메이션 효과가 나타난다. true일 때가 이어서 증가하는 애니메이션!!!

 

 

 

 

결과

 

 

 

 

최종코드

import 'package:flutter/material.dart';
import 'package:flutter_vlc_player/flutter_vlc_player.dart';
import 'package:percent_indicator/circular_percent_indicator.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: VideoDemo(),
    );
  }
}
class VideoDemo extends StatefulWidget {
  @override
  _VideoDemoState createState() => _VideoDemoState();
}

class _VideoDemoState extends State<VideoDemo> {

  Key _key = GlobalKey<ScaffoldState>();

  String url ="https://www.learningcontainer.com/wp-content/uploads/2020/05/sample-mp4-file.mp4";
  late VlcPlayerController vlcPlayerController;
  bool isPlaying = true;
  bool isBuffering = true;
  String position = '';
  String duration = '';
  double sliderValue = 0.0;
  double startValue = 0.0;
  double volume = 80;


  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    vlcPlayerController = new VlcPlayerController(onInit: (){
      vlcPlayerController.play();
    });
    vlcPlayerController.addListener(() {
      if(!this.mounted){
        return;
      }
      if(vlcPlayerController.initialized){
        var Position = vlcPlayerController.position;
        var Duration = vlcPlayerController.duration;
        if(Duration.inHours == 0) {
          var startPosition = Position.toString().split('.')[0];
          var startDuration = Duration.toString().split('.')[0];
          position =
          '${startPosition.split(':')[1]}:${startPosition.split(':')[2]}';
          duration =
          '${startDuration.split(':')[1]};${startDuration.split(':')[2]}';
        }else{
          position = Position.toString().split('.')[0];
          duration = Duration.toString().split('.')[0];
        }
        sliderValue = vlcPlayerController.position.inSeconds.toDouble();


        switch(vlcPlayerController.playingState){

          case PlayingState.PLAYING:
            setState(() {
              isBuffering = false;
            });
            break;
          case PlayingState.BUFFERING:
            setState(() {
              isBuffering = true;
            });
            break;

          case PlayingState.STOPPED:
            setState(() {
              isBuffering = false;
              isPlaying = false;
            });
            break;

          case PlayingState.PAUSED:
            setState(() {
              isPlaying = false;
              isBuffering = false;
            });
            break;

          case PlayingState.ERROR:
            setState(() {
            });
            print('Error cant play');
            break;

          default:
            setState((){});
            break;
        }
      }
    });
  }

  @override
  void dispose() {
    // TODO: implement dispose
    super.dispose();
    vlcPlayerController.dispose();
  }

  void playAndPause(){
    String state = vlcPlayerController.playingState.toString();

    if(state == 'PlayingState.PLAYING'){
      vlcPlayerController.pause();
      setState(() {
        isPlaying = false;
      });
    }
    else{
      vlcPlayerController.play();
      setState(() {
        isPlaying = true;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: _key,
      appBar: AppBar(
        title: Text('Demo'),
      ),
      body: Builder(builder:(context){
        return Container(
          padding: EdgeInsets.all(10.0),
          child: ListView(
            shrinkWrap: true,
            children: [
              SizedBox(
                height: 250,
                child: new VlcPlayer(
                  controller: vlcPlayerController,
                  aspectRatio: 16 / 9,
                  url: url,
                  isLocalMedia: false,
                  placeholder: Container(
                    height: 250.0,
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: <Widget>[
                        CircularProgressIndicator(),
                      ],
                    ),
                  ),
                ),
              ),
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceAround,
                mainAxisSize: MainAxisSize.max,
                children: [
                  Flexible(
                    flex: 1,
                    child: FlatButton(
                      onPressed: (){playAndPause();},
                      child: isPlaying ? Icon(Icons.pause_circle_outline) :
                      Icon(Icons.play_circle_outline),
                    ),),
                  Flexible(
                    flex: 3,
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      mainAxisSize: MainAxisSize.max,
                      children: [
                        Text(position),
                        Expanded(
                          child: Slider(
                              value: sliderValue,
                              activeColor: Colors.red,
                              min: 0.0,
                              max: vlcPlayerController.duration == null ? 1.0
                                  : vlcPlayerController.duration.inSeconds.toDouble(),
                              onChanged: (progress){
                                setState(() {
                                  sliderValue = progress.floor().toDouble();
                                });
                                vlcPlayerController.setTime(sliderValue.toInt()* 1000);
                              }
                          ),
                        ),
                        Text(duration),
                      ],
                    ),
                  ),
                ],
              ),
              Divider(height: 1,),
              Row(
                crossAxisAlignment: CrossAxisAlignment.center,
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                children: [
                  Text('Volume Level'),
                  Slider(
                    min: 0,
                    max: 100,
                    value: volume,
                    onChanged: (value){
                      setState(() {
                        volume = value;
                      });

                      vlcPlayerController.setVolume(volume.toInt());
                    },
                  ),
                ],
              ),
              CircularPercentIndicator(
                radius: 180.0,
                lineWidth: 13.0,
                animation: true,
                percent: sliderValue * 100 / vlcPlayerController.duration.inSeconds.toDouble() * 0.01,
                center: new Text(
                  (sliderValue * 100 / vlcPlayerController.duration.inSeconds.toDouble()).toString() + "%",
                  style:
                  new TextStyle(fontWeight: FontWeight.bold, fontSize: 30.0),
                ),
                circularStrokeCap: CircularStrokeCap.round,
                progressColor: Colors.black,
                animateFromLastPercent: true,
              ),
            ],
          ),
        );
      }),
    );
  }
}

 

 

 

 

참고 : github.com/DhanrajNilkanth/FlutterVideoOnline

 

DhanrajNilkanth/FlutterVideoOnline

Contribute to DhanrajNilkanth/FlutterVideoOnline development by creating an account on GitHub.

github.com

www.androidcoding.in/2020/07/25/flutter-circular-progress/

 

Flutter Circular Progress Indicator - AndroidCoding.in

Flutter circular progress is used to display the status of the file being downloaded or being loaded in the background pictorially.

www.androidcoding.in

 

320x100

'프로그래밍 > Flutter-Dart' 카테고리의 다른 글

[Flutter] Provider (1)  (0) 2021.03.24
[Flutter] Login App (2)  (0) 2021.03.24
[Flutter] Custom Horizontal Number Picker  (0) 2021.03.23
[Flutter] Horizontal Number Picker  (0) 2021.03.23
[Flutter] DatePicker (iOS style)  (0) 2021.03.23

댓글