Flutter white flicker when pushing route before backgroundImage - image

In my flutter app, after the splash screen animation is finished, it pushes to the HomeRoute.
The HomeRoute has a backgropundImage which is intended to cover the whole screen:
HomeRoute.dart:
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/images/mainBgndsmall.png"),
fit: BoxFit.cover)),
child: SafeArea(child: _buildBody())),
);
}
When the route is pushed, there is a white flicker before the backgroundImage is showed.
Is that a normal behavior or am I doing something wrong when trying to put an image as a background?
Image size is about 500KB or 600KB aprox. PNG image.

The image has not loaded yet that is why the container loads before the image comes up
you can fix it by using a future builder which will display a circular progress indictor until the image is loaded and ready to be rendered

You can use precacheImage in your didChangeDependencies method to increase the chances of your image being loaded prior to the widget being displayed, preventing the white flicker.
#override
void didChangeDependencies() {
super.didChangeDependencies();
precacheImage(const AssetImage("assets/images/mainBgndsmall.png"), context);
}
You may need to convert your widget to a StatefulWidget first in order to pass a BuildContext.

It happens because the image is being loaded.
Alternatively, you can use FutureBuilder Widget to handle images as they load
here example
...
///future type variable to keep value from future method
late Future<String> futureData;
///future method to fetch some data
Future<String> getData(){
///give some duration before return value
await Future.delayed(Duration(seconds: 1));
//some code if you have some code
// ....
///return string
return "oke";
}
#override
didChangeDependencies(){
super.didChangeDependencies();
futureData = getData();
}
#override
Widget build(BuildContext context){
Future.delayed(Duration(seconds: 1));
return Scaffold(
body: FutureBuilder<String>(
future: futureData,
builder:(context, snapshot) {
///if loading is done
if(snapshot.connectionState == ConnectionState.done){
// if future success
if(snapshot.hasData){
///return widget what you want to show
return Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/images/mainBgndsmall.png"),
fit: BoxFit.cover)),
child: SafeArea(
child: _buildBody()
)
);
}else{
// if future failed return some widget
return Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: Center(
child: Text("Image can't load"),
)
);
}
}
///return progress loading
return Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: Center(
child: CircularProgressIndicator(),
)
);
},
),
);
}

As of now it is considered as flutter framework bug. You can check that here.
Also it is in Github open issue.
You can do one thing, You can use cached_network_image. While loading your image show your own container or whatever you want.

Related

Assets do not load but when I hot reload

I am new to flutter. I am getting image from backend and displaying those images on the screen using Hero and FadeInImage.
I ave added the hyperlinks in the images and generating the list of images after hitting the API.
child: Hero(
tag: tag,
child: FadeInImage(
width: 130.0,
height: 186.0,
placeholder: AssetImage('assets/images/splash1.png'),
fit: BoxFit.cover,
// onTap: _launchUrl(),
image: NetworkImage(
(merchant.logo)),
// fit: BoxFit.cover,
),
),
),
),
when I run my app, the images are not loaded; the screen is empty. But when I hot reload it shows.
...List.generate(
merchantsList.length,
(index) {
print(merchantsList.length);
print(index);
return MerchantCard(merchant: merchantsList[index]);
You can use placeholder image and also you can add Future Builder concept and Please once check the Future Concept.
#override
Widget build(BuildContext context) {
return new FutureBuilder(
future: _loadImage(),
builder: (BuildContext context, AsyncSnapshot<Image> image) {
if (image.hasData) {
return image.data; // image is ready
} else {
return new Container(); // placeholder
}
},
);
}
The problem was actually widget was built before values are populated in the list. I used setState on my listPopulated function and it worked perfectly ok.

firestore image not load to profile page

when i try to pull profile image from firestore daatabse, It show following error on profile page
'package:flutter/src/painting
_network_image_io.dart':
Failed assertion:line22
pos14:'url!=null':is
not true.
See also:
https://flutter.dev/docs/testing/errors
although it gives this error if i press ctrl+s it loads the profile page. This is my code.
String profilePicUrl;
#override
void initState() {
super.initState();
FirebaseAuth.instance.currentUser().then((user){
profilePicUrl=user.photoUrl;
}).catchError((e){
print(e);
});
}
and then i put profilpicUrl inside of networkImage, as follows
Container(
width: 150.0,
height: 150.0,
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(profilePicUrl),
fit: BoxFit.cover,
),
borderRadius: BorderRadius.all(Radius.circular(75.0)),
boxShadow: [
BoxShadow(
blurRadius:7.0,
color:Colors.black
)
]
),
),
Every time i run the App i have to press ctrl+s to prevent the error and load the profile page
The image is not loading in time, first the initState is getting called and the build method is getting called before the image is received. Therefore, you can use FutureBuilder:
Container(
width: 150.0,
height: 150.0,
child: FutureBuilder(
builder: (context, AsyncSnapshot<FirebaseUser> snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return Image.network(profilePicUrl, fit: BoxFit.cover);
} else if (snapshot.connectionState == ConnectionState.none) {
return Text("No data");
}
return CircularProgressIndicator();
},
future: FirebaseAuth.instance.currentUser(),
),
),

Flutter Image How starting a gif in next build at specific frame from where it left off in previous build

I am trying to design a splash screen. There is a gif that shows in a splash screen. There is no problem of showing the gif.
The problem is that the gif restarts from first frame when the page rebuilds. In my use case, rebuild is expected since a provider listens a firebase user.
My question is that, how can i ensure the gif starts in next build at specific frame from where it left off in previous build.
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:provider/provider.dart';
import 'package:provider_architecture/provider_architecture.dart';
import 'package:myproject/core/viewmodels/startup_view_model.dart';
class StartUpView extends StatelessWidget {
#override
Widget build(BuildContext context) {
FirebaseUser user = Provider.of<FirebaseUser>(context);
ScreenUtil.init(context, width: 411, height: 683, allowFontScaling: true);
return ViewModelProvider<StartUpViewModel>.withConsumer(
viewModel: StartUpViewModel(),
builder: (context, model, child) {
model.handleStartUpLogic(user);
return Scaffold(
backgroundColor: Colors.white,
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Image.asset('assets/images/lock.gif', height: 100.h)
],
),
),
);
},
);
}
}
That's interesting. My problem is the complete opposite of yours.
I want my gif to start from the beginning each time I load the gif, but it always starts at the frame that it left off last time.
return SafeArea(
child: Scaffold(
backgroundColor: Colors.black,
appBar: AppBar(
backgroundColor: Colors.black,
title: Text(
getImageName(),
),
centerTitle: true,
),
body: Center(
child: Column(
children: <Widget>[
Expanded(
child: Image (
height: height * 0.75,
width: width * 0.75,
image: AssetImage(getGuideImagePath()),
)
),
However, for your problem, this implementation may help you.
https://www.youtube.com/watch?v=xZ9vdVkI4Vc&feature=youtu.be
https://github.com/aliyigitbireroglu/flutter-image-sequence-animator/tree/master/image_sequence_animator

Flutter - Relative Position Animations

Oops guys, how are you?
I am making an app using flutter and came across an issue related to animations.
Based on my study I wanted to make an animation where a center image on the screen after the animation is on top (topcenter).
But I didn't find a way to animate using relative values (for example the actual screen height value) only with values that I would describe (which causes problems on screens with different sizes).
Does anyone have any solutions?
AnimatedLogo({this.controller}) :
imagePosition = Tween(
begin: (Use screen size here without context),
end: (0 to topcenter)
).animate(
CurvedAnimation(
parent: controller,
curve: Interval(0.0, 0.150),
)
);
You have some options, you can use AnimatedContainer or AnimatedPositioned
All these options can use AlignmentDirectional.bottomCenter , topCenter
For other options, you can reference this https://medium.com/aubergine-solutions/options-to-animate-in-flutter-2cec6612c207
full code with AnimatedContainer
import 'package:flutter/material.dart';
import 'dart:ui';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or simply save your changes to "hot reload" in a Flutter IDE).
// Notice that the counter didn't reset back to zero; the application
// is not restarted.
primarySwatch: Colors.blue,
),
home: Option5()
);
}
}
class Option5 extends StatefulWidget {
#override
_Option5State createState() => _Option5State();
}
class _Option5State extends State<Option5> with TickerProviderStateMixin {
AlignmentDirectional _ironManAlignment = AlignmentDirectional.bottomCenter; //AlignmentDirectional(0.0, 0.7);
#override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/images/person-96.png'),
fit: BoxFit.cover)),
),
AnimatedContainer(
duration: Duration(seconds: 3),
alignment: _ironManAlignment,
child: Container(
height: 250,
width: 150,
child: Image.asset('assets/images/alarm-80.png'),
),
),
Align(
alignment: AlignmentDirectional.bottomCenter,
child: RaisedButton(
onPressed: () {
_flyIronMan();
},
child: Text('Go'),
color: Colors.red,
textColor: Colors.yellowAccent,
shape: BeveledRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(20))),
),
)
],
);
}
void _flyIronMan() {
setState(() {
_ironManAlignment = AlignmentDirectional.topCenter; //AlignmentDirectional(0.0,-0.7);
});
}
}

Check image is loaded in Image.network widget in flutter

I am new to Flutter. I try to load network images using image.network widget. it's working fine but sometimes it takes time to load. I added tap listener to image.network during tap I need to check image is fully loaded or not based on the result I need to redirect the page. how to check image is loaded or not?
Code:
new Image.network('http://via.placeholder.com/350x150')
Any help will be appreciated, thank you in advance
You may use the loadingBuilder which is inbuilt feature from flutter for Image.Network
I did it as below:
Image.network(imageURL,fit: BoxFit.cover,
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,
),
);
},
),
for this kind of issues it's good to use the cached_network_image
so you can provide a placeholder when the image is loading and an error widget in case a resource fails to load
String url = "http://via.placeholder.com/350x150";
CachedNetworkImage(
imageUrl: url,
placeholder: (context,url) => CircularProgressIndicator(),
errorWidget: (context,url,error) => new Icon(Icons.error),
),
for ones who do not need to cache the image can use meet_network_image package,
The package basic usage :
MeetNetworkImage(
imageUrl:
"https://random.dog/3f62f2c1-e0cb-4077-8cd9-1ca76bfe98d5.jpg",
loadingBuilder: (context) => Center(
child: CircularProgressIndicator(),
),
errorBuilder: (context, e) => Center(
child: Text('Error appear!'),
),
)
In addition, you can do that by yourself with using a FutureBuilder,
We need to get data with http call that way, we need to import http before import you also need to add pubspec.yaml and run the command flutter packages get
import 'package:http/http.dart' as http;
FutureBuilder(
// Paste your image URL inside the htt.get method as a parameter
future: http.get(
"https://random.dog/3f62f2c1-e0cb-4077-8cd9-1ca76bfe98d5.jpg"),
builder: (BuildContext context, AsyncSnapshot<http.Response> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
return Text('Press button to start.');
case ConnectionState.active:
case ConnectionState.waiting:
return CircularProgressIndicator();
case ConnectionState.done:
if (snapshot.hasError)
return Text('Error: ${snapshot.error}');
// when we get the data from the http call, we give the bodyBytes to Image.memory for showing the image
return Image.memory(snapshot.data.bodyBytes);
}
return null; // unreachable
},
);
This way it will start loading, then it will show the loading of the image loading and then the image. Best option if you don't want to use external libs.
Image.network(
imgUrl,
height: 300,
fit: BoxFit.contain,
frameBuilder: (_, image, loadingBuilder, __) {
if (loadingBuilder == null) {
return const SizedBox(
height: 300,
child: Center(child: CircularProgressIndicator()),
);
}
return image;
},
loadingBuilder: (BuildContext context, Widget image, ImageChunkEvent? loadingProgress) {
if (loadingProgress == null) return image;
return SizedBox(
height: 300,
child: Center(
child: CircularProgressIndicator(
value: loadingProgress.expectedTotalBytes != null
? loadingProgress.cumulativeBytesLoaded / loadingProgress.expectedTotalBytes!
: null,
),
),
);
},
errorBuilder: (_, __, ___) => Image.asset(
AppImages.withoutPicture,
height: 300,
fit: BoxFit.fitHeight,
),
)
thank you for your comment thats help to resolve the situation that how to know if the image is loaded or not hope that help
I use a StatefulWidget
need a editing depend on your AffichScreen
situation :
-i have an url that i enter
-if url is correct affich the image if not affich an icon
-if empty affich a Text()
-precacheImage check if the url is correct if not give an error and change _loadingimage(bool) to false to affich the icon eror
-i use a NetworkImage to check with precacheImage and before affich use a Image.network
bool _loadingimage;
ImageProvider _image;
Image _imagescreen;
#override
void initState() {
_loadingimage = true;
_imageUrlfocusNode.addListener(_updateImageUrl);
super.initState();
}
#override
void dispose() {
_imageUrlfocusNode.removeListener(_updateImageUrl);
_quantityfocusNode.dispose();
_imageUrlConroller.dispose();
_imageUrlfocusNode.dispose();
super.dispose();
}
void _updateImageUrl() {
setState(() {
_image = NetworkImage(_imageUrlConroller.text);
});
if (!_imageUrlfocusNode.hasFocus) {
if (_imageUrlConroller.text.isNotEmpty) {
setState(() {
loadimage();
});
}
}
}
void loadimage() {
_loadingimage = true;
precacheImage(_image, context, onError: (e, stackTrace) {
// log.fine('Image ${widget.url} failed to load with error $e.');
print('error $e');
setState(() {
_loadingimage = false;
print(_loadingimage);
});
});
if (_loadingimage == true) {
_imagescreen = Image.network(
_imageUrlConroller.text,
fit: BoxFit.fill,
);
}
}
Container(
width: 100,
height: 100,
margin: EdgeInsets.only(top: 13, right: 11),
decoration: BoxDecoration(
border: Border.all(
width: 1,
color: Colors.grey,
),
),
child:_imageUrlConroller.text.isEmpty
? Text('enter an url')
: !_loadingimage
? Container(
child: Icon(Icons.add_a_photo),
)
: Container(
child: _imagescreen,
),
),

Resources