I'm making a new project in Flutter. Every widget that i made is work perfectly.. but there's some issue when i want to place two images Container in Row, it's perfectly fine on Emulator with 1080x1920, but when i open it on my 460x854 phone...it's crashing with the Symmetric Padding. I've reading some about MediaQuery, but because i'm a beginner, i can't implement it.
Can someone help me?
Here is the code(the full code is too long):
return new Scaffold(
body: ListView(
children: <Widget>[
new Stack(
children: <Widget>[
Container(
child: Column(
children: <Widget>[
//sdsds
new Row(
children: <Widget>[
Expanded(
child: Row(
//HERE IS THE IMAGE IN ROW
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
new Container(
height: 160.0,
width: 160.0,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('intro/1pew.png'),
)),
),
new Container(
height: 160.0,
width: 160.0,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('intro/2pew.png'),
)),
Here is the screenshot (btw, ignore those pewds):
Rather than set the height and width. I would use a Row, then add Expanded widgets, with AspectRatio childs to force behaviour.
example:
Widget build(BuildContext context) {
return Row(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Expanded(
child: AspectRatio(
aspectRatio: 1,
child: Image.asset("assets/image1.png"),
),
),
Expanded(
child: AspectRatio(
aspectRatio: 1,
child: Image.asset("assets/image2.png"),
),
)
],
);
}
This forces both items in the Row to be the same size as both Expanded the AspectRatio widget will force a square, then your view can fill that square.
for detail about mediaquery
to use media query
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
for screen adjustment you can add
height: MediaQuery.of(context).size.height/number (e.g 2 or 3, whatever),
width: MediaQuery.of(context).size.width/2,
Related
How to make slider discrete look like image above in Flutter?
slider discrete
Use the divisions property of the Slider widget to divide it into equal portions, then you have to put Text widgets under them:
Container(
width: MediaQuery.of(context).size.width,
height: 200.0,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Slider(min: 0.0, max: 1.0, divisions: 9, value: 0.0, onChanged: null); // you have to provide an `onChanged` function to let slider pointer change place, and to execute other related actions.
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Container(
child: Text('6'),
),
Container(
child: Text('7'),
),
Container(
child: Text('8'),
),
Container(
child: Text('9'),
),
Container(
child: Text('10'),
),
Container(
child: Text('11'),
),
Container(
child: Text('12'),
),
Container(
child: Text('13'),
),
Container(
child: Text('14'),
),
]
),
]),
)
Screenshot of the problem
I am trying to put elements in the red box by having even spaces between each other. (Like giving weight 1 to each of them). To do so, I put "mainAxisAlignment: MainAxisAlignment.spaceEvenly" in parent Column but it is not working.
Container(
margin: EdgeInsets.only(bottom: 8.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
CachedNetworkImage(
imageUrl:
"https://image.tmdb.org/t/p/w500/${movieDetails
.posterPath}",
height: 120.0,
fit: BoxFit.fill),
Expanded(
child: Container(
margin: EdgeInsets.only(left: 8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly, //NOT WORKING!
children: <Widget>[
generateRow(
Strings.released, movieDetails.releaseDate),
generateRow(Strings.runtime,
movieDetails.runtime.toString()),
generateRow(Strings.budget,
movieDetails.budget.toString())
],
)))
],
)),
This is the code for movie image and the red box. I have created a Row which has 2 elements. First one is that image, second one is for red box.
Row generateRow(String key, String value) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[Text(key), Text(value)],
); }
My generateRow method
How can i solve this problem?
As you have given the height to the image is 120.0, can you do the same for the other Container child. By giving this, I was able to achieve what you want.
Code snippet:
Container(
margin: EdgeInsets.only(bottom: 8.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
CachedNetworkImage(
imageUrl:
"https://image.tmdb.org/t/p/w500/${movieDetails
.posterPath}",
height: 120.0,
fit: BoxFit.fill),
Expanded(
child: Container(
height: 120.0 //added to fix
margin: EdgeInsets.only(left: 8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly, //NOT WORKING!
children: <Widget>[
generateRow(
Strings.released, movieDetails.releaseDate),
generateRow(Strings.runtime,
movieDetails.runtime.toString()),
generateRow(Strings.budget,
movieDetails.budget.toString())
],
)))
],
)),
Tips to debug:
I used Flutter Inspector to find the problem. Refer
Refer the image below. Even though we gave Expanded, it occupied just half the size of image. Here the size of Expanded is determined by child's size (which is almost half the image size).
try this :
new Container(
margin: EdgeInsets.only(bottom: 8.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
CachedNetworkImage(
imageUrl:
"https://image.tmdb.org/t/p/w500/${movieDetails
.posterPath}",
height: 120.0,
fit: BoxFit.fill),
Expanded(
child: Container(
margin: EdgeInsets.only(left: 8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly, //NOT WORKING!
children: <Widget>[
new Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
new Text("Released : "),
new Text("25-07-2018 "),
],
),
new Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
new Text("Released : "),
new Text("25-07-2018 "),
],
),
new Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
new Text("Released : "),
new Text("25-07-2018 "),
],
),
],
)))
],
)),
Another way to achieve the result:
Expanded(
child: Center(
child: // your widget here,
),
)
This one should be the child of the Column, then it will work.
Try looking at this post:
Flutter Layout Row / Column - share width, expand height
Essentially, the image element in the Row makes the row expand in cross axis, but row's actual constraints are not modified. This is why Column's mainAxisAlignment: MainAxisAlignment.spaceEvenly is not working. It needs a parent constraint. And this is achieved with help of IntrinsicHeight. Wrapping Row widget with it will set row's constraints to the largest child's size (which is the image).
I am using Flutter for my app development.
I would like to overlay a poster image view on top of a background image just like in this screenshot below.
The code snippet below does this, but it requires me to also position every other widget including the movie title, release date, etc based on poster's position and background image's position, which is not reliable across several devices and orientation. Is there an example or suggestion to solve this problem?
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new PlatformAdaptiveAppBar(
title: new Text(widget.movie.title),
),
body: new Container(
constraints: new BoxConstraints.expand(),
child: new Stack(
children: <Widget>[
new Container(
child: new Image(
image: new AdvancedNetworkImage(
movieGridUtil.getUrlFromPath(widget.movie.backdrop_path,
MovieGridImageTypes.BACKDROP),
useMemoryCache: false,
useDiskCache: true)),
constraints: new BoxConstraints.expand(height: 250.0),
),
new Positioned(
left: 12.0,
top: 220.0,
child: new Image(
width: 100.0,
height: 150.0,
image: new AdvancedNetworkImage(
movieGridUtil.getUrlFromPath(widget.movie.poster_path,
MovieGridImageTypes.POSTER),
useMemoryCache: false,
useDiskCache: true),
)),
],
)),
);
}
Create Stack
Then inside Stack add Column and make full layout without the poster.
Then as a second Child of Stack, add this combination:
new Stack(
children: [
new Column(
children: _layout()
new Positioned(
top:200,
left:50,
child: _child // or optionaly wrap the child in FractionalTranslation
)]
)
)
Stack(
children: <Widget>[
Container(
color: Colors.blue,
height: 200.0,
),
Padding(
padding: const EdgeInsets.only(left: 20.0,right: 20.0, top:160.0),
child: Container(
color: Colors.pink,
height: 150.0,
width: 110.0,
),
)
],
),
By Creating the Stack,
You can add multiple Container, whichever is last added will be on the top.
Stack(
children: <Widget>[
Container(
color: Colors.blue,
height: 200.0,
),
Padding(
padding: const EdgeInsets.only(left: 20.0,right: 20.0, top:160.0),
child: Container(
color: Colors.pink,
height: 150.0,
width: 110.0,
),
)
],
),
I'm creating a login screen, and i have this background image,
the problem is when the user clicks one of the TextFields and the keyboard pops, the background image changes its size to fit the new screen size (excluding the keyboard).
I want the background to stay persistent and the same size, i would use BoxFit.none, but i'm afraid it will hurt the responsiveness of the app.
Here's the code:
new Container(
decoration: new BoxDecoration(
color: Colors.red,
image: new DecorationImage(
fit: BoxFit.cover,
image: new AssetImage(
'assets/images/splash_screen/background.png'))),
child: new Center(
child: new ListView(
physics: new PageScrollPhysics(),
children: <Widget>[ //Login screen content ],
),
),
);
I also tried to define BoxConstraints with minHeight of the device screen but it doesn't help, and used Stack as well but with not luck.
Here's what i mean by changing dimensions:
No Keyboard / With Keyboard
Put your Scaffold as a child of a Container and make it transparent
final emailField = TextFormField(
decoration: InputDecoration(
hintText: "Email",
),
);
return Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/bg.png'),
fit: BoxFit.cover,
),
),
child: Scaffold(
backgroundColor: Colors.transparent,
body: ListView(
children: <Widget>[
emailField,
],
),
),
);
Try using a Stack, with your image in a Positioned, with a BoxFit of fill. Then, set top: 0.0. This way, its height shouldn't be influenced by the height of the bottom of the screen (i.e. it shouldn't change when the keyboard comes up), and its size should remain the same.
Example:
return Stack(
children: <Widget>[
Positioned(
top: 0.0,
child: Image.asset(
'assets/images/splash_screen/background.png',
fit: BoxFit.fill,
),
),
Center(
child: ListView(
physics: PageScrollPhysics(),
children: <Widget>[
//Login screen content
],
),
),
],
);
Try going to to your Scaffold (or use one) and set
resizeToAvoidBottomPadding = false
You can try this, It works well
import 'package:flutter/material.dart';
class SignUpView extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Stack(children: [
Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/images/background.png"),
fit: BoxFit.cover,
))),
Scaffold(
resizeToAvoidBottomInset: false,
backgroundColor: Colors.transparent,
appBar: AppBar(
title: Text('NEW USER'),
backgroundColor: Colors.transparent,
elevation: 0,
),
body: Padding(
padding: EdgeInsets.all(10),
child: ListView(children: <Widget>[])))
]);
}
}
I want to make a card, a few cards in flutter. On the right side an image and on the left side a information text. I tested it with CircleAvatar and it almost worked like i wanted it to, but I don't want a circle, I want a square image. I removed the CircleAvatar part and put in a new container and a child, but i couldn't use AssetImage, the only thing i could use was image.asset('.jpg'). The image was almost bigger that the phone, because there was no working way to set the size. With the CircleAvatar it worked because I set the radius as size.
When i tried AssetImage() vscode said to me I cannot put it in a widget.
I hope you can help me out (I thing image.asset() isn't the right way). Thank you all
return new MaterialApp(
title: title,
home: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Card(
child: new Column(
children: <Widget>[
new Row(
children: <Widget>[
new Container(
child:
new CircleAvatar(
backgroundImage: new AssetImage('images/lake.jpg'),
radius: 80.0,
child: new Container(
padding: const EdgeInsets.all(0.0),
child: new Text('Sight'),
),
)
),
),
new Container(
child: new Text('long information text'),
)
],
)
],
),
)
],
),
)
);
}
}
You should be able to do this for your row:
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Sample App',
home: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Card(
child: new Column(
children: <Widget>[
new Row(
children: <Widget>[
new Container(
child: new Image.asset(
'images/lake.jpg',
height: 60.0,
fit: BoxFit.cover,
),
),
new Container(
child: new Text('long information text'),
),
],
),
],
),
),
],
),
),
);
}
For an answer in your comment!
You can use ClipRRect,
new ClipRRect(
borderRadius: new BorderRadius.circular(8.0),
child: new AssetImage('images/lake.jpg')
)
also You can do like this:
new Container(
width: 50.0,
height: 50.0,
decoration: new BoxDecoration(
shape: BoxShape.circle,
image: new DecorationImage(
fit: BoxFit.fill,
image: new AssetImage('images/lake.jpg')
)
)),