Reputation: 1957
sample screen of video player attached below How can i make video player to play dynamically , while onclick of list play video by passing the video URL?
while on click i have passed URL and tried to reinitialise and start play its not working ,state not changing
Here is my code,
videoplayerscreen.dart,
class VideoPlayerScreen extends StatefulWidget {
int playBackTime;
int playBackTotalTime;
String setPlayTime;
String setPlayDuration;
double aspectRatio;
String videoUrl;
bool isForward;
bool isFullScreen;
bool allowFullScreen;
bool showControls;
bool isAutoPlay;
int startWithinSeconds;
VideoPlayerScreen({
Key key,
this.playBackTime = 0,
this.playBackTotalTime = 0,
this.setPlayTime = "00:00",
this.setPlayDuration = "00:00",
this.aspectRatio = 16 / 9,
this.videoUrl =
"",
this.isForward = true,
this.isFullScreen = false,
this.allowFullScreen = false,
this.showControls = true,
this.isAutoPlay = false,
this.startWithinSeconds = 0,
}) : super(key: key);
@override
_VideoPlayerScreenState createState() => _VideoPlayerScreenState();
}
class _VideoPlayerScreenState extends State<VideoPlayerScreen> {
VideoPlayerController _controller;
void initPlayer() async {
_controller = VideoPlayerController.network(widget.videoUrl);
await _controller.initialize();
_controller.setLooping(true);
_controller.seekTo(Duration(seconds: widget.startWithinSeconds));
if (widget.isAutoPlay) {
_controller.play();
}
_controller.addListener(() {
setState(() {
widget.playBackTime = _controller.value.position.inSeconds;
widget.setPlayTime = timeFormatter(widget.playBackTime);
});
});
}
@override
void initState() {
initPlayer();
super.initState();
}
@override
void dispose() {
_controller.dispose();
SystemChrome.setPreferredOrientations([
DeviceOrientation.landscapeRight,
DeviceOrientation.landscapeLeft,
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);
super.dispose();
}
In Config,
video_player: ^0.10.5
Calling in Other class CourseDetails.dart ,
Container(
padding: EdgeInsets.only(left: 20.0, right: 20.0),
child: ClipRRect(
borderRadius: BorderRadius.circular(8.0),
child: _playUrl != null
? VideoPlayerScreen(videoUrl: _playUrl)
: Image.asset(
'assets/images/test_video_player_screen.png'),
),
)
GestureDetector(
**here i am changing the state **
onTap: () {
setState(() {
_playUrl = videoLists['course_video_url'];
});
},
child: Padding(
padding:
EdgeInsets.only(left: 10.0, right: 20.0, top: 2.0, bottom: 5.0),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Text(
"${videoLists['sn_no']}",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.black45,
fontFamily: 'Oswald-SemiBold'),
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: EdgeInsets.only(left: 10.0),
child: Text(
"${videoLists['course_video_title']}",
textAlign: TextAlign.left,
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
color: Colors.black45,
fontFamily: 'Oswald-SemiBold'),
),
),
Row(
children: <Widget>[
Padding(
padding: EdgeInsets.only(left: 10.0),
child: Text(
"Video - ${videoLists['course_video_duration']}",
textAlign: TextAlign.left,
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.bold,
color: Colors.grey,
fontFamily: 'Oswald-SemiBold'),
),
),
Padding(
padding: EdgeInsets.only(left: 5.0),
child: videoLists['course_watched']
? Image.asset(
'assets/images/green_tick_icon.png',
width: 12.0,
height: 12.0,
)
: null),
],
),
],
),
],
),
),
)
Upvotes: 3
Views: 12869
Reputation: 555
@Jai Techie I think you have already found the solution, But I will add some more explanation to it for those who still have got some errors using the video_player package.
Actually, when we are loading another video from the list of videos using network URLs, we create another instance of our videoController and initialize it without destroying the previous one.
Another big issue is that The video_player plugin fails to play videos after playing successfully 10-15 times stated here on GitHub video_player issue/24565.
First of all, we will use a Chewie Wrapper Package which is a wrapper package around the video_player package.
/// initialize the videoController
void _initController(String link) {
_videoController = VideoPlayerController.network(link)
..initialize().then((_) {
setState(() {});
//do what you want.
_videoController?.play();
});
chewieController = ChewieController(
videoPlayerController: _videoController!,
);
}
Future<void> _startVideoPlayer(String link) async {
if (_videoController == null && chewieController == null) {
// If there was no controller, just create a new one
_initController(link);
} else {
// If there was a controller, we need to dispose of the old one first
final oldController = _videoController;
final oldChewieController = chewieController;
// Registering a callback for the end of the next frame
// to dispose of an old controller
// (which won't be used anymore after calling setState)
WidgetsBinding.instance.addPostFrameCallback((_) async {
await oldController?.dispose();
oldChewieController?.dispose();
// Initing new controller
_initController(link);
});
//Make sure that the controller is not used by setting it to null
setState(() {
_videoController = null;
});
}
}
Now call this method from your initState
_startVideoPlayer('your URL here')
And also call it from your listview (list of videos) onTap property
_startVideoPlayer(listOfVideos[index].URLS.toString())
Just Create a method _startVideoPlayer() where it will check if videoController is initialized or not. If videoController is not initialized it will call the initController(), if it is already initialized, first we have to dispose() of that videoController after disposing of it then initialize the new one.
I hope it will work.
Upvotes: 0
Reputation: 1201
You can use didUpdateWidget
method.
We can compare any property of the Widget class and according to that reset the player.
For resetting, general steps would be
Below is the code snippet for logic.
class _VideoPlayerScreenState extends State<VideoPlayerScreen> {
VideoPlayerController _controller;
void initPlayer() async {
/// initialise player
}
void disposePlayer() {
/// dispose player
}
void resetPlayer() {
disposePlayer();
initPlayer();
}
@override
void initState() {
initPlayer();
super.initState();
}
@override
void didUpdateWidget(VideoPlayerScreen oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.videoUrl != widget.videoUrl) {
resetPlayer();
}
}
@override
void dispose() {
disposePlayer();
super.dispose();
}
}
Reference for didUpdateWidget method.
Upvotes: 0
Reputation: 1957
Thanks for all the replies. I got the solution:
In Build
Function, I have checked if any url changes happened or not. If changes happened, I disposed old controller and I reinitialized video controller. Then, it works fine for me.
@override
Widget build(BuildContext context) {
if (currentObjectVideoUrl != widget.videoUrl) {
_controller.dispose();
initPlayer();
}
}
Upvotes: 4
Reputation: 996
You can achieve this by creating a stateful widget passing a URL. Then inside the init method, you can do this
class ViewVideo extends StatefulWidget {
final link;
ViewVideo(this.link);
@override
_ViewVideoState createState() => _ViewVideoState(this.link);
}
class _ViewVideoState extends State<ViewVideo> {
final link;
_ViewVideoState(this.link);
@override
void initState() {
super.initState();
//Write your video player code here
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(),
);
}
@override
void dispose() {
//Here you can close the video player
super.dispose();
}
}
Upvotes: 1
Reputation: 9635
I've modified my response based on your comments. You just need to have your video url on a class variable that you change with the setState. Then on your Widgets have a check for the presence of the variable and decide to show the VideoPlayerScreen
widget or an empty box.
String videoUrl = '';
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
videoUrl == '' ? SizedBox() : VideoPlayerScreen(videoUrl: videoUrl),
RaisedButton(
onPressed: () {
setState((){
videoUrl == videoLists['course_video_url'];
});
}
),
],
);
}
Upvotes: 0