Flutter CachedNetworkImageProvider - How to Show local default image on error? - dart

I would like to show a default local image if CachedNetworkImageProvider fails to get the remote image for some reason:
Container(
width: 80.0,
height: 120.0,
decoration: new BoxDecoration(
shape: BoxShape.rectangle,
image: new DecorationImage(
fit: BoxFit.fill,
image: new CachedNetworkImageProvider(url),
),
),
),

#Abdullah Khan - I ended up with this:
CachedNetworkImage(
imageUrl: url,
placeholder: (context, url) => CircularProgressIndicator(),
errorWidget: (context, url, error) => GestureDetector(
onTap: () {
setAvatar();
},
child: Icon(
Icons.account_circle,
size: 100.0,
color: Theme.of(context).primaryColor,
),
),
imageBuilder: (context, image) => Hero(
tag: 'photo',
child: GestureDetector(
onTap: () {
Get.toNamed(Routes.FULLPHOTO,
arguments: {
'url': url,
'name': photoTitle,
'idx': 0
});
},
child: CircleAvatar(
backgroundImage: image,
radius: size,
),
),
),
),
Get.toNamed comes from the GetX package (great for navigation and state management).

#Kamlesh, something like this?:
Container(
margin: EdgeInsets.only(right: 8, left: 8, top: 8, bottom: 8),
width: 80,
height: 80,
decoration: BoxDecoration(
// borderRadius: BorderRadius.all(Radius.circular(14)),
// color: Colors.blue.shade200,
image: DecorationImage(
fit: BoxFit.contain,
image: CachedNetworkImageProvider(
ipath,
),
),
),
),

You can use the cached network image plugin which has an errorWidget parameter, the installation steps are explained on the link. This is an example implementation of it :
image: new CachedNetworkImage(
imageUrl: "http://via.placeholder.com/350x150",
placeholder: new CircularProgressIndicator(),
errorWidget: new Image.assets('error.jpg'), // This is what you need
fit: BoxFit.fill,
fadeInCurve: Curves.easeIn ,
fadeInDuration: Duration(seconds: 2),
fadeOutCurve: Curves.easeOut,
fadeOutDuration: Duration(seconds: 2),
),
you can notice that it also has other features like placeholder and animations ,so you will have more capabilities to tinker with.

Related

CircleAvatar not showing circular image

I am using CicleAvatar to show my avatar but it is not showing circular shape.
Here is my code
//Circle Image
Widget circularImage(){
return new CircleAvatar(
radius: 45,
child: CachedNetworkImage(
imageUrl: this.strImageURL,
placeholder: new CircularProgressIndicator(),
errorWidget: new Icon(Icons.error),
)
);
}
You can wrap your cachedNetworkImage in ClipRRect widget like this:
Widget circularImage(){
return CircleAvatar(
radius: 45,
child: ClipRRect(
borderRadius: BorderRadius.circular(45),
child: CachedNetworkImage(
imageUrl: this.strImageURL,
placeholder: new CircularProgressIndicator(),
errorWidget: new Icon(Icons.error),
),
),
);
}
ClipOval can be used, this Creates an oval-shaped clip.
If [clipper] is null, the oval will be inscribed into the layout size and
position of the child.
ClipOval(
child: Image.asset(
"image.png",
fit: BoxFit.cover,
width: 50.0,
height: 50.0,
)
),

Flutter - How to control profile image size in the drawer

I would like to control the profile image size, and get it rounded instead of oval as shown below.
Changing the height and/or the width values doesn't affect neither the size nor the ratio, also the weird thing is when I change the margin parameter it changes the oval shape radius.
new UserAccountsDrawerHeader(
decoration: BoxDecoration(color: Colors.white),
currentAccountPicture: new Container(
margin: const EdgeInsets.only(bottom: 40.0),
width: 10.0,
height: 10.0,
decoration: new BoxDecoration(
shape: BoxShape.circle,
image: new DecorationImage(
fit: BoxFit.fill,
image: new NetworkImage(
"https://example.com/assets/images/john-doe.jpg",
),
),
),
),
accountName: new Container(
...
),
accountEmail: new Container(
...
),
onDetailsPressed: () {
...
},
),
What am I doing wrong ?
Update: The above way of doing is a workaround to the CircleAvatar that didn't give any control on the image size. If you tried CircleAvatar in some different way that gives control on image size, please share it to help.
Use This code for network image:
new CircleAvatar(
radius: 60.0,
backgroundColor: const Color(0xFF778899),
backgroundImage: NetworkImage("Your Photo Url"), // for Network image
),
Use this for asset Image:
new CircleAvatar(
radius: 60.0,
backgroundColor: const Color(0xFF778899),
child: new Image.asset(
'images/profile.png',
), //For Image Asset
),
If you use backgroundImage as the image provider for CircleAvatar then changing the radius property indeed has no effect. From the source circle_avatar.dart it can be observed the image is being rendered as BoxFit.cover DecorationImage(image: backgroundImage, fit: BoxFit.cover) - and in user_accounts_drawer_header.dart the currentAccountPicture is hardcoded to be a 72.0 pixel SizedBox so the image will always be 72.0px in dimensions.
https://github.com/flutter/flutter/blob/master/packages/flutter/lib/src/material/user_accounts_drawer_header.dart#L57
https://github.com/flutter/flutter/blob/master/packages/flutter/lib/src/material/circle_avatar.dart#L203
Hopefully the Flutter team adds some level of control to this in the future.
Not an answer, just more info that hopefully helps someone.
Try This:
import 'package:flutter/material.dart';
class AppDrawer extends StatefulWidget {
#override
_AppDrawerState createState() => new _AppDrawerState();
}
class _AppDrawerState extends State<AppDrawer> {
#override
Widget build(BuildContext context) {
return new Drawer(
child: Center(
child: Column(
children: <Widget>[
new UserAccountsDrawerHeader(
decoration: BoxDecoration(color: Colors.white),
currentAccountPicture: new CircleAvatar(
radius: 50.0,
backgroundColor: const Color(0xFF778899),
backgroundImage:
NetworkImage("http://tineye.com/images/widgets/mona.jpg"),
),
),
],
),
),
);
}
}
This is the screenshot of output:
Wrap your image in a CircleAvatar widget. It’s made for such purposes.
You put the margin inside the Container of the image while you have to use the margin parameter of the UserAccountDrawerHeader, this is why your image became an oval:
UserAccountsDrawerHeader(
decoration: BoxDecoration(color: Colors.white),
margin: EdgeInsets.only(bottom: 40.0),
currentAccountPicture: Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
image: DecorationImage(
fit: BoxFit.fill,
image:
NetworkImage("https://via.placeholder.com/150"))),
),
accountName: new Container(
child: Text(
'Name',
style: TextStyle(color: Colors.black),
)),
accountEmail: new Container(
child: Text(
'Email',
style: TextStyle(color: Colors.black),
)),
),
You can create your own header:
DrawerHeader(
decoration: BoxDecoration(
color: Colors.blue
),
child: ListView(
children: [
return ClipRRect(
borderRadius: BorderRadius.circular(8.0),
child: Image.asset('images/myImage.jpg'),
),
//These can go here or below the header with the same background color
Text("user name"),//customize this text
Text("useremail#example.com"),
//...additional header items here
],
)),
I found a solution!!! at least thats what worked for me
import 'package:flutter/material.dart';
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
// Side menu
drawer: new Drawer(
child: GestureDetector(
onTap: () {},
child: ListView(
children: <Widget>[
new UserAccountsDrawerHeader(
accountName: new Text('Hymn +'),
accountEmail: new Text('johndoe#gmail.com'),
currentAccountPicture: new CircleAvatar(
backgroundImage: new NetworkImage(
'https://miro.medium.com/max/1400/1*uC0kYhn8zRx8Cfd0v0cYQg.jpeg'),
),
),
],
),
),
),
);
}
}
This works for me:
DrawerHeader(
decoration: BoxDecoration(color: Colors.blue),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
/*CircleAvatar(
radius: 50.0,
backgroundColor: const Color(0xFF778899),
child: new Image.asset('assets/images/profile_image.png'), //For Image Asset
),*/
Container(
height: 110,
child: ClipRRect(
borderRadius: BorderRadius.circular(100.0),
child: Image.asset('assets/images/profile_image.png'),
),
),
//These can go here or below the header with the same background color
//Divider(height: 1.0, thickness: 1.0, color: Colors.black),
SizedBox(height: 9.0),
Text("user name"),
//...additional header items here
],
),
),

Round CachedNetworkImage in Flutter

new Container(
width: 80.0,
height: 80.0,
decoration: new BoxDecoration(
shape: BoxShape.circle,
image: new DecorationImage(
fit: BoxFit.fill,
image: new NetworkImage(widget.profile_picture)))),
At the moment I have a NetworkImage however I wold like to have a round CachedNetworkImage instead.
You can use
ClipRRect(borderRadius: BorderRadius.circular(10000.0),
child: CachedNetworkImage(...))
Since CachedNetworkImageProvider is not a Widget, it doesn't work in place of a CachedNetworkImage. Meaning it won't have the placeholder widget option.
You can use the CachedNetworkImageProvider like this:
new Container(
width: 80.0,
height: 80.0,
decoration: new BoxDecoration(
shape: BoxShape.circle,
image: new DecorationImage(
fit: BoxFit.fill,
image: new CachedNetworkImageProvider(widget.profile_picture),
),
),
),
You can use the imageBuilder of the CachedNetworkImage:
CachedNetworkImage(
imageUrl: imageUrl,
imageBuilder: (context, imageProvider) => Container(
height: 100,
width: 100,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(50)),
image: DecorationImage(
image: imageProvider,
fit: BoxFit.cover,
),
),
),
placeholder: (context, url) => placeholder,
errorWidget: (context, url, error) => errorWidget,
)
In order to have a rounded image, set the width and height to the same value and set the borderRadius to half the height.
you should try it
ClipOval(
child: CachedNetworkImage(
imageUrl: url,
fit: BoxFit.cover
),
)
BorderRadius and Border Color
1st way
Container(
decoration: BoxDecoration(
border: Border.all(color: Palette.greyTextColor),
borderRadius: BorderRadius.all(Radius.circular(8.0)),),
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(8.0)),
child: CachedNetworkImage(
2nd way
CachedNetworkImage(
imageBuilder: (context, imageProvider) => Container(
width: width,
decoration: BoxDecoration(
border: Border.all(color: Palette.greyTextColor),
borderRadius: BorderRadius.all(Radius.circular(8.0)),
image: DecorationImage(image: imageProvider),
),
),
I use this to create a circular cached image network with border color
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
class CircularCachedNetworkImage extends StatelessWidget {
final String imageURL;
final double size;
final Color borderColor;
final BoxFit fit;
final double borderWidth;
const CircularCachedNetworkImage({
required this.imageURL,
required this.size,
required this.borderColor,
this.fit = BoxFit.fill,
this.borderWidth = 2,
});
#override
Widget build(BuildContext context) {
return Container(
width: size,
height: size,
decoration: BoxDecoration(
color: borderColor,
shape: BoxShape.circle,
),
child: Padding(
padding: EdgeInsets.all(borderWidth),
child: Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.white, // inner circle color
),
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(300.0)),
child: CachedNetworkImage(
imageUrl: imageURL,
fit: fit,
),
),
),
),
);
}
}
usage
CircularCachedNetworkImage(
imageURL: "your image URL in here",
size: 100,
borderColor: Colors.green,
)
You just need to add clipBehavior: Clip.antiAlias,
You can use ClipOval instead of ClipRRect
child: ClipOval(
child: CachedNetworkImage(imageUrl : url),
fit: BoxFit.cover,
),
I needed an avatar widget that kept the circular shape whether the CachedNetworkImage was square or not, and was not fixed to one size but used the available space. My solution was this:
CircleAvatar(
child: AspectRatio(
aspectRatio: 1,
child: ClipOval(
child: CachedNetworkImage(
imageUrl: imgUrl,
fit: BoxFit.fill,
),
),
),
)

How do I stack widgets overlapping each other in flutter

I need to stack widgets like this:
I wrote the code below. However the coins are coming one after another with some default padding. How can I get something like the image above?
Row(
children: <Widget>[
Icon(
Icons.monetization_on, size: 36.0,
color: const Color.fromRGBO(218, 165, 32, 1.0),
),
Icon(
Icons.monetization_on, size: 36.0,
color: const Color.fromRGBO(218, 165, 32, 1.0),
),
],
),
You can use a Stack with Positioned to achieve this:
class StackExample extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(),
body: new Container(
padding: const EdgeInsets.all(8.0),
height: 500.0,
width: 500.0,
// alignment: FractionalOffset.center,
child: new Stack(
//alignment:new Alignment(x, y)
children: <Widget>[
new Icon(Icons.monetization_on, size: 36.0, color: const Color.fromRGBO(218, 165, 32, 1.0)),
new Positioned(
left: 20.0,
child: new Icon(Icons.monetization_on, size: 36.0, color: const Color.fromRGBO(218, 165, 32, 1.0)),
),
new Positioned(
left:40.0,
child: new Icon(Icons.monetization_on, size: 36.0, color: const Color.fromRGBO(218, 165, 32, 1.0)),
)
],
),
),
)
;
}
}
And this how you get some nice shadow drop so the icon stands out more:
class StackExample extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(),
body: new Container(
padding: const EdgeInsets.all(8.0),
height: 500.0,
width: 500.0,
// alignment: FractionalOffset.center,
child: new Stack(
//alignment:new Alignment(x, y)
children: <Widget>[
new Container(
decoration: new BoxDecoration(
borderRadius: BorderRadius.circular(25.0),
boxShadow: [
new BoxShadow(
blurRadius: 5.0,
offset: const Offset(3.0, 0.0),
color: Colors.grey,
)
]
),
child: new Icon(Icons.monetization_on, size: 36.0, color: const Color.fromRGBO(218, 165, 32, 1.0))),
new Positioned(
left: 20.0,
child: new Container(
decoration: new BoxDecoration(
borderRadius: BorderRadius.circular(25.0),
boxShadow: [
new BoxShadow(
blurRadius: 5.0,
offset: const Offset(3.0, 0.0),
color: Colors.grey,
)
]
),
child: new Icon(Icons.monetization_on, size: 36.0, color: const Color.fromRGBO(218, 165, 32, 1.0))),
),
new Positioned(
left:40.0,
child: new Container(
decoration: new BoxDecoration(
borderRadius: BorderRadius.circular(25.0),
boxShadow: [
new BoxShadow(
blurRadius: 5.0,
offset: const Offset(3.0, 0.0),
color: Colors.grey,
)
]
)
,child: new Icon(Icons.monetization_on, size: 36.0, color: const Color.fromRGBO(218, 165, 32, 1.0))),
)
],
),
),
)
;
}
}
As of November 2019 I'd like to add a second solution:
Using package: https://pub.dev/packages/assorted_layout_widgets
var widget1 = ...;
var widget2 = ...;
RowSuper(
children: [widget1, widget2],
innerDistance: -20.0,
);
This will overlap row cells by 20 pixels.
The difference from this solution to the one using Stack is that Positioned widgets in a Stack don't occupy space. So you can't make the Stack the size of its contents, unless you know their sizes in advance. However, the RowSuper will have the size of all of its children widgets.
Note, there is also a ColumnSuper. Also note I am the author of this package.
I wanted something without dependencies and without hardcoded layout.
You could enhance by making overlap use a media query to overlap in terms of %.
Widget overlapped() {
final overlap = 10.0;
final items = [
CircleAvatar(child: Text('1'), backgroundColor: Colors.red),
CircleAvatar(child: Text('2'), backgroundColor: Colors.green),
CircleAvatar(child: Text('3'), backgroundColor: Colors.blue),
];
List<Widget> stackLayers = List<Widget>.generate(items.length, (index) {
return Padding(
padding: EdgeInsets.fromLTRB(index.toDouble() * overlap, 0, 0, 0),
child: items[index],
);
});
return Stack(children: stackLayers);
}
Here is my code on Profile Picture overlapped by camera image in flutter.
Output:
Click here to view output image
Container(
constraints: new BoxConstraints(
maxHeight: 200.0,
maxWidth: 200.0
),
padding: new EdgeInsets.only(left: 16.0, bottom: 8.0, right: 16.0),
decoration: new BoxDecoration(
shape: BoxShape.circle,
image: new DecorationImage(
image: new AssetImage('assets/images/profile.png'),
fit: BoxFit.cover,
),
),
child: Stack(
children: [
new Positioned(
right: 0.0,
bottom: 3.0,
child: Container(
constraints: new BoxConstraints(
maxHeight: 50.0,
maxWidth: 50.0
),
decoration: new BoxDecoration(
boxShadow: [
BoxShadow(
color:Color(0xFFdedede),
offset: Offset(2,2)
),
],
color: Colors.white,
shape: BoxShape.circle,
),
child: GestureDetector(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Icon(
Icons.photo_camera,
size: 34,
color: Color(0xFF00cde7),
),
),
),
),
),
],
),
)
Wraping your elements with OverflowBox and giving the maxWidth value will achieve this effect.
The following can be used in a row or a listview
return SizedBox(
width: 35, //--> list children will be 35 in width
child: OverflowBox(
maxWidth: 50, // --> allowing the child to overflow will cause overlap between elements
child: Container(
width: 50,
child: Text((index + 1).toString()),
),
),
);
You could try my package (signed_spacing_flex). It's exactly the same as a normal Row (or Column and Flex). But it also lets you set negative spacing which causes its children to overlap. You can also set which children should be on top when they overlap.
In your case it would be something like:
SignedSpacingRow(
spacing: -12.0,
stackingOrder: StackingOrder.lastOnTop,
children: <Widget>[
Icon(
Icons.monetization_on, size: 36.0,
color: const Color.fromRGBO(218, 165, 32, 1.0),
),
Icon(
Icons.monetization_on, size: 36.0,
color: const Color.fromRGBO(218, 165, 32, 1.0),
),
],
),
It also works with expanded children if you need.
Reverse variant based on #Lee Higgins
const size = 32.0;
const overlap = size - 6.0;
final containers = [
Container(
decoration: BoxDecoration(
color: Colors.grey[300],
shape: BoxShape.circle,
),
width: size,
height: size,
),
Container(
decoration: BoxDecoration(
color: Colors.grey[400],
shape: BoxShape.circle,
),
width: size,
height: size,
),
];
List<Widget> stackLayers = List<Widget>.generate(containers.length, (index) {
return Padding(
padding: EdgeInsets.fromLTRB(0, 0, index * overlap, 0),
child: containers[index],
);
});
return Stack(alignment: AlignmentDirectional.topEnd, children: stackLayers);
Stack is very much confusing.
The best solution is to use enter link description here

Blurred Decoration Image in Flutter

I have the background of my app set like so:
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Container(
decoration: new BoxDecoration(
image: new DecorationImage(
image: new ExactAssetImage('assets/lol/aatrox.jpg'),
fit: BoxFit.cover,
),
),
child: new BackdropFilter(filter: new ImageFilter.blur(sigmaX: 600.0, sigmaY: 1000.0)),
width: 400.0,
),
);
}
}
I'm wanting to blur the DecorationImage, so I added a BackdropFilter to the Container, but I don't see any change. What am I doing wrong?
You could do something like this, by blurring the container child instead.
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Container(
decoration: new BoxDecoration(
image: new DecorationImage(
image: new ExactAssetImage('assets/dog.png'),
fit: BoxFit.cover,
),
),
child: new BackdropFilter(
filter: new ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0),
child: new Container(
decoration: new BoxDecoration(color: Colors.white.withOpacity(0.0)),
),
),
),
);
}
}
Screenshot:
Using Stack:
SizedBox(
height: 200,
child: Stack(
fit: StackFit.expand,
children: [
Image.asset('chocolate_image', fit: BoxFit.cover),
ClipRRect( // Clip it cleanly.
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 10, sigmaY: 10),
child: Container(
color: Colors.grey.withOpacity(0.1),
alignment: Alignment.center,
child: Text('CHOCOLATE'),
),
),
),
],
),
)
Without using Stack:
Container(
height: 200,
width: double.maxFinite,
decoration: BoxDecoration(
image: DecorationImage(
image: ExactAssetImage("your_chocolage_image"),
fit: BoxFit.cover,
),
),
child: ClipRRect( // make sure we apply clip it properly
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 10, sigmaY: 10),
child: Container(
alignment: Alignment.center,
color: Colors.grey.withOpacity(0.1),
child: Text(
"CHOCOLATE",
style: TextStyle(fontSize: 28, fontWeight: FontWeight.bold),
),
),
),
),
)
As I mentioned here, you should wrap your ImageFiltered widget in a ClipRRect to prevent it from flowing out the widget boundaries. Here's the code:
ClipRRect(
child: ImageFiltered(
imageFilter: ImageFilter.blur(sigmaX: 3, sigmaY: 3),
child: Image.asset('assets/flutter_image.png'),
),
),
This is the output:
ImageFiltered is the perfect widget for that . It creates a widget that applies an ImageFilter to its child.
ImageFilter is an easy way to blur or transform pixels in your app . You can import it from dart:ui
Code :
ImageFiltered(
imageFilter: ImageFilter.blur(sigmaY:5,sigmaX:5), //SigmaX and Y are just for X and Y directions
child: Image.asset('assets/image.png') //here you can use any widget you'd like to blur .
)
ImageFilter.blur() make anything blurry and
ImageFilter.matrix() lets you use any matrix for
transformation ,scaling , translating , skewing and rotating
Output :
A similar widget to ImageFiltered is BackdropFilter .
BackdropFilter lets you apply filter to everything that's painted
beneath a widget , instead of applying the filter to the widget
itself.
It's also less performant . If you can do your effect with
ImageFiltered , Use it instead of BackdropFilter.
You can learn more about ImageFiltered by watching this official video or by visiting flutter.dev
It's better if you put in ClipRRect, like this :
Container(
child: ClipRRect(
child: Stack(
children: <Widget>[
FadeInImage.assetNetwork(
placeholder: placeholder,
image: thumbnail,
fit: BoxFit.cover,
),
BackdropFilter(
child: Container(
color: Colors.black12,
),
filter: ImageFilter.blur(sigmaY: 10, sigmaX: 10),
)
],
),
),
width: double.infinity,
),
This case apply for Image (Thumbnail) list items correctly.
All the above answers are correct, I'll reply to #user123456 here since I can't comment yet.
can i make the BoxDecoration image clickeble – user123456
Just wrap the whole Container with a GestureDetector
GestureDetector(
onTap: () {...},
child: Container(
...
decoration: BoxDecoration(...),
),
);
You can use Image widget. It's very simple.
Image(
image: AssetImage("assets/images/news-media.png"),
color: Colors.black,
colorBlendMode: BlendMode.softLight,
fit: BoxFit.fill,
),

Resources