How to fix size and position of background image in flutter? - 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),
],
),
),
),
),
],
);
}

Related

How to get an image above background while shadowing background in flutter

I have an image and I want it to appear on my screen, above my background, with keeping background a bit dark type like in the image. I am thinking on using AlertDialog to display the image, but if you think there is a better way of doing it or a specific widget for this, please do tell me. Also please tell me what do we name this kind of image which hovers over background and focusing itself in UI.
enter code here
Just for trying out, I used this in my screen's initstate, as I want it to appear as soon as my screen appears -
super.initState();
showDialog(
context: context,
builder: (BuildContext buildContext) {
return AlertDialog(
content: Center(
child: Container(
color: Colors.red,
width: 200,
height: 200,
),
),
);
}
);
initState doesn't contain context you can get context after first frame.
You can use addPostFrameCallback
WidgetsBinding.instance?.addPostFrameCallback((timeStamp) {
showDialog(..);}
Or Future.delayed
Future.delayed(Duration.zero).then((value) {
showDialog(..); }
The dialog construction is :
showDialog(
context: context,
builder: (BuildContext buildContext) {
const double iconSize = 48;
return LayoutBuilder(
builder: (context, constraints) => AlertDialog(
backgroundColor: Colors.transparent,
elevation: 0,
contentPadding: EdgeInsets.zero,
content: SizedBox(
width: constraints.maxWidth * .75,
height: constraints.maxHeight * .75,
child: Stack(
children: [
///background image with fit Cover
Align(
alignment: Alignment.center,
child: Container(
width: constraints.maxWidth * .75 - iconSize,
height: constraints.maxHeight * .75 - iconSize,
color: Colors.cyanAccent,
),
),
Align(
alignment: Alignment.topRight,
child: GestureDetector(
onTap: () {
Navigator.of(context).pop();
},
child: Container(
decoration: const BoxDecoration(
color: Colors.white, shape: BoxShape.circle),
child: const Icon(
Icons.close,
size: iconSize,
),
),
),
)
],
),
),
),
);
},
);
You can use Stack widget withe three widget as children.
first children widget is your background screen.
second children widget is a Container widget with color .withOpacity().
third children widget is the image you are trying to show on top.
Like this:
return Scaffold(
body: Stack(
children: [
Container(
color: Colors.white,
),
Container(
color: Colors.black.withOpacity(0.5),
),
Center(
child: Container(
height: MediaQuery.of(context).size.height * 70 / 100,
width: MediaQuery.of(context).size.width * 80 / 100,
color: Colors.purple,
),
),
],
),
);
for Visibility issue you can use this.
bool isVisible = false;
#override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
body: Stack(
children: [
Container(
color: Colors.red,
child: Center(
child: Container(
child: TextButton(
onPressed: () {
setState(() {
isVisible = true;
});
},
child: Text('Show Widget'),
),
),
),
),
Visibility(
visible: isVisible,
child: GestureDetector(
onTap: () {
setState(() {
isVisible = false;
});
},
child: Container(
color: Colors.white.withOpacity(0.5),
),
),
),
Visibility(
visible: isVisible,
child: Center(
child: Container(
height: MediaQuery.of(context).size.height * 70 / 100,
width: MediaQuery.of(context).size.width * 80 / 100,
color: Colors.purple,
child: Stack(
children: [
Positioned(
top: 0.0,
right: 0.0,
child: IconButton(
icon: const Icon(
Icons.close,
color: Colors.white,
),
onPressed: () {
setState(() {
isVisible = false;
});
},
),
),
],
),
),
),
),
],
),
);
}

is Media query different between ios and android?

i try to fill background of picture use mediaquery to fill picture. ios work fine but android its doesn't work i use media query to fill picture and then got this
can i make another way to fill it ?
here is code
#override
Widget build(BuildContext context) {
double size = MediaQuery.of(context).size.width;
return Scaffold(
body: Form(
key: formKey,
child: SingleChildScrollView(
child: Stack(
children: <Widget>[
buildBackgroud(context),
GestureDetector(
onTap: () => FocusScope.of(context).requestFocus(FocusNode()),
behavior: HitTestBehavior.opaque,
child: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
height: size * 0.3,
),
buildTopic('General Information'),
buildTextBoxEmail(size),
buildTextBoxUserName(size),
buildTextBoxPassword(size),
buildButton(size, context),
Row(
children: [
IconButton(onPressed: (){}, icon: Icon(Icons.add_photo_alternate))
],
)
],
),
),
)
],
),
),
));
}
background method is
SvgPicture buildBackgroud(BuildContext context) {
return SvgPicture.asset(
'assets/images/bg.svg',
alignment: Alignment.center,
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
fit: BoxFit.fill,
);
}
You can try this one, wrapping SvgPicture.asset() into SizedBox and giving full screen height and width into it in your buildBackground function.
SvgPicture buildBackgroud(BuildContext context) {
return SizedBox(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
SvgPicture.asset(
'assets/images/bg.svg',
alignment: Alignment.center,
fit: BoxFit.cover,
)
);
}

Widget on a widget with Centering

I want to put a widget onto other's view.
Here is what I did
In normal version without countdown timer, there is no whitespace inside the screen. It is %50 %50 divided by colours(red and blue).
What I want to do is adding that countdown timer without creating whitespace. Directly adding it onto those colours on the center.
I saw that with Stack it is possible to do. I tried it but couldn't remove the white area.
Here is my code:
#override
Widget build(BuildContext context) {
return Scaffold(
body: new Column(
children: [
Expanded(
flex: 40,
child: new Container(
width: double.infinity,
child: new Column(
children: <Widget>[
box1 = new Expanded(
flex: boxSize1,
child: InkWell(
onTap: () {
clickBox1();
}, // Handle your callback
child: new Container(
alignment: Alignment.topCenter,
color: colorRandom,
),
),
),
TimeCircularCountdown(
unit: CountdownUnit.second,
countdownTotal: 3,
onUpdated: (unit, remainingTime) => print('Updated'),
onFinished: () {
setState(() {
visibility = false;
});
},
),
box2 = new Expanded(
flex: boxSize2,
child: InkWell(
onTap: () {
clickBox2();
}, // Handle your callback
child: new Container(
alignment: Alignment.topCenter,
color: color,
),
),
),
],
),
),
),
],
),
);
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
Column(
children: [
Expanded(
child: Container(
color: Colors.blue,
)),
Expanded(
child: Container(
color: Colors.red,
)),
],
),
Center(
child: Container(
height: 200,
width: 200,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(100),
color: Colors.white,
),
// use your countdown timer widget in child
),
)
],
),
);
}

Flutter - center button

I'm creating a UI with 5 buttons. One of them should be center and its width should be 50% of the screen. The height should be the same size (it should be a circle). I tried with MediaQuery.of(context).size.width but it doesn't work.
This is the closest I got:
The code is:
Widget _playButton() {
return FractionallySizedBox(
widthFactor: 0.5,
heightFactor: 0.5, // I know this is wrong
child: Container(
alignment: new FractionalOffset(0.0, 0.0),
color: Colors.red,
/*decoration: new BoxDecoration(
color: hexToColor('#E8532E'),
shape: BoxShape.circle,
),*/
child: Center(
child: Text(
"PLAY",
style: TextStyle(fontSize: 20.0, color: Colors.white),
),
),
),
);
}
The container where I have this button:
Widget build(BuildContext context) {
return new MaterialApp(
debugShowCheckedModeBanner: false,
home: new Scaffold(
body: new Stack(
alignment: AlignmentDirectional.center,
children: <Widget>[_myScreenOptions(), _playButton()],
),
),
);
}
Obviously, the rest of the buttons should be clickable.
If you wanna create a circular button, you don't have to worry about width & height, giving only one size is enough... or you can use FractionallySizedBox, as you already did.
Code output:
Sample code:
import 'package:flutter/material.dart';
class SampleCenterButton extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
width: double.infinity,
height: double.infinity,
child: Stack(
alignment: Alignment.center,
children: <Widget>[
_myScreenOptions(),
_playButton(),
],
),
),
);
}
_playButton() {
return GestureDetector(
onTap: () {
print("Play game");
},
child: FractionallySizedBox(
widthFactor: 0.5,
child: Container(
// defining one dimension works as well, as Flutter knows how to render a circle.
// width: MediaQuery.of(context).size.width/2,
decoration: BoxDecoration(
color: Colors.red,
shape: BoxShape.circle,
),
child: Center(
child: Text(
"PLAY",
style: TextStyle(fontSize: 30, color: Colors.white),
),
),
),
),
);
}
_myScreenOptions() {
return Column(
children: <Widget>[
buildRow([
buildOption(Color(0xff1D4554), Icons.person, "Teams"),
buildOption(Color(0xff229B8D), Icons.folder_open, "Pets"),
]),
buildRow([
buildOption(Color(0xffE7C16A), Icons.videogame_asset, "Modes"),
buildOption(Color(0xffF2A061), Icons.settings, "Options"),
]),
],
);
}
Widget buildOption(Color bgColor, IconData iconData, String title) {
return Expanded(
child: Container(
color: bgColor,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(
iconData,
size: 80,
),
Text(
title,
style: TextStyle(fontSize: 30),
),
],
),
),
);
}
buildRow(List<Widget> buttons) {
return Expanded(
child: Row(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: buttons,
),
);
}
}

Make soft keyboard overlaps other widgets - Flutter

How to make soft keyboard covers/overlaps other widgets instead of pushing them up which causes the UI to go crazy and pixels overflow?
I tried with and without Stack()
I tried with and without resizeToAvoidBottomInset: false,
But still no result!
class Home extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: Stack(
children: <Widget>[
ClipPath(
clipper: CustomBackgroundClipper(),
child: Container(
height: 220.0,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
gradientStart,
gradientEnd
],
),
),
),
),
Container(
height: MediaQuery.of(context).size.height,
child: HomeTopContainer(),
),
],
),
),
);
}
}
Just add this in Scaffold :
resizeToAvoidBottomInset: false,
I don´t know what is inside your HomeTopContainer, but like this way, its working to me:
class Home extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
body: Stack(
children: <Widget>[
ClipPath(
child: Container(
height: 220.0,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.green, Colors.blue],
),
),
),
),
Container(
height: MediaQuery.of(context).size.height,
child: Align(
alignment: Alignment.bottomCenter,
child: Column(
children: <Widget>[
Spacer(),
Container(
height: 30,
color: Colors.red,
),
TextField()
],
),
),
),
],
),
);
}
}
I would suggest removing the Align widget completely and adding mainAxisAlignment and crossAxisAlignment properties to your Column widget.