Assign an image dynamically in flutter - flutter

How can I assign an image dynamically in flutter ? For example:
final topContent = Stack(
children: <Widget>[
Container(
padding: EdgeInsets.only(left: 10.0),
height: MediaQuery.of(context).size.height * 0.5,
decoration: new BoxDecoration(
image: new DecorationImage(
image: new AssetImage(lesson.imagePath),
fit: BoxFit.cover,
),
)),
Container(
height: MediaQuery.of(context).size.height * 0.5,
padding: EdgeInsets.all(40.0),
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(color: Color.fromRGBO(58, 66, 86, .9)),
child: SingleChildScrollView(
controller: _scrollController,
child: Center(
child: topContentText,
),
),
),
Positioned(
left: 8.0,
top: 60.0,
child: InkWell(
onTap: () {
Navigator.pop(context);
},
child: Icon(Icons.arrow_back, color: Colors.white),
),
)
],
);
Now the image at the start lesson.imagePath is what I want to change dynamically. I tried to use setState() but it gives me an error:
The expression here is a type of void and cannot be used
image: setState ((){
if (someCondition) {
return new AssetImage(lesson.imagePath);
}
}),

Your setState call is wrong! The most simple way is make your image as state of your widget and update this image inside a setState call. setState method does not returns nothing it just rebuilds your widget.
In your _WidgetState class you declare as member:
AssetImage _imageToShow;
You can provider a initial image inside initState method.
#override
initState(){
_imageToShow = AssetImage('youAssetImage');
}
Your Container widget should be declared as:
Container(
padding: EdgeInsets.only(left: 10.0),
height: MediaQuery.of(context).size.height * 0.5,
decoration: new BoxDecoration(
image: new DecorationImage(
image: _imageToShow,
fit: BoxFit.cover,
),
)),
),
And to update your image with setState call you just need:
void updateImage() {
setState ((){
if (someCondition) {
_imageToShow = new AssetImage(lesson.imagePath);
}
});
}
But remember that something has to call updateImage method.

The above solution can work also you can set an array of names and you can set the same image name in the assets folder and you can dynamically select the image where you want to use.
suppose in your case you have a list of lessons.
var lesson = ['a','b','c'];
In assets, folder give the same name to the images. (Don't forget to update the pubspec.yaml file)
Then in the AssetImage you can give the path which can be chosen dynamically.
image:AssetImage('assets/${lesson[index]}.jpg')
Remember to give the same name to the image like here a,b and c to the image.
Also the same extension to be given like here .jpg
image:AssetImage('assets/${lesson[index]}.jpg')

Related

asset image not appearing in flutter

I am using dhiwise to convert my figma prototype into flutter but the header is not appearing and is somehow above the screen. I tried moving it elsewhere but it just puts it outside the header.
current look
what it is supposed to look like
return SafeArea(
child: Scaffold(
backgroundColor: ColorConstant.whiteA700,
body: Container(
height: size.height,
width: size.width,
child: Stack(
children: [
Align(
alignment: Alignment.center,
child: SingleChildScrollView(
child: Container(
height: size.height,
width: size.width,
child: Stack(
alignment: Alignment.topRight,
children: [
Align(
alignment: Alignment.center,
child: Container(
height: size.height,
width: size.width,
decoration: BoxDecoration(
color: ColorConstant.whiteA700,
),
child: Stack(
alignment: Alignment.bottomCenter,
children: [
Align(
alignment: Alignment.topCenter,
child: Container(
width: size.width,
padding: getPadding(
left: 11,
top: 7,
right: 11,
bottom: 7,
),
decoration: BoxDecoration(
color: ColorConstant.blue200,
),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment:
CrossAxisAlignment.start,
mainAxisAlignment:
MainAxisAlignment.start,
children: [
CustomIconButton(
height: 53,
width: 53,
margin: getMargin(
bottom: 276,
),
child: CustomImageView(
svgPath: ImageConstant.imgUser,
the custom image view code, this code was directly from the website itself and I have no idea what any of the code means to do
// ignore_for_file: must_be_immutable
import 'dart:io';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
class CustomImageView extends StatelessWidget {
///[url] is required parameter for fetching network image
String? url;
///[imagePath] is required parameter for showing png,jpg,etc image
String? imagePath;
///[svgPath] is required parameter for showing svg image
String? svgPath;
///[file] is required parameter for fetching image file
File? file;
double? height;
double? width;
Color? color;
BoxFit? fit;
final String placeHolder;
Alignment? alignment;
VoidCallback? onTap;
EdgeInsetsGeometry? margin;
BorderRadius? radius;
BoxBorder? border;
///a [CustomImageView] it can be used for showing any type of images
/// it will shows the placeholder image if image is not found on network image
CustomImageView({
this.url,
this.imagePath,
this.svgPath,
this.file,
this.height,
this.width,
this.color,
this.fit,
this.alignment,
this.onTap,
this.radius,
this.margin,
this.border,
this.placeHolder = 'assets/images/image_not_found.png',
});
#override
Widget build(BuildContext context) {
return alignment != null
? Align(
alignment: alignment!,
child: _buildWidget(),
)
: _buildWidget();
}
Widget _buildWidget() {
return Padding(
padding: margin ?? EdgeInsets.zero,
child: InkWell(
onTap: onTap,
child: _buildCircleImage(),
),
);
}
///build the image with border radius
_buildCircleImage() {
if(radius!=null) {
return ClipRRect(
borderRadius: radius,
child: _buildImageWithBorder(),
);
}
else{
return _buildImageWithBorder();
}
}
///build the image with border and border radius style
_buildImageWithBorder(){
if(border!=null) {
return Container(
decoration: BoxDecoration(
border: border,
borderRadius: radius,
),
child: _buildImageView(),
);
}else{
return _buildImageView();
}
}
Widget _buildImageView() {
if (svgPath != null && svgPath!.isNotEmpty) {
return Container(
height: height,
width: width,
child: SvgPicture.asset(
svgPath!,
height: height,
width: width,
fit: fit ?? BoxFit.contain,
color: color,
),
);
} else if (file != null && file!.path.isNotEmpty) {
return Image.file(
file!,
height: height,
width: width,
fit: fit ?? BoxFit.cover,
color: color,
);
} else if (url != null && url!.isNotEmpty) {
return CachedNetworkImage(
height: height,
width: width,
fit: fit,
imageUrl: url!,
color: color,
placeholder: (context, url) => Container(
height: 30,
width: 30,
child: LinearProgressIndicator(
color: Colors.grey.shade200,
backgroundColor: Colors.grey.shade100,
),
),
errorWidget: (context, url, error) => Image.asset(
placeHolder,
height: height,
width: width,
fit: fit ?? BoxFit.cover,
),
);
} else if (imagePath != null && imagePath!.isNotEmpty) {
return Image.asset(
imagePath!,
height: height,
width: width,
fit: fit ?? BoxFit.cover,
color: color,
);
}
return SizedBox();
}
}
1- flutter clean
2- flutter pub get
And if it doesn't work with these instructions, I suggest you look at the link below
enter link description here
I hope you specified that image as an asset in the pubspec.yaml.
I mean...
Flutter uses the pubspec.yaml file, located at the root of your project, to identify assets required by an app.
flutter:
assets:
- assets/my_icon.png
- assets/background.png
To include all assets under a directory, specify the directory name with the / character at the end:
flutter:
assets:
- directory/
- directory/subdirectory/
If you already specify path of your image (sometimes you need to hot restart if you add new asset)
please check that svg image was fine by opening it via web. I face the same issues before with svg using SvgPicture I can open svg file on web but not readble in mobile apps. As I remember my error was not valid svg.
This library only supports <defs> and xlink:href references that are defined ahead of their references.
If do so, maybe you can try this one.
save image as PNG from Figma
Import image to Adobe XD
Export to SVG.
Replace current asset with this Adobe XD svg format.

How do I create a progress bar container that fills based on my data?

I have a widget(s) to build that looks like this:
Being somewhat new to flutter, I'm drawing a blank on how to achieve the background being filled like that.
I do have my data like so:
enum ProgressKeys {
articles,
meals,
bloodPressure,
mood,
physicalActivity,
weight,
}
class StepProgress {
StepProgress({
required this.displayText,
required this.progress,
required this.count,
});
final String displayText;
final int progress;
int count;
}
final Map<ProgressKeys, StepProgress> programStepCounts = {
ProgressKeys.articles: {
displayText: "Articles Read",
progress: 2,
count: 4,
},
ProgressKeys.meals: {
displayText: "Meals Logged",
progress: 3,
count: 9,
},
// Etc...
}
All I can think of is start with a ListView.builder but I have no idea how to achieve something like this with the background.
You can use LinearProgressIndicator inside a Stack! Heres a code sample:
return Center(
child: Container(
clipBehavior: Clip.hardEdge,
margin: const EdgeInsets.symmetric(horizontal: 20.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20.0),
),
height: 80.0,
width: double.infinity,
child: Stack(
alignment: Alignment.centerLeft,
children: [
Positioned.fill(
child: LinearProgressIndicator(
//Here you pass the percentage
value: 0.7,
color: Colors.blue.withAlpha(100),
backgroundColor: Colors.blue.withAlpha(50),
),
),
const Padding(
padding: EdgeInsets.symmetric(horizontal: 10.0),
child: Text('Hello world'),
)
],
),
),
);
You can pass to LinearProgressIndicator a value between 0 to 1 wich represents the percentage of completition. In the code sample i used 0.7 so its 70% full. It looks like this:
Of course you can change the colors and in the first container you can adjust the border.

How to have Label text with graphics over image(product image of e commerce app) in flutter?

I am trying to get a text label with graphics over the image. Labels like new arrival, best seller, limited, on sale just like on the pic attached.
enter image description here
Here's what i think the skeletal layout would be :
return Stack(
children: [
Card(
color: Colors.black54,
child: Image.asset('assets/xyz.png'),
),
Align(
//for bottomRight
alignment: Alignment.bottomRight,
child: Image.asset(
'assets/fireimg.png',
), //can be an SVG converted to png
),
Align(
//for topLeft
alignment: Alignment.topLeft,
child: Image.asset(
'assets/label.png',
), //can be an SVG converted to png
),
],
);
Feel free to give the Padding of your choice.
it has so much code to write , so i will give some examples to achieve that output
in this image ,i mentioned 0 and one .
for all 1
solution 1
you can use image like this way
Stack(
children: [
Container(
width: 200,
height: 200,
color: Colors.amber,// added only for view this example
child:Image() // add Product image here
),
Positioned(
top: 20, //change according to your use case position
left: 0,// change according to your use case position
child: Container(
color: Colors.black, // added only for view this example
decoration: BoxDecoration(image: ),// add label image here
width: 100,
height: 50,
child: Row(
children: [Text('hi')],
),
))
],
)
solution 2
you can use custom paint for label layout
not that
in both solution you have to use stack and position widgets , you can control position according to your use case
for all 0
you can use RotationTransition widgets to achieve this
not that
you have to use stack and position widgets , you can control position according to your use case
for the vertical Text
use this example
String exText = "meta";
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('hi'),
),
body: Container(
width: 200,
height: 200,
color: Colors.amber,
child: Column(
children: exText.characters
.map((e) => Container(
child: Text('$e'),
))
.toList()),
),
out put will be

Modifying an image dynamically doesn't update the image on the screen

I have this code in my build:
XFile? file;
...
body: Container(
color: Colors.black,
child: SizedBox(
height: MediaQuery.of(context).size.width,
width: MediaQuery.of(context).size.width,
child: AspectRatio(
aspectRatio: 1,
child: GestureDetector(
onTap: () => editPhoto(),
child: Image.file(File(file!.path))), //here is the line with problems
),
),
)
With my editPhoto() method, I modify the file whose path is read in my Image.file, but in my screen I still see the old image before the edit. Now, I know for sure that the file has effectively changed because in another part of my code I can see the changes, so the problem is that Image.file doesn't update. How can I solve?

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