Make FadeInImage.memoryNetwork render circular cropped image - flutter

I am trying to create something like CircleAvatar, but with a Stacked widget having a CircularProgressIndicator and a FadeInImage.memoryNetwork as children so that I get a nice loading animation (bonus: placeholder image) when I fetch the image on slow Internet.
Everything else is working fine but I am not being able to figure out how to crop the fetched image into a circular form. I read here that I can use a ClipOval, but I couldn't find any tutorial on how to use it.
Stack(children: <Widget>[
Center(child: CircularProgressIndicator(valueColor: new AlwaysStoppedAnimation<Color>(Colors.lightBlue))),
Center(
child: FadeInImage.memoryNetwork(
placeholder: kTransparentImage,
image:
'https://s3-media2.fl.yelpcdn.com/bphoto/7BlRoSOG3AsAWHMPOaG7ng/ls.jpg',
),
),
],
),
));
Note: I am using transparent_image library for the placeholder to get a transparent placeholder while displaying the loading animation.

This is what I am using in one of my projects, I guess you can create something similar, then instead of using FadeInImage directly use the custom widget.
class AvatarFadeImage extends StatelessWidget {
final String imageUrl;
AvatarFadeImage(this.imageUrl);
#override
Widget build(BuildContext context) {
return ClipOval(
child: FadeInImage.memoryNetwork(
placeholder: kTransparentImage,
image: imageUrl,
fit: BoxFit.contain,
),
);
}
}
Use it like this:
Stack(children: <Widget>[
Center(child: CircularProgressIndicator(valueColor: new AlwaysStoppedAnimation<Color>(Colors.lightBlue))),
Center(
child: AvatarFadeImage("https://s3-media2.fl.yelpcdn.com/bphoto/7BlRoSOG3AsAWHMPOaG7ng/ls.jpg"),
),
],
),
));
PS: You may also look at https://pub.dartlang.org/packages/cached_network_image and https://flutter.io/cookbook/images/cached-images/
Plugin might just do the trick for you.

Just in case this helps anyone, the modified code which worked for me:
Stack(
fit: StackFit.passthrough,
children: <Widget>[
Center(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(Colors.lightBlue))),
Center(
child: ClipOval(
child: FadeInImage.memoryNetwork(
fit: BoxFit.contain,
placeholder: kTransparentImage,
image: 'https://s3-media2.fl.yelpcdn.com/bphoto/7BlRoSOG3AsAWHMPOaG7ng/ls.jpg',
),
),
),
],
),
));

Related

Putting a CircularProgressIndicator below each image

There are a lot of such stack elements on the page:
Stack(
children: <Widget>[
SizedBox(
height: 150,
width: 150,
child: Center(child: CircularProgressIndicator()),
),
Center(child: _getImage(imagePath)),
],
),
So there will be a CircularProgressIndicator below each image. Does it reduce the ui speed? When the Progress Indicator widget is ovelapped by the other widget will be disabled then?
First off you may use const on the constructor for better performance. Secondly, if you want to show a progress indicator when the image is loading maybe try using a FutureBuilder to check if the image is loading, if so return a CircularProgressIndicator else return the image.
But generally speaking flutter should be able to render tons of CircularProgressIndicator and yes it will still render the CircularProgressIndicator even if your image is shown and will therefore take up resources. If you dont want it to show and take resources you could warap it in a Visablity widget but I highly recommend using a futurebuilder so you can maintain the state of the image loading.
I think you are using progress loaders for image loading state, but I'd go with a package.
extended_image: ^4.1.0 seems like a good one and check the code below. It allows you to interfere in Loading State of the image, and you can put whatever widget in place of that state. This package does more than your intended use as well.
ExtendedImage.network(
url,
width: ScreenUtil.instance.setWidth(600),
height: ScreenUtil.instance.setWidth(400),
fit: BoxFit.fill,
cache: true,
loadStateChanged: (ExtendedImageState state) {
switch (state.extendedImageLoadState) {
case LoadState.loading:
_controller.reset();
return Image.asset(
"assets/loading.gif",
fit: BoxFit.fill,
);
break;
///if you don't want override completed widget
///please return null or state.completedWidget
//return null;
//return state.completedWidget;
case LoadState.completed:
_controller.forward();
return FadeTransition(
opacity: _controller,
child: ExtendedRawImage(
image: state.extendedImageInfo?.image,
width: ScreenUtil.instance.setWidth(600),
height: ScreenUtil.instance.setWidth(400),
),
);
break;
case LoadState.failed:
_controller.reset();
return GestureDetector(
child: Stack(
fit: StackFit.expand,
children: <Widget>[
Image.asset(
"assets/failed.jpg",
fit: BoxFit.fill,
),
Positioned(
bottom: 0.0,
left: 0.0,
right: 0.0,
child: Text(
"load image failed, click to reload",
textAlign: TextAlign.center,
),
)
],
),
onTap: () {
state.reLoadImage();
},
);
break;
}
},
)

Flutter: How to make the below image widget functional in Stack

I try to achieve the feature: pinch to zoom in/out an image under another overlay image.
My approach is using photo_view to make the main photo zoomable and put the overlay image on top of the main photo by the "stack".
import 'package:photo_view/photo_view.dart';
class Body extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
child: Stack(
children: <Widget>[
Container(
child: PhotoView(
initialScale: PhotoViewComputedScale.covered,
imageProvider: AssetImage("assets/mainphoto.jpg"),
),
),
),
Container(
child: Center(
child: AssetImage("assets/overlay.png”),
),
),
],
),
);
}
}
The result of the above code
But the overlay image completely disables the main photo, I cannot pinch to zoom in/out the main photo.
I think it’s because of Stack, I googled around it but still don’t have any proper solution.
If any suggestions, I am very appreciated.
Use IgnorePointer Widget
IgnorePointer(
child: Container(
child: Center(
child: Image.asset(
"assets/overlay.png",
),
),
),
)

use loadingBuilder in NetworkImage class flutter

I faced some problems in my flutter app when I use network image:
the image takes too much time to load.
I found the solution by adding loading Builder prosperity in the network.image widget like that :
Image.network( 'URL image}',
fit: BoxFit.fitHeight,
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,
),
);
},
),
This works out right now, but then I need to add the same property (loadingBuilder) with the NetworkImage class (into the BoxDecoration)
as follows:
image: DecorationImage(
image: NetworkImage(widget.cover),
fit: BoxFit.cover,
),
How do I add the loadingBuilder with the NetworkImage class (in the last part of the code)?
There is a solution that I used although it seems like trick.
Using 'Stack' widget, at first show loading widget and draw image widget over that.
If that, at first loading widget will be shown and after image loading completed, image will be shown over the loading widget.
Stack(
children: <Widget>[
// Locate loading widget
LoadingWidget(),
//
Container(
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(widget.cover),
fit: BoxFit.cover,
),
),
),
],
);

How can i fix local asset error in flutter?

Can someone tell me why the picture cannot be displayed?
#
When I take a picture from the Internet with "NetworkImage" it works. Is there a local solution too?
#
I tried a lot around but even the posts here in the forum can not help me.
# To add assets to your application, add an assets section, like this:
assets:
- images/mio.jpg
-
import 'package:flutter/material.dart';
void main() {
runApp(Main());
}
class Main extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Container(
width: 250,
height: 250,
color: Colors.grey,
child: Stack(
children: <Widget>[
Container(
width: 200,
height: 300,
color: Colors.green,
),
Positioned(
top: 0,
right: 0,
child: Container(
width: 200,
height: 300,
child: Image(
fit: BoxFit.contain,
image: AssetImage(
'images/mio.jpg',
),
),
),
),
],
),
),
),
);
}
}
I get this error message
I'm not sure why you are getting this error but you should try
Asset.Image(
'images/mio.jpg',
fit: BoxFit.contain,
),
instead of
Image(
fit: BoxFit.contain,
image: AssetImage(
'images/mio.jpg',
),
),
another suggestion would be to not declare all your images in your pubspec.yaml, because there is a chance of human mistype error, you should just declare the root folder of your images, in your case
assets:
- images/
Here's three solution
First make sure that there's only one tap before assets and two taps before the image path
Second change these lines of code
Image(
fit: BoxFit.contain,
image: AssetImage(
'images/mio.jpg',
),
and write this instead that works for me
Image.asset(
'images/mio.jpg',
fit: BoxFit.cover,
),
Third use flutter clean than flutter run

Use Background image and put scaffold on it

It uses the background image for whole application.
So My plan is use Stack including backgroundimage and Scaffold on it.
In this code, it shows Title.png but dosent show BackGround.png
Where should I fix??
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Stack(
children: <Widget>[
new Image.asset('images/BackGround.png',
fit: BoxFit.cover,
),
Scaffold(
body: Center(
child: Image.asset('images/Title.png')
),
),
],
),
);
}
I think it is showing your "BackGround.png" image. But, "Title.png" image is overlay above it. That's why you're not able to view it.
To check out if it is rendered or not just replace your code as following,
home: Stack(
children: <Widget>[
Scaffold(
body: Center(
child: Image.asset('images/Title.png')
),
),
new Image.asset('images/BackGround.png',
fit: BoxFit.cover,
),
],
),
Stack always renders his first child, then second and then so on. So, in your case, whichever background you want to upload above all, should be on top.
Place your Scaffold inside Container with a background image and use Colors.transparent for Scaffold's backgroundColor property like this:
Container(
//your image here
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/bg.jpg"),
fit: BoxFit.cover,
),
),
//your Scaffold goes here
child: Scaffold(
backgroundColor: Colors.transparent,
body: Container(),
),
);