How to set background image for scaffold? - flutter

I am trying to set a background Image for a screen which takes about 25% of the screen,positioned at the top.
I have tried,
#override
Widget build(BuildContext context) {
return Scaffold(
extendBodyBehindAppBar: true,
appBar: AppBar(
backgroundColor: Colors.transparent,
actions: [
IconButton(
icon: Icon(Icons.settings),
onPressed: () {
//Go to Settings Page
},
)
],
),
body: Container(
width: double.infinity,
alignment: Alignment.topCenter,
decoration: BoxDecoration(
image: DecorationImage(
fit: BoxFit.fitWidth,
image: AssetImage(
"assets/images/image1.png",
),
),
),
child: SingleChildScrollView(
child: Column(
children: [
Container(
height: 200,
width: 220,
color: Colors.purple,
),
Container(
height: 200,
width: 220,
color: Colors.pink,
),
It does not align itself to top.Is there any easier way?
I have tried using stack too.
This is what I am getting:
Expected.

Take container as the body of the Scaffold and then set your image as background image inside container decoration.
Don't forget to set the width and height for the container like this:
width : Mediaquery.of(context).size.width
height : Mediaquery.of(context).size.height

Related

How to fix size and position of background image in flutter?

Widget build(BuildContext context){
var height2 = AppBar().preferredSize.height;
return Scaffold(
backgroundColor: Colors.white,
body: Stack(
children: <Widget>[
Image(
image: AssetImage("assets/oral_structure.png"),
fit: BoxFit.fill
),
Padding(
padding: EdgeInsets.only(top:100, left: 100),
child: Container(
height: 60,
width: 60,
child: FlatButton(
child: Text('ㅂ', style: TextStyle(fontSize: 30,fontWeight: FontWeight.bold)),
onPressed: (){
Navigator.push(context, MaterialPageRoute(builder: (context) => B()),);
},
)
),
),
Above is part of my code. The app I'm making is where the appropriate button is placed on top of the background image. However, if you make the code above, the position of the button and the position of the image are different depending on the screen size of the smartphone. The same goes for fixing the height and width. How come there is no way?
#override
Widget build(BuildContext context) {
return Scaffold(
key: v.scaffoldKey,
body: Stack(
children: [
getBackgroundLight(),
],
),
);
}
Widget getBackgroundLight() {
return Stack(
children: [
Image.asset('assets/background.jpg', width: double.infinity),
Transform.rotate(
angle: -SizeConfig.calculateBlockVertical(180) *
(math.pi / SizeConfig.calculateBlockVertical(180)),
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.center,
end: Alignment.bottomCenter,
colors: [
Get.theme.scaffoldBackgroundColor,
Get.theme.scaffoldBackgroundColor.withOpacity(0.5),
],
),
),
),
),
],
);
}

How to overlap a widget with a custom appbar

I want to achieve an effect similar to this one:
Here's what I have: (Blue container is hidden below the appBar)
And this is my current code:
Widget build(BuildContext context) {
return Scaffold(
appBar: GradesAppBar(
title: "Grades",
gradientBegin: Colors.red[200],
gradientEnd: Colors.red,
),
body: Stack(
fit: StackFit.expand,
overflow: Overflow.visible,
children: <Widget>[
Positioned(
top: -20,
left: MediaQuery.of(context).size.width / 2 - 150,
child: Container(
color: Colors.blue,
width: 300,
height: 60,
),
),
],
),
);
}
The GradesAppBar is a Container with boxShadow, borderRadius and gradient decoration.
When you're using stack to achieve this UI approach you should remove the AppBar and make it like this :-
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
alignment: Alignment.center,
fit: StackFit.expand,
overflow: Overflow.visible,
children: <Widget>[
GradesAppBar(
title: "Grades",
gradientBegin: Colors.red[200],
gradientEnd: Colors.red,
),
Positioned(
top: -20,
left: MediaQuery.of(context).size.width / 2 - 150,
child: Container(
color: Colors.blue,
width: 300,
height: 60,
),
),
],
),
);
}
The most important thing; if your GradesAppBar extends PreferredSizeWidget I think you should replace it with Container and give it some cool decorations as you want :")

how to custom position button in flutter?

I'm trying to position a button in custom place in Flutter web app but i cant.
Here is my code:
class HomeScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context)
.size; // This method will give us the height and width of our device screen
return Container(
height: size.height,
width: size.width,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/images/687.jpg"), fit: BoxFit.cover)),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FlatButton(
color: Colors.black,
onPressed: () {},
child: Text("Login"),
textColor: Colors.white,
),
],
));
}
}
Here is picture for demonstration the custom place that i want:
You can use the container set full width to it, add margin and place button inside it.Margin help to adjust the button n any place.
or you can user Positioned Widget
example:
new Positioned(
left: MediaQuery.of(context).size.width/2+100,
top: MediaQuery.of(context).size.height/2,
child: new Container(
width: 100.0,
height: 80.0,
decoration: new BoxDecoration(color: Colors.red),
child: new Text('hello'),
)

Flutter Why is container width not honoured?

I'm trying to create a circle image. Unfortunately, the width of the container is not honoured and I can't figure out why. What am I missing?
Drawer _getDrawer(List<Job> data) {
return Drawer(
// Add a ListView to the drawer. This ensures the user can scroll
// through the options in the Drawer if there isn't enough vertical
// space to fit everything.
child: ListView(
// Important: Remove any padding from the ListView.
padding: EdgeInsets.zero,
children: <Widget>[
_getDrawerHeader(),
ListTile(
title: Text('Item 1'),
onTap: () {
// Update the state of the app
// ...
},
),
ListTile(
title: Text('Item 2'),
onTap: () {
// Update the state of the app
// ...
},
),
],
),
);
}
DrawerHeader _getDrawerHeader() {
return DrawerHeader(
child: StreamBuilder(
stream: FirebaseAuth.instance.currentUser().asStream(),
builder: (context, AsyncSnapshot<FirebaseUser> snapshot) {
if (snapshot.hasData) {
return ListView(
children: <Widget>[
_getCircleImage(snapshot.data.photoUrl),
Text('test'),
Text('test'),
],
);
}
return Center(child: CircularProgressIndicator());
}),
decoration: BoxDecoration(
color: Colors.blue,
),
);
}
_getCircleImage(String url) {
return Container(
width: 64.0,
height: 64.0,
decoration: new BoxDecoration(
image: new DecorationImage(
image: new NetworkImage(url),
fit: BoxFit.cover,
),
shape: BoxShape.circle,
),
);
}
That's a little tricky but it's how Flutter works, your Container doesn't know the constraints of the Parent, then It try to fill all the space available.
You can fix it adding an Align Widget
_getCircleImage(String url) {
return Align(
alignment: Alignment.centerLeft,
child: Container(
width: 64.0,
height: 64.0,
decoration: new BoxDecoration(
image: new DecorationImage(
image: new NetworkImage(url),
fit: BoxFit.cover,
),
shape: BoxShape.circle,
),
),
);
}
More info : https://docs.flutter.io/flutter/widgets/Container-class.html
A widget can decide its own size only within the constraints given to it by its parent. This means a widget usually can’t have any size it wants.
A widget can’t know and doesn’t decide its own position on the screen, since it’s the widget’s parent who decides the position of the widget.
The parent widget takes the entire space available to draw the widget, Here Container is the parent widget, and it's taking whatever space is available, so to give heigh/width to the Container, that needed to be placed inside any widget which assigns x,y position of widgets to get it to draw.
So as per the above description, Container should have a parent that aligns Container on the screen.
Ex: Use
Align(
alignment: Alignment.center,
child: Container(),
);
OR
Center(
child: Container(),
);
Problem:
Container's constraints wont' have any impact if the passed constraints were tight.
For example:
SizedBox.fromSize(
size: Size.fromRadius(100), // Tight constraints are passed to the Container below
child: Container(
width: 100, // No impact
height: 100, // No impact
color: Colors.blue,
),
)
Solutions:
You need to loose those tight constraints. There are multiple ways of doing it. I'm listing a few here:
Use UnconstrainedBox:
SizedBox.fromSize(
size: Size.fromRadius(100),
child: UnconstrainedBox( // <-- UnconstrainedBox
child: Container(
width: 100, // Works
height: 100, // Works
color: Colors.blue,
),
),
)
Use Center or Align:
SizedBox.fromSize(
size: Size.fromRadius(100),
child: Center( // <-- Center
child: Container(
width: 100, // Works
height: 100, // Works
color: Colors.blue,
),
),
)
Use a Column or better Wrap:
SizedBox.fromSize(
size: Size.fromRadius(100),
child: Wrap( // <-- Wrap
children: [
Container(
width: 100, // Works
height: 100, // Works
color: Colors.blue,
),
],
),
)

How do I Set Background image in Flutter?

I am trying to set a background image for the home page. I am getting the image place from start of the screen and filling the width but not the height.
Am I missing something in my code? Are there image standards for flutter? Do images scale based on each phone's screen resolution?
class BaseLayout extends StatelessWidget{
#override
Widget build(BuildContext context){
return Scaffold(
body: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Image.asset("assets/images/bulb.jpg")
]
)
)
);
}
}
I'm not sure I understand your question, but if you want the image to fill the entire screen you can use a DecorationImage with a fit of BoxFit.cover.
class BaseLayout extends StatelessWidget{
#override
Widget build(BuildContext context){
return Scaffold(
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/images/bulb.jpg"),
fit: BoxFit.cover,
),
),
child: null /* add child content here */,
),
);
}
}
For your second question, here is a link to the documentation on how to embed resolution-dependent asset images into your app.
If you use a Container as the body of the Scaffold, its size will be accordingly the size of its child, and usually that is not what you want when you try to add a background image to your app.
Looking at this other question, #collin-jackson was also suggesting to use Stack instead of Container as the body of the Scaffold and it definitely does what you want to achieve.
This is how my code looks like
#override
Widget build(BuildContext context) {
return new Scaffold(
body: new Stack(
children: <Widget>[
new Container(
decoration: new BoxDecoration(
image: new DecorationImage(image: new AssetImage("images/background.jpg"), fit: BoxFit.cover,),
),
),
new Center(
child: new Text("Hello background"),
)
],
)
);
}
Screenshot:
Code:
#override
Widget build(BuildContext context) {
return DecoratedBox(
decoration: BoxDecoration(
image: DecorationImage(image: AssetImage("your_asset"), fit: BoxFit.cover),
),
child: Center(child: FlutterLogo(size: 300)),
);
}
You can use Stack to make the image stretch to the full screen.
Stack(
children: <Widget>
[
Positioned.fill( //
child: Image(
image: AssetImage('assets/placeholder.png'),
fit : BoxFit.fill,
),
),
...... // other children widgets of Stack
..........
.............
]
);
Note: Optionally if are using a Scaffold, you can put the Stack inside the Scaffold with or without AppBar according to your needs.
I was able to apply a background below the Scaffold (and even it's AppBar) by putting the Scaffold under a Stack and setting a Container in the first "layer" with the background image set and fit: BoxFit.cover property.
Both the Scaffold and AppBar has to have the backgroundColor set as Color.transparent and the elevation of AppBar has to be 0 (zero).
Voilà! Now you have a nice background below the whole Scaffold and AppBar! :)
import 'package:flutter/material.dart';
import 'package:mynamespace/ui/shared/colors.dart';
import 'package:mynamespace/ui/shared/textstyle.dart';
import 'package:mynamespace/ui/shared/ui_helpers.dart';
import 'package:mynamespace/ui/widgets/custom_text_form_field_widget.dart';
class SignUpView extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Stack( // <-- STACK AS THE SCAFFOLD PARENT
children: [
Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/images/bg.png"), // <-- BACKGROUND IMAGE
fit: BoxFit.cover,
),
),
),
Scaffold(
backgroundColor: Colors.transparent, // <-- SCAFFOLD WITH TRANSPARENT BG
appBar: AppBar(
title: Text('NEW USER'),
backgroundColor: Colors.transparent, // <-- APPBAR WITH TRANSPARENT BG
elevation: 0, // <-- ELEVATION ZEROED
),
body: Padding(
padding: EdgeInsets.all(spaceXS),
child: Column(
children: [
CustomTextFormFieldWidget(labelText: 'Email', hintText: 'Type your Email'),
UIHelper.verticalSpaceSM,
SizedBox(
width: double.maxFinite,
child: RaisedButton(
color: regularCyan,
child: Text('Finish Registration', style: TextStyle(color: white)),
onPressed: () => {},
),
),
],
),
),
),
],
);
}
}
We can use Container and mark its height as infinity
body: Container(
height: double.infinity,
width: double.infinity,
child: FittedBox(
fit: BoxFit.cover,
child: Image.network(
'https://cdn.pixabay.com/photo/2016/10/02/22/17/red-t-shirt-1710578_1280.jpg',
),
),
));
Output:
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('images/background.png'),fit:BoxFit.cover
)
),
);
decoration: BoxDecoration(
image: DecorationImage(
image: ExactAssetImage("images/background.png"),
fit: BoxFit.cover
),
),
this also works inside a container.
Other answers are great. This is another way it can be done.
Here I use SizedBox.expand() to fill available space and for passing tight constraints for its children (Container).
BoxFit.cover enum to Zoom the image and cover whole screen
Widget build(BuildContext context) {
return Scaffold(
body: SizedBox.expand( // -> 01
child: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage('https://flutter.github.io/assets-for-api-docs/assets/widgets/owl-2.jpg'),
fit: BoxFit.cover, // -> 02
),
),
),
),
);
}
To set a background image without shrinking after adding the child, use this code.
body: Container(
constraints: BoxConstraints.expand(),
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/aaa.jpg"),
fit: BoxFit.cover,
)
),
//You can use any widget
child: Column(
children: <Widget>[],
),
),
You can use the following code to set a background image to your app:
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("images/background.jpg"),
fit: BoxFit.cover,
),
),
// use any child here
child: null
),
);
}
If your Container's child is a Column widget, you can use the crossAxisAlignment: CrossAxisAlignment.stretch to make your background image fill the screen.
I know there is a lot of answers to this question already, but this solution comes with a color gradient around the background image, I think you would like it
import 'package:flutter/material.dart';
class BackgroundImageExample extends StatelessWidget {
const BackgroundImageExample({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Stack(
children: [
backgroudImage(),
Scaffold(
backgroundColor: Colors.transparent,
body: SafeArea(
child: Column(
children: [
// your body content here
],
),
),
),
],
);
}
Widget backgroudImage() {
return ShaderMask(
shaderCallback: (bounds) => LinearGradient(
colors: [Colors.black, Colors.black12],
begin: Alignment.bottomCenter,
end: Alignment.center,
).createShader(bounds),
blendMode: BlendMode.darken,
child: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('your image here'), /// change this to your image directory
fit: BoxFit.cover,
colorFilter: ColorFilter.mode(Colors.black45, BlendMode.darken),
),
),
),
);
}
}
Stack(
children: [
SizedBox.expand(
child: FittedBox(
fit: BoxFit.cover,
child: Image.asset(
Images.splashBackground,
),
)
),
your widgets
])
This Helped me
import 'package:flutter/material.dart';
void main() => runApp(DestiniApp());
class DestiniApp extends StatefulWidget {
#override
_DestiniAppState createState() => _DestiniAppState();
}
class _DestiniAppState extends State<DestiniApp> {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: SafeArea(
child: Scaffold(
appBar: AppBar(
backgroundColor: Color.fromRGBO(245, 0, 87, 1),
title: Text(
"Landing Page Bankground Image",
),
),
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: ExactAssetImage("images/appBack.jpg"),
fit: BoxFit.cover
),
),
),
),
),
);
}
}
Output:
#override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: Container(
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/bgmain.jpg'),
//fit: BoxFit.cover
fit: BoxFit.fill),
),
child: Column(
children:
[
//
],
),
)));
}
Image.asset(
"assets/images/background.png",
fit: BoxFit.cover,
height: double.infinity,
width: double.infinity,
alignment: Alignment.center,
),
if still there is a problèm, it' seem like your image is not perfection in the heigth and width
Here is how you can achieve this. First example is with assets image and the second one is with network image.
Local image:
Container(
height: 200,
width: double.infinity,
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/images/cat2.jpg"),
fit: BoxFit.cover),
),
child:
)
Network image:
Container(
height: 200,
width: double.infinity,
decoration: const BoxDecoration(
image: DecorationImage(
image: NetworkImage("https://picsum.photos/id/237/200/300"),
fit: BoxFit.cover),
),
child:
)
You can use FractionallySizedBox
Sometimes decoratedBox doesn't cover the full-screen size.
We can fix it by wrapping it with FractionallySizedBox Widget.
In this widget we give widthfactor and heightfactor.
The widthfactor shows the [FractionallySizedBox]widget should take _____ percentage of the app's width.
The heightfactor shows the [FractionallySizedBox]widget should take _____ percentage of the app's height.
Example : heightfactor = 0.3 means 30% of app's height. widthfactor = 0.4 means 40% of app's width.
Hence, for full screen set heightfactor = 1.0 and widthfactor = 1.0
Tip: FractionallySizedBox goes well with the stack widget. So that you can easily add buttons, avatars, texts over your background image in the stack widget whereas in rows and columns you cannot do that.
For more info check out this project's repository github repository link for this project
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: SafeArea(
child: Stack(
children: <Widget>[
Container(
child: FractionallySizedBox(
heightFactor: 1.0,
widthFactor: 1.0,
//for full screen set heightFactor: 1.0,widthFactor: 1.0,
child: DecoratedBox(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("images/1.jpg"),
fit: BoxFit.fill,
),
),
),
),
),
],
),
),
),
);
}
}
OutPut:
It can be done either of the following ways, based on your requirement:
Background image spanning accross the app Bar
Scaffold(
extendBodyBehindAppBar: true,
appBar: AppBar(
elevation: 0,
title: const Text(
"Home Page",
style: TextStyle(color: Colors.white),
),
backgroundColor: Colors.transparent,
),
body: Container(
height: double.infinity,
width: double.infinity,
decoration: const BoxDecoration(
image: DecorationImage(
fit: BoxFit.fill,
image: NetworkImage(
'https://wallpaperaccess.com/full/2440003.jpg'))
child: < Your Widgets go here >
),
));
Background image not spanning accross the app Bar
Scaffold(
appBar: AppBar(
elevation: 0,
title: const Text(
"Home Page",
style: TextStyle(color: Colors.black),
),
backgroundColor: Colors.transparent,
),
body: Container(
height: double.infinity,
width: double.infinity,
decoration: const BoxDecoration(
image: DecorationImage(
fit: BoxFit.fill,
image: NetworkImage(
'https://wallpaperaccess.com/full/2440003.jpg'))
child: < Your Widgets go here >
),
));
Extra :
To add background image only to the appBar refer this answer