How to auto pause video when scrolling / when the player is not visible on screen in flutter - flutter

I am working with a video player called 'flick video player'. I can play videos fairly okay with default functionality. The problem occurs when I scroll down the screen and the video continues to play in the background. I would like to pause it when it isn't visible, or when a user navigates to a different page on the project app.
The video player that I am using (flick_video_player) has video_player as its dependency.
Answers are much appreciated.
Regards

I think you can use visibility detector for the purpose-
VisibilityDetector(
key: ObjectKey(flickManager),
onVisibilityChanged: (visibility){
if (visibility.visibleFraction == 0 && this.mounted) {
flickManager?.flickControlManager?.pause();//pausing functionality
}
},
child: Container(
child: AspectRatio(
aspectRatio: 1280/720,
child: FlickVideoPlayer(
flickManager: flickManager
),
/*VideoPlayer(
video_controller
),*/
),
),
),
I was working on something similar. For more info like how to play it again and more you can refer this repo- https://github.com/GeekyAnts/flick-video-player/tree/master/example/lib/feed_player
Hope it helped!

Maybe this visibility detector package can help https://pub.dev/packages/visibility_detector

Wrap your list of videos with a NotificationListener and listen to whether the user has started or stopped scrolling. Use this value to either play or pause your video.
Edit: misread your question. This will work for pausing once the user scrolls. If you want to detect whether the video is within the current view, check out ScrollablePositionedList.
return NotificationListener(
onNotification: (notificationInfo) {
if (notificationInfo is ScrollStartNotification) {
// Set a state value to indicate the user is scrolling
}
if (notificationInfo is ScrollEndNotification) {
// Set a state value to indicate the user stopped scrolling
}
return true;
},
child: YourVideos(),
);

This is exactly what you need, inview_notifier_list:
InViewNotifierList(
isInViewPortCondition:
(double deltaTop, double deltaBottom, double vpHeight) {
return deltaTop < (0.5 * vpHeight) && deltaBottom > (0.5 * vpHeight);
},
itemCount: 10,
builder: (BuildContext context, int index) {
return InViewNotifierWidget(
id: '$index',
builder: (BuildContext context, bool isInView, Widget child) {
return Container(
height: 250.0,
color: isInView ? Colors.green : Colors.red,
child: Text(
isInView ? 'Is in view' : 'Not in view',
),
);
},
);
},
);

Related

How to Set the Loading Value for the Circular progresss Indicator like progress percentage for 60 days in flutter?

How to Set the loading value for the Circular progresss indicator like progress percentage in flutter for 60 days-Math formula?I need this stuff for my flutter project,Sorry if i am asking something silly:-)
Note: I'm new to this amazing flutter development.
You can set "completed" rate of a progress indicator like this:
CircularProgressIndicator(value: 0.5)
The above will result in a 50% indicator. All you have to do is use a member as value in a StatefulWidget and use setState to update it according to the desired percentage.
Also you can use it to indicate the progress when loading an image:
Image.network(
'<url>',
height: 50,
loadingBuilder: (BuildContext context, Widget child,
ImageChunkEvent? loadingProgress) {
if (loadingProgress == null) {
return child;
}
return Center(
child: CircularProgressIndicator(
value: loadingProgress.expectedTotalBytes != null
? loadingProgress.cumulativeBytesLoaded /
loadingProgress.expectedTotalBytes!
: null,
),
);
},
)

MiniPlayer shows only when toggling between tabs in Flutter

I have created a Miniplayer in Flutter which looks like this:
Miniplayer(
controller: miniplayerController,
minHeight: 60,
onDismissed: (){
context.read(selectedVideoProvider).state = null;
},
maxHeight: size.height - topPadding - 60,
builder: (height, percentage){
if (selectedVideo == null) {
return const SizedBox.shrink();
}
if (height <= size.width / 16 * 9){
return Row(
children: [
Text('This is a miniplayer'),
IconButton(
onPressed: (){
context.read(selectedVideoProvider).state = null;
},
icon: Icon(Icons.close)
)
],
);
}
return AnotherScreen();
}
);
Also as you can see I have a selectedVideoProvider StateProvider (I use flutter_riverpod for a state management). Also I wrapped my Miniplayer with a Visibility widget:
Consumer(
builder: (context, watch, _){
final selectedVideo = watch(selectedVideoProvider).state;
return Visibility(maintainState: true, visible: selectedVideo != null, child: MyMiniplayerWidget());
}
),
Here is the screen of the app:
Miniplayer appears when I click on these pictures in my ListView. When I click for the first time everything works great (miniplayer appears properly). However when i dismiss my miniplayer I can not open a new miniplayer by clicking on another picture. Only when i go to another tab (tabs are on my bottom navigation bar) and then go back to this screen the miniplayer appears with the MIN size:
But I want it to pop up when I click on the pictures. And again, when I click on the picture for the first time everything works great.
What is wrong with my code? Why miniplayer appears only when I toggle between tabs?
PS. if I make maintainState = false in my Visibility widget miniplayer appears immediately after clicking on the picture, however it appears with the MIN size, but I want it to appear in MAX size. Could you please also explain me why it doesn't work, if I make
context.read(miniPlayerControllerProvider).state.animateToHeight(state: PanelState.MAX);
this when I click on the picture (this is a StateProvider for my miniplayerController) (this line of code makes my miniplayer appear with MAX size when I click on the picture when maintainState = true in Visibility widget)?
I had the same problem with miniplayer and solved it with the following code:
Miniplayer(
valueNotifier: ValueNotifier(MediaQuery.of(context).size.height),

Flutter Image assets and Stream values only render after user interactions

When opening the application for the first time images and stream values are not rendering until I tap on the screen or start scrolling. Made sure that the snapshot.data is printing out the correct values before returning the widget in the stream builder.
Row(
mainAxisSize: MainAxisSize.min,
children: [
Image.asset(
'assets/profile_image.png',
height: 36.0,
width: 36.0,
),
SizedBox(width: 10.0),
StreamBuilder<String>(
stream: context.read<UserBloc>().balanceStream,
builder: (context, snapshot) {
print('ConnectionState is ${snapshot.connectionState}');
switch (snapshot.connectionState) {
case ConnectionState.active:
print('Value is ${snapshot.data}');
return NonScalingTextView(
"\$ ${snapshot.data}",
style: TitleTiny,
);
break;
default:
return Container();
}
},
),
],
);
Performing some user interaction or hot reloading or hot restarting the application after first launch, the widgets render as expected.
I had an Authentication Bloc parenting the Material App. Inside I had a User Bloc created on successful Auth. I had the above issues when this was the case. The issue was only happening on the Widgets rendered based on the states emitted by the User Bloc. So rather than returning these widgets on state changes I changed my listener to navigate to these widgets on state changes. Now in order to call on my User Bloc from this navigated route, I had to move the User Bloc on top of the Material App. And doing this solved my issue.
This solved it but I still don't know what caused the former architecture to fail. If anyone can explain me, it'd be great.

Lost FloatingActionButton State when change Portrait to Landsacpe

I'm building an apps, that contain floatingactionbutton which I made with my own custom, when it pressed it shows 3 menu icons below it.
There are 2 problems:
When the orientation change to landscape, and we press floatingactionbutton it won't show instead of it will show when we press long, continue no 2
In current landscape it shows with long press like I said in no 1, and when we back again to portrait it need long press again to make it show
I've been trying some ways to make it fix, but it still doesn't work.
Here's the code and screenshot
When portrait menu show up
When changing to landscape, menu icons are missing and need long press to make it show
for floatingActionButton
floatingActionButton: OrientationBuilder(
builder: (BuildContext context, Orientation orientation){
return orientation == Orientation.landscape
? _buildMenu(context)
: _buildMenu(context);
},
),
_buildMenu() that call floatingActionButton
Widget _buildMenu(BuildContext context){
final icons = [ Icons.swap_vert, Icons.check_circle_outline, Icons.filter_list ];
var nowOrientation = MediaQuery.of(context).orientation;
var b = Container(
child: LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints){
return OverlayBuilder(
showOverlayTrue: true,
overlayBuild: (BuildContext overlayContext){
RenderBox box = context.findRenderObject() as RenderBox;
final center = box.size.center(box.localToGlobal(const Offset(0.8, 0.8)));
return new Positioned(
top: Offset(center.dx, center.dy - icons.length * 35.0).dy,
left: Offset(center.dx, center.dy - icons.length * 35.0).dx,
child: new FractionalTranslation(
translation: const Offset(-0.5, -0.6),
child: FabIcons(
icons: icons,
),
),
);
},
);
},
),
);}
To make it simple in viewing I put some code on github
OverlayBuilder Class https://github.com/ubaidillahSriyudi/StackOverflowhelp/blob/master/OverlayBuilderClass
Fabicons Class
https://github.com/ubaidillahSriyudi/StackOverflowhelp/blob/master/FabIcons
Thanks so much to someone that could help it
Happens because every time you change orientation, your FloatingActionButton rebuilds and loses state.
You should find a way to save the state of FabIcons widget.
Simple solution :
Constructing FabIcons widget with
icons,
iconTapped;
These variables should be saved in the Parent Widget, so every time you call _buildMenu(context); you pass in those variables

Flutter app freezes when a TextField or TextFormField is selected

I have a Flutter app that is functioning properly in all respects except when I select a TextField (or TextFormField). When I select the TextField, the cursor blinks in the TextField, but I can't type anything AND all other buttons like the floatingActionButton and the back button in the AppBar quit working. Essentially, the app appears to be frozen, but I don't get any error messages.
After numerous attempts to fix the problem in two different pages that contain FocusNodes and TextEditingControllers, I went back to square one by incorporating a new page with code straight from Flutter's website, but the TextField in this barebones code still locks up the app.
import 'package:flutter/material.dart';
class EventDetailForm extends StatefulWidget {
static const String routeName = "/events/event-detail-form";
#override
_EventDetailFormState createState() => _EventDetailFormState();
}
class _EventDetailFormState extends State<EventDetailForm> {
final myController = TextEditingController();
#override
void dispose() {
myController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Event Detail')),
body: Padding(
padding: const EdgeInsets.all(16),
child: TextField(
controller: myController,
)),
floatingActionButton: FloatingActionButton(
onPressed: () {
return showDialog(
context: context,
builder: (context) {
return AlertDialog(
content: Text(myController.text),
);
});
},
child: Icon(Icons.text_fields),
),
);
}
}
Unfortunately, I am not getting any error messages. The cursor just blinks in the TextField and everything else loses function and I have to quit and restart. I am not sure what else I should be considering. Does anyone have any ideas on what might be causing this?
Simulator -> Device -> Erase All Content And Settings works for me.
Had same problem when I upgraded Xcode to ios 13.1. I switched to a different simulator, and the problem went away.
This maybe late, but it happened to me too just today. I also changed the channel to beta but unfortunately did not work too. Apparently what worked for me is when I restarted the simulator after I put back the channel to stable.
I had the same bug, solved by switching to the beta channel of Flutter.
In your terminal use
flutter channel beta
flutter upgrade
About channels you can read here https://github.com/flutter/flutter/wiki/Flutter-build-release-channels
I did not change channel, a simple flutter upgrade was enough to fix this problem. I also closed Android Studio and all simulators and when I restarted, the problem was gone.
I think I am late to the party but the issue still exists in 2021.
I tried all the solutions but couldn't fix it. Whatever I was typing in TextField or TextFormField or autocomplete_textfield, the characters were not visible.
I fixed it by opening the Widget as a showGeneralDialog() instead of using Navigator.of(...). Here is the sample code.
await showGeneralDialog(
barrierColor: AppStyle.primaryColor.withOpacity(0.3),
transitionBuilder: (context, a1, a2, widget) {
return Transform.scale(
scale: a1.value,
child: Opacity(opacity: a1.value, child: WidgetScreenToOpen()),
);
},
transitionDuration: Duration(milliseconds: 500),
barrierDismissible: true,
barrierLabel: 'Label',
context: context,
pageBuilder: (context, animation1, animation2) {
return Container();
}).then((result) {
return result;
});