I have a list of videos urls/youtube IDs and a PageView.builder
. I want to load next/previous video according to position in the list. For example:
List videos = ['vid_0', 'vid_1', 'vid_2', 'vid_3', 'vid_4']
if current Playing video is vid_2
, it should reload the next video or previous video of the list based on button event.
Currently when I press next or previous button, the same video is loaded but the PageView
makes pages equal to the length
of list. I am using youtube_video_player package.
Here is my code:
import 'package:flutter/material.dart';
import 'package:youtube_player_flutter/youtube_player_flutter.dart';
void main(){
runApp(WatchVideoLesson());
}
class WatchVideoLesson extends StatefulWidget {
const WatchVideoLesson({Key? key}) : super(key: key);
@override
State<WatchVideoLesson> createState() => _WatchVideoLessonState();
}
class _WatchVideoLessonState extends State<WatchVideoLesson> {
List ytIDs = ['mluJOYd17L8', 'd-RCKfVjFI4', 'xXPuaB7UpB0'];
var playingVideo;
final _pageController = PageController();
late YoutubePlayerController _controller;
bool _isPlayerReady = false;
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
void initState() {
_controller = YoutubePlayerController(
initialVideoId: ytIDs.first,
flags: const YoutubePlayerFlags(
autoPlay: false,
)
);
// TODO: implement initState
super.initState();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
resizeToAvoidBottomInset: true,
appBar: AppBar(
title: Text('Week'),
backgroundColor: Colors.red,
),
body:
Column(
children:[
Expanded(
child: PageView.builder(
physics: const NeverScrollableScrollPhysics(),
controller: _pageController,
itemCount: ytIDs.length,
itemBuilder: (context, index) {
return Column(
children: [
Container(
decoration: const BoxDecoration(
color: Colors.grey,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
ElevatedButton(style: ElevatedButton.styleFrom(
backgroundColor: Colors.red),
onPressed: () {
_pageController.previousPage(duration: Duration(seconds: 1), curve: Curves.ease);
},
child: Icon(Icons.arrow_back_ios_new,)),
SizedBox(width: 10,),
Flexible(child: Text('Video Title', overflow: TextOverflow.ellipsis,)),
SizedBox(width: 10,),
ElevatedButton(style: ElevatedButton.styleFrom(
backgroundColor: Colors.green),
onPressed: () {
_pageController.nextPage(duration: Duration(seconds: 1), curve: Curves.easeInOut);
},
child: Icon(Icons.arrow_forward_ios,)),
],
),
),
SizedBox(height: 20,),
YoutubePlayer(
progressColors: const ProgressBarColors(
playedColor: Colors.red,
handleColor: Colors.green),
controller: _controller,
showVideoProgressIndicator: true,
onReady: (){
_isPlayerReady = true;
},
),
SizedBox(height: 10,),
],
);
}
),
),
]
),
),
);
}
}
Current snippet using the same controller on YoutubePlayer
and my guess this is issue having same video. I separating the widget so that it can have different controller for PageView item.
class WatchVideoLesson extends StatefulWidget {
const WatchVideoLesson({Key? key}) : super(key: key);
@override
State<WatchVideoLesson> createState() => _WatchVideoLessonState();
}
class _WatchVideoLessonState extends State<WatchVideoLesson> {
List ytIDs = ['mluJOYd17L8', 'd-RCKfVjFI4', 'xXPuaB7UpB0'];
var playingVideo;
final _pageController = PageController();
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Column(children: [
Expanded(
child: PageView.builder(
physics: const NeverScrollableScrollPhysics(),
controller: _pageController,
itemCount: ytIDs.length,
itemBuilder: (context, index) {
return Column(
children: [
Container(
decoration: const BoxDecoration(
color: Colors.grey,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.red),
onPressed: () {
_pageController.previousPage(
duration: Duration(seconds: 1),
curve: Curves.ease);
},
child: Icon(
Icons.arrow_back_ios_new,
)),
SizedBox(
width: 10,
),
Flexible(
child: Text(
'Video Title',
overflow: TextOverflow.ellipsis,
)),
SizedBox(
width: 10,
),
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.green),
onPressed: () {
_pageController.nextPage(
duration: Duration(seconds: 1),
curve: Curves.easeInOut);
},
child: Icon(
Icons.arrow_forward_ios,
)),
],
),
),
YTPlayer(ytIDs: ytIDs[index]),
SizedBox(
height: 20,
),
SizedBox(
height: 10,
),
],
);
}),
),
]),
),
);
}
}
class YTPlayer extends StatefulWidget {
final String ytIDs;
const YTPlayer({super.key, required this.ytIDs});
@override
State<YTPlayer> createState() => _YTPlayerState();
}
class _YTPlayerState extends State<YTPlayer> {
late YoutubePlayerController _controller;
bool _isPlayerReady = false;
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
void initState() {
super.initState();
_controller = YoutubePlayerController(
initialVideoId: widget.ytIDs,
flags: const YoutubePlayerFlags(
autoPlay: false,
));
}
@override
Widget build(BuildContext context) {
return YoutubePlayer(
controller: _controller,
progressColors: const ProgressBarColors(
playedColor: Colors.red, handleColor: Colors.green),
showVideoProgressIndicator: true,
onReady: () {
_isPlayerReady = true;
},
);
}
}