I want to use a background image for every page in my Flutter app. Therefore, I want to have a class that I can use to return a BoxDecoration to call it from every new page that I create. For the moment, I'm using a simple global function backgroundImage() that returns a BoxDecoration. Is there a way to have a custom class that I can directly pass to decoration: instead of calling a global function?
BoxDecoration backgroundImage() {
return BoxDecoration(
image: DecorationImage(
image: AssetImage("images/background.png"),
fit: BoxFit.cover,
),
);
}
class HomeScreen extends StatelessWidget{
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
decoration: backgroundImage(),
child: null /* add child content here */,
),
);
}
}
It seems to me that what you want is a variable that you can import and re-use. Creating a new class in which you are only going be returning an instance of BoxDecoration with a few custom options is probably overkill. Why not create a separate file, import material, declare a variable with your customisation and use it? Like this example:
Custom decoration file to re-use:
import 'package:flutter/material.dart';
BoxDecoration baseBackgroundDecoration =
BoxDecoration(
image: DecorationImage(
image: AssetImage("images/background.png"),
fit: BoxFit.cover,
),
);
Using it:
import 'custom_decorations.dart';
Using the variable:
Container(
decoration: baseBackgroundDecoration,
),
There's nothing wrong with your original idea though. You wouldn't be using it as a global variable, just a file that you import when you need it, which contains a class with your custom decorations, like this:
import 'package:flutter/material.dart';
class CustomDecorations {
BoxDecoration baseBackgroundDecoration(){
return BoxDecoration(
image: DecorationImage(
image: AssetImage("images/background.png"),
fit: BoxFit.cover,
),
);
}
}
Which you can then just use in one of these ways:
Container(
decoration: CustomDecorations().baseBackgroundDecoration(),
),
Or:
// Declare it
CustomDecorations customDecorations = CustomDecorations();
...
// Use it
Container(
decoration: customDecorations.baseBackgroundDecoration(),
),
Related
I am struggling to set up the correct layout for my composite widgets.
It is the Stack widget containing two images each wrapped in the corresponding widget which are applying some visual effects on the images.
The images are supposed to change every couple of seconds and then I am using the AnimatedSwitcher to animate the fading transition between them.
This is how it looks now:
The result I want to achieve should look like this:
Here is the source code of the corresponding widget:
import 'dart:ui';
import 'package:demo_flutter_fading_images/themes/style.dart';
import 'package:flutter/material.dart';
class ImagesStack extends StatefulWidget {
final String imagePath;
const ImagesStack({required Key key, required this.imagePath}) : super(key: key);
#override
State<ImagesStack> createState() => _ImagesStackState();
}
class _ImagesStackState extends State<ImagesStack> {
#override
Widget build(BuildContext context) {
return Center(
child: Stack(children: <Widget>[
ImageFiltered(
imageFilter: ImageFilter.blur(
sigmaX: 6,
sigmaY: 6,
),
child: Container(
// constraints: const BoxConstraints.expand(),
constraints: BoxConstraints.tight(const Size(360, 500)),
decoration: BoxDecoration(
image: DecorationImage(
alignment: Alignment.center,
image: AssetImage(widget.imagePath),
fit: BoxFit.fill,
),
),
),
),
Container(
margin: const EdgeInsets.fromLTRB(8, 4, 8, 4),
decoration: frontImageBoxDecoration,
child: ClipRRect(
borderRadius: BorderRadius.circular(20),
child: Image.asset(
widget.imagePath,
fit: BoxFit.fill,
),
),
),
]),
);
}
}
And the full source code of demo project:
github - demo project
I tried it quickly on dartpad.
https://dartpad.dev/?id=3c24c716a9844b706662cb495675f56d
You can refer to the code to follow the structure and make changes. I have left some comments to help understand the code.
Try resizing the window after running the app in dart to see how the image gets positioned for different sizes.
The following code works fine to get the right container color. However, when I want to use the _green function replacing Color(0xff0c9869) in the BoxDecoration widget, the color turns out to be very pale/transparent.
It seems like the same solution, but the result is totally different, anyone knows why?
import 'package:flutter/material.dart';
class Home extends StatelessWidget {
final _green = Color(0xff0c9869);
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(children: [
Container(
height: 200,
decoration: BoxDecoration(
color: Color(0xff0c9869),
borderRadius: BorderRadius.all(
Radius.circular(35),
),
),
child: Row(
children: [Text('Hi'), Icon(Icons.account_circle)],
),
)
]));
}
}
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,
),
),
),
],
);
I have a scenario where I would like to load an image based on the text that is chosen to be displayed on the app.
For example, I have a map that looks like this:
final _activity = const [
{'Activity': 'Rock Climbing','Image':'assets/images/rockclimbing.jpg'},
{'Activity': 'Running','Image':'assets/images/running.jpg'},
];
If I want to display the text related to an Activity in a Text Widget I can do the following:
Text(
activity[activityNumber]['Activity'],
),
However, I would also like to display the corresponding image, here is what I have tried that does not work:
decoration: BoxDecoration(
color: const Color(0xff7c94b6),
image: const DecorationImage(
image:AssetImage (activity[activityNumber]['Image']),
fit: BoxFit.cover,
),
I have also tried wrapping this in quotes, curly braces etc but I cannot make this work.
The way you are doing should work:
Container(
decoration: BoxDecoration(
color: const Color(0xff7c94b6),
image: DecorationImage(
image: AssetImage(_activity[activityNumber]['Image']),
fit: BoxFit.cover,
),
),
);
Have you considered using Image.asset? Something like: Image.asset(_activity[activityNumber]['Image'])
I am trying to cover the entire canvas with an image. For this, I am using BoxFit.cover enum. But it is not working.
Code :
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body:
Image(
image: AssetImage("assets/choco.jpg"),
fit: BoxFit.cover,
),
),
);
}
}
Output Screenshot :
Why is it not covering the entire screen? None of the BoxFit enum values are working. Please explain in detail. Thank you.
Stack also has a fit property, so set fit to StackFit.expand.
Stack(
fit: StackFit.expand,
...
More info here: https://docs.flutter.io/flutter/widgets/Stack/fit.html
If you don't have a parent widget for you Image try using the height and width property.
Image(
image: AssetImage("assets/choco.jpg"),
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
fit: BoxFit.cover,
),
Images are not knowing the width to cover.
Wrap your image with a Container() and set width: double.infinity, for it.
Container(
width: double.infinity,
child: Image(
image: AssetImage("assets/choco.jpg"),
fit: BoxFit.cover,
),
),