Invalid Image Dimensions in Flutter when taking a video snapshot - image

I have a flutter app, which streams video from an ESP32 Camera. The code I am interested in should take a snapshot of the image. However, when I press the button, I get the error below.
I have tried changing the resolution in the code and also the resolution on the camera sending the stream. Both gave me the same error.
Can anyone help me, please?
E/flutter (22722): [ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: Exception: Invalid image dimensions.
E/flutter (22722): #0 Scene.toImage (dart:ui/compositing.dart:28:7)
E/flutter (22722): #1 OffsetLayer.toImage (package:flutter/src/rendering/layer.dart:1208:26)
E/flutter (22722): #2 RenderRepaintBoundary.toImage (package:flutter/src/rendering/proxy_box.dart:2960:24)
E/flutter (22722): #3 _HomeState.takeScreenShot (package:traincam/main.dart:173:32)
E/flutter (22722): #4 _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:993:19)
E/flutter (22722): #5 _InkResponseState.build.<anonymous closure> (package:flutter/src/material/ink_well.dart:1111:38)
E/flutter (22722): #6 GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:183:24)
E/flutter (22722): #7 TapGestureRecognizer.handleTapUp (package:flutter/src/gestures/tap.dart:598:11)
E/flutter (22722): #8 BaseTapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:287:5)
E/flutter (22722): #9 BaseTapGestureRecognizer.handlePrimaryPointer (package:flutter/src/gestures/tap.dart:222:7)
E/flutter (22722): #10 PrimaryPointerGestureRecognizer.handleEvent (package:flutter/src/gestures/recognizer.dart:476:9)
E/flutter (22722): #11 PointerRouter._dispatch (package:flutter/src/gestures/pointer_router.dart:77:12)
E/flutter (22722): #12 PointerRouter._dispatchEventToRoutes.<anonymous closure> (package:flutter/src/gestures/pointer_router.dart:122:9)
E/flutter (22722): #13 _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:377:8)
E/flutter (22722): #14 PointerRouter._dispatchEventToRoutes (package:flutter/src/gestures/pointer_router.dart:120:18)
E/flutter (22722): #15 PointerRouter.route (package:flutter/src/gestures/pointer_router.dart:106:7)
E/flutter (22722): #16 GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:358:19)
E/flutter (22722): #17 GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:338:22)
E/flutter (22722): #18 RendererBinding.dispatchEvent (package:flutter/src/rendering/binding.dart:267:11)
E/flutter (22722): #19 GestureBinding._handlePointerEvent (package:flutter/src/gestures/binding.dart:295:7)
E/flutter (22722): #20 GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:240:7)
E/flutter (22722): #21 GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:213:7)
E/flutter (22722): #22 _rootRunUnary (dart:async/zone.dart:1206:13)
E/flutter (22722): #23 _CustomZone.runUnary (dart:async/zone.dart:1100:19)
E/flutter (22722): #24 _CustomZone.runUnaryGuarded (dart:async/zone.dart:1005:7)
E/flutter (22722): #25 _invoke1 (dart:ui/hooks.dart:265:10)
E/flutter (22722): #26 _dispatchPointerDataPacket (dart:ui/hooks.dart:174:5)
Here is the code:
import 'dart:ui';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:gesture_zoom_box/gesture_zoom_box.dart';
import 'package:web_socket_channel/io.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
import 'package:save_in_gallery/save_in_gallery.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData.dark(),
title: "Train Cam",
home: Home(
channel: IOWebSocketChannel.connect('ws://192.168.1.213:8888'),
)
);
}
}
class Home extends StatefulWidget {
final WebSocketChannel channel;
Home({Key key, #required this.channel}) : super (key: key);
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
final videoWidth = 640;
final videoHeight = 480;
double newVideoSizeWidth = 640;
double newVideoSizeHeight = 480;
bool isLandscape = false;
String _timeString;
var _globalKey = new GlobalKey();
final _imageSaver = ImageSaver();
#override
void initState() {
super.initState();
isLandscape = false;
}
#override
void dispose() {
widget.channel.sink.close();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: OrientationBuilder(
builder: (context, orientation) {
var screenWidth = MediaQuery.of(context).size.width;
var screenHeight = MediaQuery.of(context).size.height;
if (orientation == Orientation.portrait) {
//screenWidth < screenHeight
isLandscape = false;
newVideoSizeWidth =
screenWidth > videoWidth ? videoWidth : screenWidth;
newVideoSizeHeight =
videoHeight * newVideoSizeHeight / screenWidth;
}
else {
isLandscape = true;
newVideoSizeHeight =
screenHeight > videoHeight ? videoHeight : screenHeight;
newVideoSizeWidth =
videoWidth * newVideoSizeHeight / videoHeight;
}
return Container(
color: Colors.black,
child: StreamBuilder(
stream: widget.channel.stream,
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
),
);
} else {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Column(
children: [
SizedBox(
height: isLandscape ? 0 : 30,
),
Stack(
children: <Widget>[
RepaintBoundary(
key: _globalKey,
),
GestureZoomBox(
maxScale: 5.0,
doubleTapScale: 2.0,
duration: Duration(milliseconds: 200),
child: Image.memory(
snapshot.data,
gaplessPlayback: true,
width: newVideoSizeWidth,
height: newVideoSizeWidth,
),
),
Positioned.fill(
child: Align(
child: Column(
children: <Widget>[
SizedBox(
height: 16,
),
Text('Train Cam', style: TextStyle(fontSize: 14, fontWeight: FontWeight.w300),),
SizedBox(
height: 8,
),
Text('Live | $_timeString', style: TextStyle(fontSize: 12, fontWeight: FontWeight.w300),),
]
),
alignment: Alignment.topCenter,
))
],
),
Expanded(flex: 1,
child: Container(
color: Colors.black,
width: MediaQuery.of(context).size.width,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 16),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
IconButton(icon: Icon(Icons.videocam, size: 24,), onPressed: () { },),
IconButton(icon: Icon(Icons.photo_camera, size: 24,), onPressed: takeScreenShot,),
IconButton(icon: Icon(Icons.mic, size: 24,), onPressed: () { },),
IconButton(icon: Icon(Icons.speaker, size: 24,), onPressed: () { },),
IconButton(icon: Icon(Icons.add_alert, size: 24,), onPressed: () { },)
],
),
)
),)
],
),
],
);
}
},
),
);
}
)
);
}
takeScreenShot()async{
RenderRepaintBoundary boundary = _globalKey.currentContext.findRenderObject();
var image = await boundary.toImage();
var byteData = await image.toByteData(format: ImageByteFormat.png);
var pngBytes = byteData.buffer.asUint8List();
final res = await _imageSaver.saveImage(imageBytes: pngBytes);
Fluttertoast.showToast(msg: res? "Screenshot saved" : "Screenshot failed!",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 16.0);
}
}

Invalid Image Dimensions in Flutter when taking a video snapshot,
Which means you need to set constraints for the error widget
For example:
I have the same problem with the following code:
Widget carIconImage =
Image.asset(BYDConstants().getBydImageHome("box.png"));
Wrapped with Container with width and height, them problem solve.
Widget carIconImage =
Container(width:30,height:30,child: Image.asset(BYDConstants().getBydImageHome("box.png")),);

Related

Flutter with UI Avatar returning invalid image

I am working on pulling my user profiles into my flutter app, but for some reason I am getting image invalid when using Image.Network when the user's profile photo is coming from ui-avatars.com, it works fine when it is just returning a jpg.
FutureBuilder<User>(
future: futureUser,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Image.network(
snapshot.data!.profilePhotoUrl,
fit: BoxFit.cover,
width: 90,
height: 90,
);
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
}
// By default, show a loading spinner.
return const CircularProgressIndicator();
},
),
For reference here is the URL that is being returned in the users profile from ui-avatars: https://ui-avatars.com/api/?name=m&color=7F9CF5&background=EBF4FF
Error in console:
Exception caught by image resource service
The following _Exception was thrown resolving an image codec:
Exception: Invalid image data
When the exception was thrown, this was the stack:
#0 _futurize (dart:ui/painting.dart:5886:5)
#1 ImageDescriptor.encoded (dart:ui/painting.dart:5741:12)
#2 instantiateImageCodecFromBuffer (dart:ui/painting.dart:2092:60)
#3 PaintingBinding.instantiateImageCodecFromBuffer (package:flutter/src/painting/binding.dart:153:15)
#4 NetworkImage._loadAsync (package:flutter/src/painting/_network_image_io.dart:135:22)
<asynchronous suspension>
Image provider: NetworkImage("https://ui-avatars.com/api/?name=m&color=7F9CF5&background=EBF4FF", scale: 1.0)
Image key: NetworkImage("https://ui-avatars.com/api/?name=m&color=7F9CF5&background=EBF4FF", scale: 1.0)
Test Screen
import 'package:flutter/material.dart';
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Welcome to Test',
home: Scaffold(
appBar: AppBar(
title: Text('Test'),
),
body: Image.network(
'https://ui-avatars.com/api/?name=m&color=7F9CF5&background=EBF4FF',
fit: BoxFit.cover,
width: 90,
height: 90,
),
),
);
}
}
Any help would be greatly appreciated, I am fairly new to Flutter.

Flutter images download again on navigator pop

Hi i have a problem with a stream of images in flutter, when i do a Navigator.push() and then Navigator.pop() the images of the stream gets reload.
My Class is a Stateful Widget with AutomaticKeepAliveClientMixin
When images gets donwloaded
After a Navigator.push() and then Navigator.pop()
I use riverpod for the stream and Firebase Storage.
Expanded(
child: watch(userEventsFamilyStream(user.uid)).maybeWhen(
data: (events) {
if (events.isEmpty) {
return EmptyGrid(
onTap: () => context
.read(menuNotifier)
.currentIndex = 1);
}
return Stack(
children: [
GridView.count(
crossAxisCount: 3,
children: [
...events.map((event) {
return EventItem(
uid: event.uid,
imgUrl: event.imgUrl,
onTap: () async {
final result =
await buildOptions(context);
_handleResult(
context, result, actions, event);
},
);
}).toList()
],
),
if (state.isSubmitting)
Container(
decoration: const BoxDecoration(
color: Colors.black54),
width: MediaQuery.of(context).size.width,
child: const Center(
child: CircularProgressIndicator())),
],
);
},
orElse: () =>
const Center(child: CircularProgressIndicator())),
),
I also use cached_network_image package
Hero(
tag: '${uid}profile',
child: FadeInImage(
placeholder: const AssetImage('assets/img/transparent.png'),
image: CachedNetworkImageProvider(imgUrl),
fit: BoxFit.cover,
),
),
if you want to keep the state of the page alive, you may use AutomaticKeepAliveClientMixin
class Foo extends StatefulWidget {
#override
FooState createState() {
return new FooState();
}
}
class FooState extends State<Foo> with AutomaticKeepAliveClientMixin {
#override
Widget build(BuildContext context) {
return Container();
}
#override
bool get wantKeepAlive => true;
}
I solved: the problem was the size of the images, even cached if the image is too big it takes some time to get load.

How to play and control gif with CachedNetworkImage in Flutter?

I'm currently developing an app for deaf people and I need to use many gifs inside my app.
I don't want my gifs to play more than once so I used GifImage which lets me control the number of reproductions and the speed of the gif locally.
Now I realize that with so many gifs, my app will be too heavy to upload to the stores, so I tried using CachedNetworkImage to play my gifs from firebase storage. The problem with this library is that I have no control on the reproduction of the gifs, they play infinitely.
What I have already tried:
Play gif from local file:
GifImage(
controller: controller,
image: AssetImage('test.gif'),
)
Play gif using CachedNetworkImage:
CachedNetworkImage(
imageUrl:
'https://firebasestorage.googleapis.com/v0/b/app-lsc-7310d.appspot.com/o/test.gif?alt=media',
fit: BoxFit.cover,
width: MediaQuery.of(context).size.width * 0.5,
placeholder: (context, url) => CircularProgressIndicator(),
errorWidget: (context, url, error) => Icon(Icons.error),
),
I want to know if it is possible to use both libraries together so I can store the gifs in the cache and also have control over them, like so:
CachedNetworkImage(
imageUrl:
'https://firebasestorage.googleapis.com/v0/b/app-lsc-7310d.appspot.com/o/test.gif?alt=media',
imageBuilder: (context, imageProvider) => GifImage(
controller: controller,
image: imageProvider,
),
placeholder: (context, url) => CircularProgressIndicator(),
errorWidget: (context, url, error) => Icon(Icons.error),
),
But I get the following error:
[VERBOSE-2:shell.cc(242)] Dart Unhandled Exception: NoSuchMethodError: The getter 'buffer' was called on null.
Receiver: null
Tried calling: buffer, stack trace: #0 Object.noSuchMethod (dart:core-patch/object_patch.dart:54:5)
#1 fetchGif (package:flutter_gifimage/flutter_gifimage.dart:243:76)
#2 GifImageState.didChangeDependencies (package:flutter_gifimage/flutter_gifimage.dart:158:7)
#3 StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:4653:11)
#4 ComponentElement.mount (package:flutter/src/widgets/framework.dart:4469:5)
#5 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3541:14)
#6 Element.updateChild (package:flutter/src/widgets/framework.dart:3303:20)
#7 SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:5981:14)
#8 Element.updateChild (package:flutter/src/widgets/framework.dart:3293:15)
#9 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4520:16)
#10<…>
Here is the full code in case you want to try it out:
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
GifController controller;
String currentGif = 'test';
double frameNum = 25.0;
void initState() {
controller = GifController(vsync: this);
super.initState();
}
playGif(String gifToPlay) async {
controller.value = 0;
controller.animateTo(frameNum - 1,
duration: Duration(milliseconds: (160 * (frameNum - 1)).toInt()));
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Giphy'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
CachedNetworkImage(
imageUrl:
'https://firebasestorage.googleapis.com/v0/b/app-lsc-7310d.appspot.com/o/test.gif?alt=media',
fit: BoxFit.cover,
width: MediaQuery.of(context).size.width * 0.5,
placeholder: (context, url) => CircularProgressIndicator(),
errorWidget: (context, url, error) => Icon(Icons.error),
),
SizedBox(
height: 20.0,
),
Card(
child: GifImage(
controller: controller,
image: AssetImage('images/test.gif'),
),
elevation: 7,
),
SizedBox(
height: 20.0,
),
GestureDetector(
onTap: () {
playGif(currentGif);
},
child: Container(
color: Colors.blueGrey,
padding: EdgeInsets.all(5.0),
child: Text(
'Play Local Gif',
style: TextStyle(fontSize: 20),
),
),
),
],
),
),
);
}
}
I am open to other suggestions as well and would be really grateful for your help.

Flutter 2 second shows error when page load and ater 2 secons successfully shows

Hello Any One Flutter Expert here ?? plz help meee...what i want to make is Like Facebook photo viewer when user slides images and check is this like or not same i want in my code...
i made my code in that i come from listing page and when i tap on listing i can see full screen image.. and i Can slide(Scroll) images...
BUTTT when i comes first time on this screen which i code it show me some bugs on screen for 3,4 seconds...after that i can see the image plz help mee and show my error
Future<PhotoDetail> pagedetail() async {
sharedPreferences = await SharedPreferences.getInstance();
Map data = {
"AccessToken": sharedPreferences.getString("AccessToken"),
"CustomerId": sharedPreferences.getInt("CustomerId"),
"ImageId": indexx == null ? widget.images[widget.currentindex].photoId : indexx
};
print(data);
final http.Response response = await http.post(
Constants.CUSTOMER_WEBSERVICE_URL + "/photo/detail",
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
body: jsonEncode(data),
);
var jsonResponse = json.decode(response.body);
if (response.statusCode == 200) {
print("Response status : ${response.statusCode}");
print("Response status : ${response.body}");
isLike = jsonResponse["IsLike"]; //here i saving value when api is run
print("iSLiked Value:" +isLike.toString()); // value is printing here
return PhotoDetail.fromJson(json.decode(response.body));
} else {
throw Exception('Failed to load data');
}
}
Future<PhotoDetail> _photoDetail;
#override
void initState() {
_photoDetail = pagedetail();
setState(() {
pagedetail(); //here is my api run when page is load
});
super.initState();
}
void pageChange(int index){ //this method is when i scroll page
setState(() {
pagedetail(); // api is call again and again
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
extendBodyBehindAppBar: true,
body: Stack(
children: <Widget>[
Container(
child:
Center(
child: PhotoViewGallery.builder(
itemCount: widget.images.length,
builder: (BuildContext context , int index) {
return PhotoViewGalleryPageOptions(
imageProvider:
NetworkImage(widget.images[index].photoPreviewImagePath),
maxScale: PhotoViewComputedScale.covered * 1.8,
minScale: PhotoViewComputedScale.contained * 1.0,
);
},
pageController: _pageController,
enableRotation: false,
scrollDirection: Axis.horizontal,
onPageChanged: pageChange,
loadingBuilder: (BuildContext context , ImageChunkEvent event){
return Center(child: CircularProgressIndicator(),);
},
)
)
),
Positioned(
bottom: 10,
left: 30,
right: 30,
child: (_photoDetail == null) ? Text("error")
: FutureBuilder<PhotoDetail>(
future: _photoDetail,
// ignore: missing_return
builder: (context , snapshot){
int like = snapshot.data.isLike;
int Slection = snapshot.data.selectedCount;
print("like ?????:" +like.toString());
print("Selection ????? :" + Slection.toString());
if (snapshot.hasData){
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
InkWell(
child: InkWell(
Likes();
Fluttertoast.showToast(
msg: "Liked",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
timeInSecForIosWeb: 1,
backgroundColor: Color(0xfff58634),
textColor: Colors.white,
fontSize: 16.0
);
},
child: Icon(Icons.thumb_up,size: 20,color: like == 1 ? Color(0xfff58634) : Colors.white),
),
),
InkWell(
child: Icon(Icons.comment,size: 20,color: Colors.white),
),
InkWell(
onTap: (){
_onShare();
},
child: Icon(Icons.share,size: 20,color: Colors.white,),
),
InkWell(
onTap: (){},
child: Icon(Icons.photo_album,size: 20,color: Slection == 0 ? Colors.white : Color(0xfff58634)),
),
InkWell(
onTap: (){
setState(() {
viewwholike();
});
},
child: Icon(Icons.card_giftcard,size: 20,color:
Colors.white,),
),
]
);
}
else {
Text("error");
}
},
),
),
],
),
);
}
ERROR::════════ Exception caught by widgets library
═══════════════════════════════════════════════════════
The following NoSuchMethodError was thrown building
FutureBuilder<PhotoDetail>(dirty, state:
_FutureBuilderState<PhotoDetail>#ef81b):
The getter 'isLike' was called on null.
Receiver: null
Tried calling: isLike
The relevant error-causing widget was:
FutureBuilder<PhotoDetail>
file:///C:/Users/Hello%20Devloper/AndroidStudioProjects/
September/PhotoGranth-
App/lib/CampaignSinglePhotos.dart:400:15
When the exception was thrown, this was the stack:
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:53:5)
#1 _CampaignSinglePhotosState.build.<anonymous closure>
(package:photogranth2020/CampaignSinglePhotos.dart:404:42)
#2 _FutureBuilderState.build
(package:flutter/src/widgets/async.dart:732:55)
#3 StatefulElement.build
(package:flutter/src/widgets/framework.dart:4619:28)
#4 ComponentElement.performRebuild
(package:flutter/src/widgets/framework.dart:4502:15)
Flutter tells you that data is not ready when you test snapshot.data.isLike.
You should test always at the beginning if snapshot.hasData, only after that you can make all you want.
Otherwise, if snapshot.hasData is false, simply return CircularProgressIndicator() .

Repeating Animation and Adjustments in Flutter

I'm trying to clone the timer of the app I use when I workout: Strong. So far, I've managed to implement all the main features and animations (which aren't many). I know my code is messy and there's probably better ways to implement what I'm trying to do if there are any suggestions on that they're also appreciated. I'm having two problems with my application. 1. When the timer starts I get the following error:
flutter: ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY
╞═══════════════════════════════════════════════════════════
flutter: The following NoSuchMethodError was thrown building Peinture(dirty, state: _PeintureState#82e34):
flutter: The getter 'inMilliseconds' was called on null.
flutter: Receiver: null
flutter: Tried calling: inMilliseconds
flutter:
flutter: When the exception was thrown, this was the stack:
flutter: #0 Object.noSuchMethod (dart:core/runtime/libobject_patch.dart:50:5)
flutter: #1 _PeintureState.build (package:workout_timer/main.dart:241:72)
flutter: #2 StatefulElement.build (package:flutter/src/widgets/framework.dart:3809:27)
flutter: #3 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3721:15)
flutter: #4 Element.rebuild (package:flutter/src/widgets/framework.dart:3547:5)
flutter: #5 StatefulElement.update (package:flutter/src/widgets/framework.dart:3878:5)
flutter: #6 Element.updateChild (package:flutter/src/widgets/framework.dart:2742:15)
flutter: #7 SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:4867:14)
flutter: #8 Element.updateChild (package:flutter/src/widgets/framework.dart:2742:15)
flutter: #9 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3732:16)
flutter: #10 Element.rebuild (package:flutter/src/widgets/framework.dart:3547:5)
flutter: #11 ProxyElement.update (package:flutter/src/widgets/framework.dart:3990:5)
flutter: #12 Element.updateChild (package:flutter/src/widgets/framework.dart:2742:15)
flutter: #13 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3732:16)
flutter: #14 Element.rebuild (package:flutter/src/widgets/framework.dart:3547:5)
flutter: #15 StatelessElement.update (package:flutter/src/widgets/framework.dart:3781:5)
flutter: #16 Element.updateChild (package:flutter/src/widgets/framework.dart:2742:15)
flutter: #17 RenderObjectElement.updateChildren (package:flutter/src/widgets/framework.dart:4585:32)
flutter: #18 MultiChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:4975:17)
flutter: #19 Element.updateChild (package:flutter/src/widgets/framework.dart:2742:15)
flutter: #20 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3732:16)
flutter: #21 Element.rebuild (package:flutter/src/widgets/framework.dart:3547:5)
flutter: #22 ProxyElement.update (package:flutter/src/widgets/framework.dart:3990:5)
flutter: #23 Element.updateChild (package:flutter/src/widgets/framework.dart:2742:15)
flutter: #24 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3732:16)
flutter: #25 Element.rebuild (package:flutter/src/widgets/framework.dart:3547:5)
flutter: #26 ProxyElement.update (package:flutter/src/widgets/framework.dart:3990:5)
flutter: #27 Element.updateChild (package:flutter/src/widgets/framework.dart:2742:15)
flutter: #28 RenderObjectElement.updateChildren (package:flutter/src/widgets/framework.dart:4585:32)
flutter: #29 MultiChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:4975:17)
flutter: #30 Element.updateChild (package:flutter/src/widgets/framework.dart:2742:15)
flutter: #31 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3732:16)
flutter: #32 Element.rebuild (package:flutter/src/widgets/framework.dart:3547:5)
flutter: #33 StatefulElement.update (package:flutter/src/widgets/framework.dart:3878:5)
flutter: #34 Element.updateChild (package:flutter/src/widgets/framework.dart:2742:15)
flutter: #35 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3732:16)
flutter: #36 Element.rebuild (package:flutter/src/widgets/framework.dart:3547:5)
flutter: #37 ProxyElement.update (package:flutter/src/widgets/framework.dart:3990:5)
flutter: #38 Element.updateChild (package:flutter/src/widgets/framework.dart:2742:15)
flutter: #39 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3732:16)
flutter: #40 Element.rebuild (package:flutter/src/widgets/framework.dart:3547:5)
flutter: #41 StatefulElement.update (package:flutter/src/widgets/framework.dart:3878:5)
flutter: #42 Element.updateChild (package:flutter/src/widgets/framework.dart:2742:15)
flutter: #43 SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:4867:14)
flutter: #44 Element.updateChild (package:flutter/src/widgets/framework.dart:2742:15)
flutter: #45 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3732:16)
flutter: #46 Element.rebuild (package:flutter/src/widgets/framework.dart:3547:5)
flutter: #47 StatelessElement.update (package:flutter/src/widgets/framework.dart:3781:5)
flutter: #48 Element.updateChild (package:flutter/src/widgets/framework.dart:2742:15)
flutter: #49 SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:4867:14)
flutter: #50 Element.updateChild (package:flutter/src/widgets/framework.dart:2742:15)
flutter: #51 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3732:16)
flutter: #52 Element.rebuild (package:flutter/src/widgets/framework.dart:3547:5)
flutter: #53 StatefulElement.update (package:flutter/src/widgets/framework.dart:3878:5)
flutter: #54 Element.updateChild (package:flutter/src/widgets/framework.dart:2742:15)
flutter: #55 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3732:16)
flutter: #56 Element.rebuild (package:flutter/src/widgets/framework.dart:3547:5)
flutter: #57 StatefulElement.update (package:flutter/src/widgets/framework.dart:3878:5)
flutter: #58 Element.updateChild (package:flutter/src/widgets/framework.dart:2742:15)
flutter: #59 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3732:16)
flutter: #60 Element.rebuild (package:flutter/src/widgets/framework.dart:3547:5)
flutter: #61 ProxyElement.update (package:flutter/src/widgets/framework.dart:3990:5)
flutter: #62 Element.updateChild (package:flutter/src/widgets/framework.dart:2742:15)
flutter: #63 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3732:16)
flutter: #64 Element.rebuild (package:flutter/src/widgets/framework.dart:3547:5)
flutter: #65 ProxyElement.update (package:flutter/src/widgets/framework.dart:3990:5)
flutter: #66 Element.updateChild (package:flutter/src/widgets/framework.dart:2742:15)
flutter: #67 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3732:16)
flutter: #68 Element.rebuild (package:flutter/src/widgets/framework.dart:3547:5)
flutter: #69 StatefulElement.update (package:flutter/src/widgets/framework.dart:3878:5)
flutter: #70 Element.updateChild (package:flutter/src/widgets/framework.dart:2742:15)
flutter: #71 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3732:16)
flutter: #72 Element.rebuild (package:flutter/src/widgets/framework.dart:3547:5)
flutter: #73 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2286:33)
flutter: #74 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding&WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:676:20)
flutter: #75 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:219:5)
flutter: #76 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:990:15)
flutter: #77 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:930:9)
flutter: #78 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:842:5)
flutter: #79 _invoke (dart:ui/hooks.dart:154:13)
flutter: #80 _drawFrame (dart:ui/hooks.dart:143:3)
flutter: ════════════════════════════════════════════════════════════════════════════════════════════════════
Which I've made sure to check I'm not getting anything null but I still get it.
And the second.
When the timer finishes I get the following error:
[VERBOSE-2:shell.cc(184)] Dart Error: Unhandled exception:
setState() called after dispose(): _TimeState#10749(lifecycle state: defunct, not mounted)
This error happens if you call setState() on a State object for a widget that no longer appears in the widget tree (e.g., whose parent widget no longer includes the widget in its build). This error can occur when code calls setState() from a timer or an animation callback. The preferred solution is to cancel the timer or stop listening to the animation in the dispose() callback. Another solution is to check the "mounted" property of this object before calling setState() to ensure the object is still in the tree.
This error might indicate a memory leak if setState() is being called because another object is retaining a reference to this State object after it has been removed from the tree. To avoid memory leaks, consider breaking the reference to this object during dispose().
#0 State.setState.<anonymous closure> (package:flutter/src/widgets/framewo<…>
And when I try to start a timer again I get this:
flutter: Another exception was thrown: NoSuchMethodError: The getter 'inMilliseconds' was called on null.
Here's is my code:
import 'dart:async';
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:fluttery/layout.dart';
Duration time;
Duration previousTime;
Duration currentTime;
AnimationController timeController, circleController;
bool reverse = false;
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
Stopwatch stopwatch = new Stopwatch();
#override
void initState() {
super.initState();
timeController = new AnimationController(
duration: const Duration(milliseconds: 250),
vsync: this,
);
timeController.addListener(() {
setState(() {});
});
}
#override
void dispose() {
timeController.dispose();
circleController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: <Widget>[
Center(
child: Opacity(
opacity: timeController.value != null ? 1.0 - timeController.value : 1.0,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new FlatButton(
onPressed: () {
setState(() {
previousTime = Duration(minutes: 1);
time = previousTime;
timeController.forward();
stopwatch.start();
circleController = new AnimationController(
duration: Duration(milliseconds: time.inMilliseconds),
vsync: this,
);
circleController.addListener(() {
setState(() {});
});
circleController.forward();
});
},
child: Text("1:00",
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 16.0)),
),
new FlatButton(
onPressed: () {
setState(() {
previousTime = Duration(minutes: 2);
time = previousTime;
timeController.forward();
stopwatch.start();
circleController = new AnimationController(
duration: Duration(milliseconds: time.inMilliseconds),
vsync: this,
);
circleController.addListener(() {
setState(() {});
});
circleController.forward();
});
},
child: Text("2:00",
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 16.0)),
),
new FlatButton(
onPressed: () {
setState(() {
previousTime = Duration(minutes: 3);
time = previousTime;
timeController.forward();
stopwatch.start();
circleController = new AnimationController(
duration: Duration(milliseconds: time.inMilliseconds),
vsync: this,
);
circleController.addListener(() {
setState(() {});
});
circleController.forward();
});
},
child: Text("3:00",
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 16.0)),
),
new FlatButton(
onPressed: () {
setState(() {
previousTime = Duration(minutes: 5);
time = previousTime;
timeController.forward();
stopwatch.start();
circleController = new AnimationController(
duration: Duration(milliseconds: time.inMilliseconds),
vsync: this,
);
circleController.addListener(() {
setState(() {});
});
circleController.forward();
});
},
child: Text("5:00",
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 16.0)),
),
],
),
),
),
Center(
child: Opacity(
opacity: timeController.value != null ? 0.0 + timeController.value : 0.0,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: time != null ? buildTimes(stopwatch, time, previousTime) : []
),
),
),
CenterAbout(
position: Offset(MediaQuery.of(context).size.width / 2,
MediaQuery.of(context).size.height / 2),
child: Peinture(color: Color.fromRGBO(224, 245, 255, 1.0), animate: false)
),
CenterAbout(
position: Offset(MediaQuery.of(context).size.width / 2,
MediaQuery.of(context).size.height / 2),
child: Peinture(color: Colors.blue, animate: true)
)
],
),
);
}
}
List<Widget> buildTimes(stopwatch, time, previousTime) {
return [
Time(stopwatch: stopwatch, time: time),
Text(
previousTime != null
? previousTime.toString().substring(3, 7)
: "",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 30.0,
color: Colors.black54),
),
];
}
class Peinture extends StatefulWidget {
final Color color;
final bool animate;
Peinture({this.color, this.animate});
#override
_PeintureState createState() => _PeintureState(color: color, animate: animate);
}
class _PeintureState extends State<Peinture> {
Timer timer;
Color color;
bool animate;
_PeintureState({this.color, this.animate}) {
timer = Timer.periodic(Duration(milliseconds: 1), callback);
}
void callback(Timer timer) {
setState(() {
if (currentTime != null) {
print(currentTime.inMilliseconds);
if (currentTime.inMilliseconds <= 0) {
reverse = true;
timeController.reverse();
previousTime = null;
time = previousTime;
currentTime = time;
reverse = false;
}
}
});
}
#override
Widget build(BuildContext context) {
return Opacity(
opacity: reverse == false ? 1.0 : timeController.value,
child: CustomPaint(
painter: CirclePainter(
radius: 150.0,
thickness: 8.0,
color: color,
startAngle: -pi / 2,
endAngle: time != null && animate ? -pi / 2 + (((currentTime.inMilliseconds - circleController.value)) / 60000) * (2*pi) : -pi / 2 + (2 * pi) - (0 / (2*pi)),
),
),
);
}
}
class CirclePainter extends CustomPainter {
final double radius;
final double thickness;
final Color color;
final double startAngle;
final double endAngle;
final Paint circlePaint;
CirclePainter({this.radius, this.thickness, this.color, this.startAngle, this.endAngle})
: circlePaint = new Paint()
..color = color
..strokeWidth = thickness
..style = PaintingStyle.stroke
..strokeCap = StrokeCap.round;
#override
void paint(Canvas canvas, Size size) {
canvas.drawArc(Rect.fromLTWH(-radius, -radius, radius * 2, radius * 2),
startAngle, endAngle - startAngle, false, circlePaint);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
class Time extends StatefulWidget {
final Duration time;
final Stopwatch stopwatch;
Time({this.stopwatch, this.time});
#override
_TimeState createState() => _TimeState(stopwatch: stopwatch, time: time);
}
class _TimeState extends State<Time> {
Timer timer;
Duration time;
Stopwatch stopwatch;
_TimeState({this.time, this.stopwatch}) {
timer = new Timer.periodic(new Duration(milliseconds: 1), callback);
}
void callback(Timer timer) {
if (stopwatch.isRunning) {
setState(() {
currentTime = time - stopwatch.elapsed;
});
}
}
#override
Widget build(BuildContext context) {
return Text(
currentTime != null ? currentTime.toString().substring(3, 7) : "",
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 60.0, color: Colors.black87),
);
}
}
Thanks for the help and again any suggestions as to how you'd go about it would be appreciated.
Try this
import 'dart:async';
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:fluttery/layout.dart';
Duration time;
Duration previousTime;
Duration currentTime;
AnimationController timeController, circleController;
bool reverse = false;
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
Stopwatch stopwatch = new Stopwatch();
#override
void initState() {
super.initState();
timeController = new AnimationController(
duration: const Duration(milliseconds: 250),
vsync: this,
);
timeController.addListener(() {
setState(() {});
});
}
#override
void dispose() {
timeController.dispose();
circleController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: <Widget>[
Center(
child: Opacity(
opacity: timeController.value != null
? 1.0 - timeController.value
: 1.0,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new FlatButton(
onPressed: () {
setState(() {
previousTime = Duration(minutes: 1);
time = previousTime;
timeController.forward();
stopwatch.start();
circleController = new AnimationController(
duration: Duration(milliseconds: time.inMilliseconds),
vsync: this,
);
circleController.addListener(() {
setState(() {});
});
circleController.forward();
});
},
child: Text("1:00",
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 16.0)),
),
new FlatButton(
onPressed: () {
setState(() {
previousTime = Duration(minutes: 2);
time = previousTime;
timeController.forward();
stopwatch.start();
circleController = new AnimationController(
duration: Duration(milliseconds: time.inMilliseconds),
vsync: this,
);
circleController.addListener(() {
setState(() {});
});
circleController.forward();
});
},
child: Text("2:00",
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 16.0)),
),
new FlatButton(
onPressed: () {
setState(() {
previousTime = Duration(minutes: 3);
time = previousTime;
timeController.forward();
stopwatch.start();
circleController = new AnimationController(
duration: Duration(milliseconds: time.inMilliseconds),
vsync: this,
);
circleController.addListener(() {
setState(() {});
});
circleController.forward();
});
},
child: Text("3:00",
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 16.0)),
),
new FlatButton(
onPressed: () {
setState(() {
previousTime = Duration(minutes: 5);
time = previousTime;
timeController.forward();
stopwatch.start();
circleController = new AnimationController(
duration: Duration(milliseconds: time.inMilliseconds),
vsync: this,
);
circleController.addListener(() {
setState(() {});
});
circleController.forward();
});
},
child: Text("5:00",
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 16.0)),
),
],
),
),
),
Center(
child: Opacity(
opacity: timeController.value != null
? 0.0 + timeController.value
: 0.0,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: time != null
? buildTimes(stopwatch, time, previousTime)
: []),
),
),
CenterAbout(
position: Offset(MediaQuery.of(context).size.width / 2,
MediaQuery.of(context).size.height / 2),
child: Peinture(
color: Color.fromRGBO(224, 245, 255, 1.0), animate: false),
),
CenterAbout(
position: Offset(MediaQuery.of(context).size.width / 2,
MediaQuery.of(context).size.height / 2),
child: Peinture(color: Colors.blue, animate: true),
)
],
),
);
}
}
List<Widget> buildTimes(stopwatch, time, previousTime) {
return [
Time(stopwatch: stopwatch, time: time),
Text(
previousTime != null ? previousTime.toString().substring(3, 7) : "",
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 30.0, color: Colors.black54),
),
];
}
class Peinture extends StatefulWidget {
final Color color;
final bool animate;
Peinture({this.color, this.animate});
#override
_PeintureState createState() =>
_PeintureState(color: color, animate: animate);
}
class _PeintureState extends State<Peinture> {
Timer timer;
Color color;
bool animate;
_PeintureState({this.color, this.animate}) {
timer = Timer.periodic(Duration(milliseconds: 1), callback);
}
void callback(Timer timer) {
setState(() {
if (currentTime != null) {
if (currentTime.inMilliseconds <= 0) {
reverse = true;
timeController.reverse();
previousTime = null;
time = previousTime;
currentTime = time;
reverse = false;
}
}
});
}
#override
Widget build(BuildContext context) {
return Opacity(
opacity: reverse == false ? 1.0 : timeController.value,
child: CustomPaint(
painter: CirclePainter(
radius: 150.0,
thickness: 8.0,
color: color,
startAngle: -pi / 2,
endAngle: time != null && animate && currentTime != null
? -pi / 2 +
(((currentTime.inMilliseconds - circleController.value)) /
60000) *
(2 * pi)
: -pi / 2 + (2 * pi) - (0 / (2 * pi)),
),
),
);
}
}
class CirclePainter extends CustomPainter {
final double radius;
final double thickness;
final Color color;
final double startAngle;
final double endAngle;
final Paint circlePaint;
CirclePainter(
{this.radius, this.thickness, this.color, this.startAngle, this.endAngle})
: circlePaint = new Paint()
..color = color
..strokeWidth = thickness
..style = PaintingStyle.stroke
..strokeCap = StrokeCap.round;
#override
void paint(Canvas canvas, Size size) {
canvas.drawArc(Rect.fromLTWH(-radius, -radius, radius * 2, radius * 2),
startAngle, endAngle - startAngle, false, circlePaint);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
class Time extends StatefulWidget {
final Duration time;
final Stopwatch stopwatch;
Time({this.stopwatch, this.time});
#override
_TimeState createState() => _TimeState(stopwatch: stopwatch, time: time);
}
class _TimeState extends State<Time> {
Timer timer;
Duration time;
Stopwatch stopwatch;
_TimeState({this.time, this.stopwatch}) {
timer = new Timer.periodic(new Duration(milliseconds: 1), callback);
}
void callback(Timer timer) {
if (stopwatch.isRunning) {
setState(() {
currentTime = time - stopwatch.elapsed;
});
}
}
#override
Widget build(BuildContext context) {
return Text(
currentTime != null ? currentTime.toString().substring(3, 7) : "",
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 60.0, color: Colors.black87),
);
}
}

Resources