Putting a CircularProgressIndicator below each image - flutter

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;
}
},
)

Related

make photo bigger when click on flutter

how to make the picture zoomable when the photo is clicked, here's the code I made to display the image
Column(
children: [
image11 != null
? Image.file(
image11,
width: 50,
height: 50,
fit: BoxFit.cover,
)
: Text(" Bagian Belakang"),
Container(
margin: const EdgeInsets.fromLTRB(14, 5, 0, 0),
child: RaisedButton(
padding: EdgeInsets.all(10),
onPressed: () {
pickImage11(ImageSource.camera);
},
child: Icon(Icons.camera),
),
),
],
),
Taking inspiration from this answer Hero animation with an AlertDialog
You can use a Hero widget combined with a PageRouteBuilder to imitate a zoom feature:
Navigator.of(context).push(
PageRouteBuilder(
opaque: false,
barrierDismissible:true,
pageBuilder: (BuildContext context, _, __) {
return Hero(
tag: "zoom",
child: Image.file(...),
);
}
)
);
EDIT: I found barrier dismissable not working and found the solution here: Flutter SizeTransition and PageRouteBuilder not working
You will have to wrap the Hero widget with a defined width and height to get the optimum zoom level.

Horizontally center a image slider in flutter

I have a image slider in flutter where I want to vertically center the carousel. I'm using carousel_slider. And this here is my code:
Widget _buildItems(BuildContext context) {
return Column(
children: <Widget>[
appBar(context),
Center(
child: CarouselSlider(
options: CarouselOptions(
enlargeCenterPage: true,
enableInfiniteScroll: false,
autoPlay: false,
),
items: widget.recipeStepsList!
.map(
(e) => ClipRRect(
borderRadius: BorderRadius.circular(8),
child: Stack(
fit: StackFit.expand,
children: <Widget>[
Container(
child: Text(
e.name!,
style: TextStyle(color: Colors.red),
),
),
Image.network(
e.stepThumbnailLink!,
width: 1000,
height: 200,
fit: BoxFit.cover,
),
],
),
),
)
.toList(),
),
),
],
);
}
As you can see, I've already wrapped everything inside a Center but this is the outcome of my code:
The only reason the back button is in place because it has a padding of 10. But since I'm building this application for all types of screens I need to keep the image slider exactly in the center.
The carousel is not coming in the center, since your Center widget is not actually taking up the full space and this is because it is inside a Column.
For widget like Row and Column, you can use Expanded widget to make any child take up the remaining space.
So, for your case, just wrap your Center inside an Expanded.
Here is the linkk to full working code.
Result,
Ignore the overflow warning, since that is happening because the carousel package is squishing view while scrolling.

How can I make a Card height extend based on content?

I am creating a Card which has a header and a grid view of photos. Below is the code:
_getImageWidget(Post post, AppConfig config) {
if (post.photoPaths != null && post.photoPaths.length > 0) {
var url = config.imagePathDomain + post.photoPaths[0];
try {
return Expanded(
child: GridView.count(
crossAxisCount: 3,
shrinkWrap: false,
children: post.photoPaths.map<Widget>((String path) {
return CachedNetworkImage(
imageUrl: url,
);
}).toList()));
} catch (err) {
return Container();
}
}
return Container();
}
#override
Widget build(BuildContext context) {
var config = AppConfig.of(context);
return BlocBuilder<UserInfoBloc, UserInfo>(builder: (_, userInfo) {
return Container(
width: MediaQuery.of(context).size.width,
child: Card(
child: Column(children: <Widget>[
Row(
children: <Widget>[
IconButton(
iconSize: 30,
icon: roundImage(post.userPicture, Icon(Icons.person)),
onPressed: () {},
),
Text('#${userInfo.username}')
],
),
this._getImageWidget(post, config),
])));
});
}
The header in the Card is a Row includes a IconButton and Text.
The body of the Card is a gridview which includes a few photo.
Below is the screenshot when I run the code. You can see that the photo is shown only a half. And I can scroll vertically on the grid view. The number of photos is dynamic which means there could be many rows of photos in the GridView. How can I make the Card extend based on its children?
By simply setting your CachedNetwork image to use a fit: BoxFit.cover that will resize to fill the content while preserving ratio (this means you may lose some of its details) or fit: BoxFit.contain that will try to be as big as possible while containing the entire source (image) within the bounds.
If that doesn't help as well (as I'm not seeing the entire tree so I'm not sure about the ancestors of your Card) you can also replace the return of your BlocBuilder's child to be a FittedBox instead of a Container and apply the same logic for the fit property, but for the whole card instead.
Try using a fixed size container and using the BoxFit property on the container.
Something like this :
new Container(
width: 80.0,
height: 80.0,
decoration: new BoxDecoration(
shape: BoxShape.rectangle,
image: new DecorationImage(
fit: BoxFit.fill,
image: CachedNetworkImageProvider(url),
),
),
),
Edit : Try to remove itemExtent from ListView.builder

Make background of CircularProgressIndicator transparent in flutter

I have integrated CircularProgressIndicator in my app on login. The indicator is visible as desired but it hides my login screen with a white overlay. I want to make its background transparent instead of white. I tried to give the background color of CircularProgressIndicator but it doesn't make any change. Here is my code:
child: !_isLoading ? _loginScreen(loginBloc.state) : Center(
child: const SizedBox(
width: 40,
height: 40,
child: CircularProgressIndicator(),
),
)
Thank you.
You can use Stack with different opacity on its childern.
E.g.
Stack(
children: <Widget>[
Opacity(
opacity: 1, // You can reduce this when loading to give different effect
child: AbsorbPointer(
absorbing: _isLoading,
child: _loginScreen(loginBloc.state),
),
),
Opacity(
opacity: _isLoading ? 1.0 : 0,
child: CircularProgressIndicator(),
),
],
);
In case you want working solution, I use it heavily in https://github.com/yagnyam-in/proxy-flutter/blob/master/lib/widgets/loading.dart, https://github.com/yagnyam-in/proxy-flutter/blob/master/lib/widgets/async_helper.dart

Make FadeInImage.memoryNetwork render circular cropped image

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',
),
),
),
],
),
));