The Flutter ListView plays the video list ①
- ListView layout
- Video player with ‘start’ text
- Click ‘Start’ to play the video
- Global controller fixes click BUG
- ListView optimization.
Oath to tie the heart of turmoil, eventually tied to the void. The mountains do not swear to the four seasons; The ocean has no promises to a sandy shore. Even the language should be abandoned, between you and me, only clean silence, and existence.
Free reference:
Flutter Wheels: Video AD countdown page
Flutter ListView use
Final result completed today:
Rendering (1.1)
:
Analysis:
- ListView loads text and video
- The ListView Item has a transparent ‘start’ text button
- Click the ‘Start’ text button to start the video, and the ‘Start’ text button disappears
- The ‘Start’ text button has a gradient effect when clicked and disappeared
- When the ListView slides, it says “loading…” Load the animation when it stops
ListView layout
VideoPage ListView code:
@override
Widget build(BuildContext context) {
return Container(
child: buildListView(),
);
}
Widget buildListView(a) {
return ListView.builder(
/ / no cache
cacheExtent: 0.// Load 20 data items
itemCount: 20,
itemBuilder: (BuildContext context, int index) {
returnbuildListViewItems(); });Copy the code
VideoPage ListView Item layout:
Widget buildListViewItems(a) {
return Container(
height: 200,
child: Stack(
children: [
Positioned.fill(
child: Text(
"CV engineers in the making.",
textAlign: TextAlign.center,
),
),
Padding(
padding: EdgeInsets.all(20),
child: VideoItemPageWidget(
// Just pass the current path
url: 'assets/video/kfc.mp4',),),),),); }Copy the code
This code is relatively simple, is a simple ListView layout, video playback reference here
Video player with ‘start’ text
(Normally, it will start to play the image, but I will add the text here to stand out)
VideoItemPageWidget class:
class VideoItemPageWidget extends StatefulWidget {
String url;
///VideoPageEnum. Asset Local video
/// VideoPageEnum.network
VideoPageEnum type;
VideoItemPageWidget({
@required this.url, / / path
this.type = VideoPageEnum.asset, // The default is to pass local video
});
@override
_VideoItemPageWidgetState createState(a) => _VideoItemPageWidgetState();
}
class _VideoItemPageWidgetState extends State<VideoItemPageWidget> {
@override
Widget build(BuildContext context) {
return buildLayout();
}
/* * Video player and controller layout */
Widget buildLayout(a) {
return Stack(
children: [
// Fill the full screen and play the video
Positioned.fill(
child: AspectRatio(
aspectRatio: _controller.value.aspectRatio,
child: VideoPlayer(_controller),
),
),
// Edit transparent text
buildtext(),
],
);
}
bool isCheck = false; //true Play false Do not play
// Edit transparent text
Widget buildtext(a){
Positioned.fill(
// Transparent animation
child: AnimatedOpacity(
// When the button text asks "Start", the current text is not displayed
opacity: isCheck ? 0 : 1,
duration: new Duration(seconds: 1),
child: Container(
color: Colors.grey.withOpacity(0.5),
child: Center(
child: Text(
"Start",
style: TextStyle(fontSize: 20, color: Colors.white),
),
),
),
),
),
}
}
Copy the code
Analysis:
- AnimatedOpacity() changes the current state and opacity according to the isCheck variable
- AnimatedOpacity() : 1 opacity; 0 opacity
- Duration in AnimatedOpacity() sets the animation time
- Video code you don’t have to care very much, are copied official code
Rendering (1.2) :
Clicking start now doesn’t work because we haven’t changed isCheck’s status yet.
Click ‘Start’ to play the video
Next, listen for the start Container button, which is the 0.5 opacity gray screen on the outer layer of the video.
bool isCheck = false; //true Play false Do not playGestureDetector( onTap: () { isCheck = ! isCheck;if (isCheck) {
// Click the start button to start playing
_controller.play();
} else {
// Pause the playback
_controller.pause();
}
setState(() {});
},
child: Container(
......
),
)
Copy the code
Analysis:
- Change the state of isCheck to false if it is true or true if it is false
- Then make it play the video when true and pause the video if not
- Refresh Changes the status of isCheck.
Rendering (1.3)
:
Existing problems:
- When A is clicked to start playing, and when B is clicked to start playing,A’s state does not change to pause
- The state of A has not changed, but also need to click again, so that his state from pause to start, can play
Solution:
- Create the global controller, assign the current state to the global controller when clicking on the video player,
- Then, by determining whether the current state is consistent with the transmitted state,
- Consistent means the same click, inconsistent means different click, if the click on different video,
- So let’s close the last video (pause())
Global controller fixes click BUG
VideoPage class:
// Create a multi-subscription stream
final StreamController<VideoPlayerController> _streamController = new StreamController.broadcast();
// Play controller
VideoPlayerController _videoPlayerController;
@override
void initState(a) {
super.initState();
_streamController.stream.listen((event) {
// Current controller ID! = The identity passed indicates that the new identity is being passed
if(_videoPlayerController ! =null&& _videoPlayerController.textureId ! = event.textureId) {/ / pause
_videoPlayerController.pause();
}
_videoPlayerController = event;
LogUtil.Log(
tagging: "streaminitState", title: "The message is received ${_videoPlayerController. TextureId}");
});
}
Copy the code
VideoItemPageWidget class:
// Global stream controller, used to close the last playback video
StreamController streamController;
VideoItemPageWidget({
@required this.url, / / path
this.streamController,
this.type = VideoPageEnum.asset, // The default is to pass local video
});
Copy the code
When the start button is clicked, the current state is passed to the StreamController to determine by ID whether the next one was clicked.
VideoItemPageWidget class:
GestureDetector( onTap: () { isCheck = ! isCheck;if (isCheck) {
// Click the start button to start playing
if(widget.streamController ! =null) {
widget.streamController.add(_controller);
}
_controller.play();
} else {
// isCheck = false;
// Pause the playback
_controller.pause();
}
setState(() {});
},
child: Container(
child: Text("Start")... ,),Copy the code
With widgets. StreamController. Add (_controller); Passes the current video player state to the global play state.
Then, by monitoring the video player controller, judge whether the current state is playing
@override
void initState(a) {
super.initState();
// Initialize the video playback_controller = ..... (a); _controller.addListener(() {// isCheck Whether the current status is playback
/ / _controller. Value. IsPlaying there is video, if it is True. False if paused.
// If the current flag is in the play state, but the player is no longer playing, change the flag to no play state
if(isCheck && ! _controller.value.isPlaying) { isCheck =false;
LogUtil.Log(tagging: "ischeck", title: '$isCheck'); setState(() {}); }}); }Copy the code
If the current flag is in the play state, but the player is no longer playing, the flag changes to the not play state as the player state changes
Rendering (1.4)
:
ListView optimization.
Listen to the ListView to see whether the current ListView slides or stops
VideoPage class:
bool isScroll = false; // Whether to slide
onNotification: (notification) {
/// Notification type
switch (notification.runtimeType) {
case ScrollStartNotification:
print("Start rolling");
isScroll = false;
break;
case ScrollUpdateNotification:
print("Rolling");
break;
case ScrollEndNotification:
print("Roll stop");
isScroll = true;
setState(() {});
break;
case OverscrollNotification:
print("Scroll to the boundary");
break;
}
return true;
},
child:ListView.builder(.....)
}
VideoItemPageWidget(
url: 'assets/video/kfc.mp4',
isScroll: isScroll,
streamController: _streamController,
),
Copy the code
VideoItemPageWidget class:
// Global stream controller, used to listen to control the video player
StreamController streamController;
// Whether the ListView is sliding
bool isScroll;
VideoItemPageWidget({
@required this.url, / / path
this.streamController,
this.isScroll, // Whether to play
this.type = VideoPageEnum.asset, // The default is to pass local video
});
@override
Widget build(BuildContext context) {
/* Widget. isScroll is currently scrolling */
return widget.isScroll
? Center(
child: Text("Loading..."),// Video player page
: buildLayout();
}
Copy the code
This code is very simple, by listening to the ListView slide, and then using the isScroll variable to identify whether the current slide, pass the variable to the layout to control, if the slide is showing the ‘loading’ layout, if not the slide display video player page layout
Rendering (1.5) :
The next chapter :Flutter knowledge :ListView
Contents involved:
Flutter Wheels: Video AD countdown page
Flutter ListView use
The complete code
Original is not easy, your thumbs up is my biggest support, leave your thumbs up ~
\
The following is my official account. I usually post some knowledge about Andorid and FLUTTER. It is mainly used to record some knowledge about flutter during work development