영상 플레이와 현재 재생 시간의 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
www.androidcoding.in/2020/07/25/flutter-circular-progress/
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 |
댓글