How can I get my flutter video player to work for Chrome Web, correctly - flutter

I am getting videoplayer overflow. How do I resize my video player, so it correctly works. Error message "A RenderFlex overflowed by 93 pixels on the right" during window resizing.
import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart';
import 'package:provider/provider.dart';
class VolumeManager with ChangeNotifier{
var _volume=50.0;
double get volume=>_volume;
void setVolume({
required double volumeValue,
required VideoPlayerController controller
}){
_volume=volumeValue;
controller.setVolume(_volume);
notifyListeners();
}
}
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Test Video',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home:
ChangeNotifierProvider(create:(context)=>VolumeManager(),child: Test_LoadVideoWidget()),
);
}
}
class Test_LoadVideoWidget extends StatefulWidget {
Test_LoadVideoWidget({Key? key}) : super(key: key);
#override
State<Test_LoadVideoWidget> createState() => _Test_LoadVideoWidgetState();
}
class _Test_LoadVideoWidgetState extends State<Test_LoadVideoWidget> {
late final VideoPlayerController controller;
late final Future<void>initVideo;
#override
void initState() {
// TODO: implement initState
super.initState();
controller=VideoPlayerController.asset("assets/video/butterfly.mp4");
controller.setLooping(true);
initVideo=controller.initialize();
}
#override
void dispose() {
// TODO: implement dispose
controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return FutureBuilder<void>(
future:initVideo,
builder:(context,snapshot){
if (snapshot.connectionState==ConnectionState.done){
return Test_VideoWidget(controller);
}
return Center(child:CircularProgressIndicator());
}
);
}
}
class Test_VideoWidget extends StatelessWidget {
final VideoPlayerController controller;
Test_VideoWidget(this.controller);
void _play(){
if (!controller.value.isPlaying){
controller.play();
}
}
void _pause(){
if (controller.value.isPlaying){
controller.pause();
}
}
#override
Widget build(BuildContext context) {
return Scaffold(appBar: AppBar(title:Text("Test Video",style:Theme.of(context).textTheme.headline2)),
body:
Container(
width:MediaQuery.of(context).size.width,
//height:MediaQuery.of(context).size.height,
padding:EdgeInsets.all(20),child:
Column(
mainAxisAlignment:MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
AspectRatio(aspectRatio: controller.value.aspectRatio,
child:VideoPlayer(controller),
),
Row(children: [
SizedBox(width:200,child:ElevatedButton(onPressed: (){_play();}, child: Text("Play!",style:Theme.of(context).textTheme.button))),
const SizedBox(height:50,width:200),
SizedBox(width:200,child:ElevatedButton(onPressed:(){_pause();}, child:Text("Pause",style:Theme.of(context).textTheme.button))),
],)
,Consumer<VolumeManager>(
builder:(context,manager,_)
=>Slider(
min: 0,
max: 100,
value: manager.volume,
onChanged: (value) =>
{
manager.setVolume(volumeValue: value, controller: controller)
}
),
)
],)
)
);
}
}

solution: I used SingleChildScrollView to solve the horizontal and vertical renderflex overflow errors. I changed the Consumer to use => notation rather than { return notation.
import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart';
import 'package:provider/provider.dart';
class VolumeManager with ChangeNotifier{
var _volume=50.0;
double get volume=>_volume;
void setVolume({
required double volumeValue,
required VideoPlayerController controller
}){
_volume=volumeValue;
controller.setVolume(_volume);
notifyListeners();
}
}
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Test Video',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home:
ChangeNotifierProvider(create:(context)=>VolumeManager(),child: Test_LoadVideoWidget()),
);
}
}
class Test_LoadVideoWidget extends StatefulWidget {
Test_LoadVideoWidget({Key? key}) : super(key: key);
#override
State<Test_LoadVideoWidget> createState() => _Test_LoadVideoWidgetState();
}
class _Test_LoadVideoWidgetState extends State<Test_LoadVideoWidget> {
late final VideoPlayerController controller;
late final Future<void>initVideo;
#override
void initState() {
// TODO: implement initState
super.initState();
controller=VideoPlayerController.asset("assets/video/butterfly.mp4");
//..initialize().then((_){
//controller.play();
//controller.setLooping(true);
setState(() {
});
//});
initVideo = controller.initialize();
}
#override
void dispose() {
// TODO: implement dispose
controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
//return Test_VideoWidget(controller);
return FutureBuilder<void>(
future:initVideo,
builder:(context,snapshot){
if (snapshot.connectionState==ConnectionState.done){
return Test_VideoWidget(controller);
}
return Center(child:CircularProgressIndicator());
}
);
}
}
class Test_VideoWidget extends StatelessWidget {
final VideoPlayerController controller;
Test_VideoWidget(this.controller);
void _play(){
if (!controller.value.isPlaying){
controller.play();
}
}
void _pause(){
if (controller.value.isPlaying){
controller.pause();
}
}
#override
Widget build(BuildContext context) {
return Scaffold(appBar: AppBar(title:Text("Test Video",style:Theme.of(context).textTheme.headline2)),
body:
// controller.value.isInitialized?
Container(
width:MediaQuery.of(context).size.width,
height:MediaQuery.of(context).size.height,
padding:EdgeInsets.all(20),child:
SingleChildScrollView(child:Column(
mainAxisAlignment:MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
AspectRatio(aspectRatio: controller.value.aspectRatio,
child:VideoPlayer(controller),
),
SingleChildScrollView(scrollDirection: Axis.horizontal, child: Row(children: [
SizedBox(width:200,child:ElevatedButton(onPressed: (){_play();}, child: Text("Play!",style:Theme.of(context).textTheme.button))),
const SizedBox(height:50,width:200),
SizedBox(width:200,child:ElevatedButton(onPressed:(){_pause();}, child:Text("Pause",style:Theme.of(context).textTheme.button))),
],))
,Consumer<VolumeManager>(
builder:(context,manager,_)=>
Slider(
min: 0,
max: 50,
value: manager.volume,
onChanged: (value) =>
{
manager.setVolume(volumeValue: value, controller: controller)
}
),
)
],)
)
//:
// Center(child:CircularProgressIndicator()),
));
}
}

Related

Custom Widget revising animation in gridview

I have a custom widget that changes color when tapped inside a gridview. When I scroll to the bottom and scroll back up to the top selected widget its animation is reversed.
I'm pretty sure that it has something to do with the widget being disposed of when out of view but I don't have a solution to overcome it. See my code below:
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Thirty Seconds',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
// Page with the gridview
class MyHomePage extends StatelessWidget {
const MyHomePage({super.key});
#override
Widget build(BuildContext context) {
return Scaffold(
body: GridView.count(
crossAxisCount: 2,
children: List.generate(20, (index) {
return MyCustomWidget(
key: GlobalKey(),
index: index + 1,
);
}),
),
);
}
}
// Custom Widget
class MyCustomWidget extends StatefulWidget {
const MyCustomWidget({
super.key,
required this.index,
});
final int index;
#override
State<MyCustomWidget> createState() => _MyCustomWidgetState();
}
class _MyCustomWidgetState extends State<MyCustomWidget>
with SingleTickerProviderStateMixin {
late AnimationController _animationController;
late Animation<Color?> _colorAnimation;
#override
void initState() {
super.initState();
_animationController = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 300),
);
_colorAnimation = ColorTween(begin: Colors.white, end: Colors.yellow)
.animate(_animationController)
..addListener(() => setState(() {}));
}
#override
void dispose() {
_animationController.dispose();
super.dispose();
}
void _toggleAnimation() {
if (_animationController.isCompleted) {
_animationController.reverse();
} else {
_animationController.forward();
}
}
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
_toggleAnimation();
},
child: Container(
color: _colorAnimation.value,
child: Center(
child: Text("Custom Widget ${widget.index}"),
),
),
);
}
}
GridView dispose the widget that aren't visible on UI. You can use cacheExtent(not suitable for this case) or AutomaticKeepAliveClientMixin on _MyCustomWidgetState.
class _MyCustomWidgetState extends State<MyCustomWidget>
with SingleTickerProviderStateMixin, AutomaticKeepAliveClientMixin {
#override
bool get wantKeepAlive => true;
#override
Widget build(BuildContext context) {
super.build(context);
You may prefer handing it parent widget and passing a bool to check active state or state-management or project level depends on scenario.

While learning flutter using (https://github.com/afitz0/exploration_planner). How to implement the action on the LinearProgressIndicator()?

This code is part of online training of flutter by Google team. The original code can be accessed in https://github.com/afitz0/exploration_planner. I am new on flutter and I´ve got some dificulties to use statefull widget. I still do not have enough confidence. I made some modification on original code to add action to the indicator bar, it works fine but I dont think my solution is ideal...
My question is related to the right way to make a change in the state of the taskitem give an
update on the linearProgressIndicator ? Thanks in advance..
import 'package:flutter/material.dart';
double _percentual = 0; //variable to hold progress bar values from zero to 1 step 0.2
// first comes root run appp
void main() => runApp(MyApp()
//MaterialApp
//Scaffold
//AppBar
//Text
//body: Column
//text, text, text
//image
//Row
//text, text, bttom
//....
);
// second comes materialapp
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Exploration!',
theme: ThemeData(primarySwatch: Colors.blueGrey),
home: MyHomePage(),
);
}
}
//third comes home page describes visual of app
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
late AnimationController controller;
#override
void initState() {
controller = AnimationController(
vsync: this,
)..addListener(() {
setState(() {
controller.value = _percentual;
});
});
super.initState();
}
#override
void dispose() {
controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Space Exploration planner'),
),
body: Column(
children: [
Progress(),
TaskList(),
],
),
);
}
}
class Progress extends StatefulWidget {
const Progress({super.key});
#override
State<Progress> createState() => _ProgressState();
}
class _ProgressState extends State<Progress> {
#override
Widget build(BuildContext context) {
return Column(
children: [
Text('You are this far away from exploring the whole universe'),
LinearProgressIndicator(
value: _percentual,
)
],
);
}
}
class TaskList extends StatelessWidget {
const TaskList({super.key});
#override
Widget build(BuildContext context) {
return Column(
children: [
TaskItem(label: "Load rocket with supplies"),
TaskItem(label: "Launch rocket"),
TaskItem(label: "Circle the home planet"),
TaskItem(label: "Head out to de first moon"),
TaskItem(label: "Launch moon lander #1"),
],
);
}
}
class TaskItem extends StatefulWidget {
final String label;
const TaskItem({Key? key, required this.label}) : super(key: key);
#override
State<TaskItem> createState() => _TaskItemState();
}
class _TaskItemState extends State<TaskItem> {
bool? _value = false;
#override
Widget build(BuildContext context) {
return Row(
children: [
Checkbox(
onChanged: (newValue) => setState(() => {
_value = newValue,
if (_value == true)
{
_percentual = double.parse(
(_percentual + 0.2).toStringAsPrecision(1)),
_ProgressState(),
}
else if (_value == false)
{
_percentual = double.parse(
(_percentual - 0.2).toStringAsPrecision(1)),
_ProgressState(),
},
main(), *//<-- worked like hot-reload but I dont think is the right way to do it.*
}),
value: _value,
),
Text(widget.label),
],
);
}
}

how to unfocus texfield and hide keybaord on paste flutter

I have a textfield on which i mostly paste content so i want to unfocus textfield and hide keybaord on paste so i have achive to handle on paste using textfield selectionControls but the problem is focusing and keybaord which is reopening i have tired all focus methods to unfocus here is my code
import 'package:flutter/material.dart';
main() => runApp(const App());
class App extends StatelessWidget {
const App({super.key});
#override
Widget build(BuildContext context) {
return const MaterialApp(home: Home());
}
}
class Home extends StatelessWidget {
const Home({super.key});
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Padding(
padding: const EdgeInsets.all(8),
child: Center(
child: TextField(
selectionControls: MySelectionControls(
onPaste: () {
print('onPaste');
// FocusManager.instance.primaryFocus?.unfocus();
// Focus.of(context).unfocus();
// FocusScope.of(context).unfocus();
// FocusScope.of(context).requestFocus(FocusNode());
// FocusScopeNode currentFocus = FocusScope.of(context);
// if (!currentFocus.hasPrimaryFocus) {
// currentFocus.focusedChild?.unfocus();
// }
},
),
),
),
),
),
);
}
}
class MySelectionControls extends MaterialTextSelectionControls {
final Function onPaste;
MySelectionControls({required this.onPaste});
#override
Future<void> handlePaste(TextSelectionDelegate delegate) {
onPaste();
return super.handlePaste(delegate);
}
}
Try this one
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return const MaterialApp(
home: Home(),
);
}
}
class Home extends StatefulWidget {
const Home({key});
#override
State<Home> createState() => _HomeState();
}
class _HomeState extends State<Home> {
TextSelectionControls? _textSelectionControls;
#override
void initState() {
// TODO: implement initState
super.initState();
_textSelectionControls = MySelectionControls(onPaste: onPaste);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Padding(
padding: const EdgeInsets.all(8),
child: Center(
child: Column(
children: [
TextField(
selectionControls: _textSelectionControls,
),
],
),
),
),
),
);
}
Future<void> onPaste(final TextSelectionDelegate? delegate) async {
Future.delayed(Duration(milliseconds: 100), () {
FocusScope.of(context).requestFocus(FocusNode());
});
}
}
class MySelectionControls extends MaterialTextSelectionControls {
MySelectionControls({required this.onPaste});
ValueChanged<TextSelectionDelegate> onPaste;
#override
Future<void> handlePaste(TextSelectionDelegate delegate) async {
onPaste(delegate);
return super.handlePaste(delegate);
}
}
I have tested this and its working

Flutter. I'm trying to put a camera widget inside a small container

I am trying to put a full camera in a container that is 255 in height and full in width.
I've tried a lot of tweaking the code below, but I'm not sure how to apply the ratio.
in widget size
Is there no room to fix it with the correct camera aspect ratio?
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:camera/camera.dart';
List<CameraDescription> cameras;
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
cameras = await availableCameras();
runApp(CameraApp());
}
class CameraApp extends StatefulWidget {
#override
_CameraAppState createState() => _CameraAppState();
}
class _CameraAppState extends State<CameraApp> {
CameraController controller;
#override
void initState() {
super.initState();
controller = CameraController(cameras[0], ResolutionPreset.max);
controller.initialize().then((_) {
if (!mounted) {
return;
}
setState(() {});
});
}
#override
void dispose() {
controller?.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
if (!controller.value.isInitialized) {
return Container();
}
return MaterialApp(
home: CameraPreview(controller),
);
}
}
The CameraPreview class cannot be modified according to your height and width. If you try to put the CameraPreview inside a sizedbox OR AspectRatio class, then it will give you a skewed image. The best option to get a preview without skewing the output is to use a stack. Sample code is below:
import 'package:flutter/material.dart';
import 'package:camera/camera.dart';
List<CameraDescription> cameras = List.empty(growable: true);
void main() async {
WidgetsFlutterBinding.ensureInitialized();
cameras = await availableCameras();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'My Flutter Camera',
home: CameraApp(),
);
}
}
class CameraApp extends StatefulWidget {
const CameraApp({Key? key}) : super(key: key);
#override
_CameraAppState createState() => _CameraAppState();
}
class _CameraAppState extends State<CameraApp> {
CameraController controller =
CameraController(cameras[1], ResolutionPreset.max);
#override
void initState() {
super.initState();
controller.initialize().then((_) {
if (!mounted) {
return;
}
setState(() {});
});
}
#override
void dispose() {
controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
if (!controller.value.isInitialized) {
return Container();
}
return Stack(
children: [
CameraPreview(controller),
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
color: Colors.white,
height: (MediaQuery.of(this.context).size.height - 255) / 2,
),
const SizedBox(
height: 255,
),
Container(
color: Colors.white,
height: (MediaQuery.of(this.context).size.height - 255) / 2,
),
],
)
],
);
}
}

Call a setState of a statefull widget from the stateless widget

I have a stateless widget class that has a widget whose movements need to be tracked. I cannot keep this widget inside the stateful widgets as I don't want the state of this widget to be refreshed.
I have the following code.
import 'package:flutter/material.dart';
import 'package:control_pad/control_pad.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
color: Colors.white,
child: Column(
children: <Widget>[
Expanded(
child: JoystickView(
onDirectionChanged: (degree, direction) {
//Change the state here.
},
),
),
Expanded(
child: MyStateFull(),
),
],
),
);
}
}
class MyStateFull extends StatefulWidget {
#override
_MyStateFullState createState() => _MyStateFullState();
}
class _MyStateFullState extends State<MyStateFull> {
double degree = 10;
double direction = 10;
//Call this from the stateless Widget
void changedDirection(degree, direction) {
setState(() {
this.degree = degree;
this.direction = direction;
});
}
#override
Widget build(BuildContext context) {
return Container(
child: Text(
"The degree Moved is $degree and the direction is $direction",
style: TextStyle(fontSize: 25, color: Colors.black),
),
);
}
}
This code produces the following output.
I want the direction and degree values to be changed as the joystick is moved.
Thank You.
I tried it myself and found the solution. This can be done using streams. I will post the code just in case someone needs it in the future.
import 'package:flutter/material.dart';
import 'package:control_pad/control_pad.dart';
class MyStateLess extends StatelessWidget {
StreamController<List<double>> _controller = StreamController<List<double>>();
GlobalKey<_MyStateFullState> statefulKey = new GlobalKey<_MyStateFullState>();
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
JoystickView(
onDirectionChanged: (degree, direction) {
List<double> temp = new List<double>();
temp.add(degree);
temp.add(direction);
_controller.add(temp);
},
),
MyStateFull(stream: _controller.stream, key: statefulKey),
],
);
}
}
class MyStateFull extends StatefulWidget {
final Stream<List<double>> stream;
MyStateFull({Key key, #required this.stream}) : super(key: key);
#override
_MyStateFullState createState() => _MyStateFullState();
}
class _MyStateFullState extends State<MyStateFull> {
double _degree = 0.0;
double _direction = 0.0;
#override
void initState() {
super.initState();
widget.stream.listen((event) {
setState(() {
_degree = event[0];
_direction = event[1];
});
});
}
#override
Widget build(BuildContext context) {
return Container(
child: Text("$_degree, $_direction"),
);
}
}