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,
),
)
],
),
Related
I am trying to create a listview with an image and vertical line at the start of the list tile. I will try to explain with an image.
I have tried using a stack with a container for the vertical line, and then an image right after, but it didn't work. I also tried adding a Position.fill to the vertical line, which also didn't work.
Row(
children: <Widget>[
Stack(
children: <Widget>[
new Image(image: new AssetImage("assets/img/airplane.png")),
Positioned.fill(
child: Container(
height: 1.0,
width: 3.0,
color: Colors.green,
margin: const EdgeInsets.only(left: 30.0, right: 10.0),
),
),
],
)
],
),
This is what i am trying to achieve.
An example of an app on the store that does what I am trying to achieve:
Here an example:
class MainPageState extends State<MainPage> {
//State must have "build" => return Widget
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Stack(alignment: const Alignment(0.0, 0.0), children: <Widget>[
Container(
//Do you need to make Image as "Circle"
child: Image.asset('images/sanBernardo1.jpg',
width: 150.0, height: 150.0, fit: BoxFit.fill),
),
Positioned(
left: 50.0,
child: Container(
width: 12.0,
height: 100.0,
padding: const EdgeInsets.all(5.0),
decoration: BoxDecoration(color: Colors.red[400])),
)
]));
}
}
Hope this help.
The correct widget for this case is Stepper
https://api.flutter.dev/flutter/material/Stepper-class.html
So, you can create progress through a sequence of steps with a lot of built-in functionality.
Also, it could be useful take a look to Material style guide https://material.io/archive/guidelines/components/steppers.html#
I am currently learning flutter and have come across an issue where the card is not staying within the boundaries of Column, but is not causing an overflow. My goal is to have the card positioned at the bottom and with Text positioned above the card.
Here is my code:
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
Stack(
children: <Widget>[
Container(
height: MediaQuery.of(context).size.height,
child:
Image.asset("assets/testimage.jpg", fit: BoxFit.cover)),
Positioned(
bottom: 10.0,
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0)),
child: Text(
"A description would be going here, this is just placeholder text.",
style: TextStyle(fontSize: 30),
),
),
)
],
),
],
),
),
);
}
}
and an image example of the problem and desired outcome
Problem
Desired Outcome
You need to define - right: 1.0, left: 1.0, also along with bottom in Positioned. widget.
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
Stack(
children: <Widget>[
Container(
height: MediaQuery.of(context).size.height,
child: Image.network("https://placeimg.com/640/480/any",
fit: BoxFit.cover)),
Positioned(
bottom: 1.0,
right: 1.0,
left: 1.0,
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0)),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"A description would be going here, this is just placeholder text.",
style: TextStyle(fontSize: 30),
),
),
),
)
],
),
],
),
);
}
Output:
I have used ClipRRect for rounded corners in the UI. The ClipRRect wraps topContent and bottomContent are a stack and a Column respectively. But, the bottom corners are not round. What may be the reason behind this?
The cardModel class is used to store the image path in this case.
class FeaturedCard extends StatelessWidget {
final FeaturedCardModel cardModel;
final double parallaxPercent;
FeaturedCard({
this.cardModel,
this.parallaxPercent = 0.0, //default value
});
#override
Widget build(BuildContext context) {
final topContent = Stack(
children: <Widget>[
Container(
padding: EdgeInsets.only(
left: 10.0,
),
height: MediaQuery.of(context).size.height * 0.3,
decoration: new BoxDecoration(
image: new DecorationImage(
image: new AssetImage(cardModel.imgUrl),
fit: BoxFit.fill,
),
)),
],
);
final bottomContentText = Text(
'This is the sample text',
style: TextStyle(fontSize: 18.0),
);
final bottomContent = Container(
height: MediaQuery.of(context).size.height * 0.5,
width: MediaQuery.of(context).size.width,
color: Colors.white,
padding: EdgeInsets.all(40.0),
child: Center(
child:
bottomContentText,
),
);
return ClipRRect(
borderRadius: BorderRadius.circular(16.0),
child: Column(
children: <Widget>[
topContent,
bottomContent,
],
),
);
}
}
If you go to Flutter Inspector and do "Toggle Debug Paint" you will see that the clipping occurs in the blue area below.
You can fix it by giving a size to your clipper.
return SizedBox(
height: MediaQuery.of(context).size.height * 0.8,
child: ClipRRect(
borderRadius: BorderRadius.circular(16.0),
child: Column(
children: <Widget>[
topContent,
//bottomContent,
],
),
),
);
The column that is the child of ClipRRect is taking as much space as it can get. so the border radius is applied to the bottom of the screen.
to solve that you just need to set mainAxisSize property of Column to MainAxisSize.min:
return ClipRRect(
borderRadius: BorderRadius.circular(16.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
topContent,
bottomContent,
],
),
);
I would like to control the profile image size, and get it rounded instead of oval as shown below.
Changing the height and/or the width values doesn't affect neither the size nor the ratio, also the weird thing is when I change the margin parameter it changes the oval shape radius.
new UserAccountsDrawerHeader(
decoration: BoxDecoration(color: Colors.white),
currentAccountPicture: new Container(
margin: const EdgeInsets.only(bottom: 40.0),
width: 10.0,
height: 10.0,
decoration: new BoxDecoration(
shape: BoxShape.circle,
image: new DecorationImage(
fit: BoxFit.fill,
image: new NetworkImage(
"https://example.com/assets/images/john-doe.jpg",
),
),
),
),
accountName: new Container(
...
),
accountEmail: new Container(
...
),
onDetailsPressed: () {
...
},
),
What am I doing wrong ?
Update: The above way of doing is a workaround to the CircleAvatar that didn't give any control on the image size. If you tried CircleAvatar in some different way that gives control on image size, please share it to help.
Use This code for network image:
new CircleAvatar(
radius: 60.0,
backgroundColor: const Color(0xFF778899),
backgroundImage: NetworkImage("Your Photo Url"), // for Network image
),
Use this for asset Image:
new CircleAvatar(
radius: 60.0,
backgroundColor: const Color(0xFF778899),
child: new Image.asset(
'images/profile.png',
), //For Image Asset
),
If you use backgroundImage as the image provider for CircleAvatar then changing the radius property indeed has no effect. From the source circle_avatar.dart it can be observed the image is being rendered as BoxFit.cover DecorationImage(image: backgroundImage, fit: BoxFit.cover) - and in user_accounts_drawer_header.dart the currentAccountPicture is hardcoded to be a 72.0 pixel SizedBox so the image will always be 72.0px in dimensions.
https://github.com/flutter/flutter/blob/master/packages/flutter/lib/src/material/user_accounts_drawer_header.dart#L57
https://github.com/flutter/flutter/blob/master/packages/flutter/lib/src/material/circle_avatar.dart#L203
Hopefully the Flutter team adds some level of control to this in the future.
Not an answer, just more info that hopefully helps someone.
Try This:
import 'package:flutter/material.dart';
class AppDrawer extends StatefulWidget {
#override
_AppDrawerState createState() => new _AppDrawerState();
}
class _AppDrawerState extends State<AppDrawer> {
#override
Widget build(BuildContext context) {
return new Drawer(
child: Center(
child: Column(
children: <Widget>[
new UserAccountsDrawerHeader(
decoration: BoxDecoration(color: Colors.white),
currentAccountPicture: new CircleAvatar(
radius: 50.0,
backgroundColor: const Color(0xFF778899),
backgroundImage:
NetworkImage("http://tineye.com/images/widgets/mona.jpg"),
),
),
],
),
),
);
}
}
This is the screenshot of output:
Wrap your image in a CircleAvatar widget. It’s made for such purposes.
You put the margin inside the Container of the image while you have to use the margin parameter of the UserAccountDrawerHeader, this is why your image became an oval:
UserAccountsDrawerHeader(
decoration: BoxDecoration(color: Colors.white),
margin: EdgeInsets.only(bottom: 40.0),
currentAccountPicture: Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
image: DecorationImage(
fit: BoxFit.fill,
image:
NetworkImage("https://via.placeholder.com/150"))),
),
accountName: new Container(
child: Text(
'Name',
style: TextStyle(color: Colors.black),
)),
accountEmail: new Container(
child: Text(
'Email',
style: TextStyle(color: Colors.black),
)),
),
You can create your own header:
DrawerHeader(
decoration: BoxDecoration(
color: Colors.blue
),
child: ListView(
children: [
return ClipRRect(
borderRadius: BorderRadius.circular(8.0),
child: Image.asset('images/myImage.jpg'),
),
//These can go here or below the header with the same background color
Text("user name"),//customize this text
Text("useremail#example.com"),
//...additional header items here
],
)),
I found a solution!!! at least thats what worked for me
import 'package:flutter/material.dart';
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
// Side menu
drawer: new Drawer(
child: GestureDetector(
onTap: () {},
child: ListView(
children: <Widget>[
new UserAccountsDrawerHeader(
accountName: new Text('Hymn +'),
accountEmail: new Text('johndoe#gmail.com'),
currentAccountPicture: new CircleAvatar(
backgroundImage: new NetworkImage(
'https://miro.medium.com/max/1400/1*uC0kYhn8zRx8Cfd0v0cYQg.jpeg'),
),
),
],
),
),
),
);
}
}
This works for me:
DrawerHeader(
decoration: BoxDecoration(color: Colors.blue),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
/*CircleAvatar(
radius: 50.0,
backgroundColor: const Color(0xFF778899),
child: new Image.asset('assets/images/profile_image.png'), //For Image Asset
),*/
Container(
height: 110,
child: ClipRRect(
borderRadius: BorderRadius.circular(100.0),
child: Image.asset('assets/images/profile_image.png'),
),
),
//These can go here or below the header with the same background color
//Divider(height: 1.0, thickness: 1.0, color: Colors.black),
SizedBox(height: 9.0),
Text("user name"),
//...additional header items here
],
),
),
I have the background of my app set like so:
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Container(
decoration: new BoxDecoration(
image: new DecorationImage(
image: new ExactAssetImage('assets/lol/aatrox.jpg'),
fit: BoxFit.cover,
),
),
child: new BackdropFilter(filter: new ImageFilter.blur(sigmaX: 600.0, sigmaY: 1000.0)),
width: 400.0,
),
);
}
}
I'm wanting to blur the DecorationImage, so I added a BackdropFilter to the Container, but I don't see any change. What am I doing wrong?
You could do something like this, by blurring the container child instead.
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Container(
decoration: new BoxDecoration(
image: new DecorationImage(
image: new ExactAssetImage('assets/dog.png'),
fit: BoxFit.cover,
),
),
child: new BackdropFilter(
filter: new ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0),
child: new Container(
decoration: new BoxDecoration(color: Colors.white.withOpacity(0.0)),
),
),
),
);
}
}
Screenshot:
Using Stack:
SizedBox(
height: 200,
child: Stack(
fit: StackFit.expand,
children: [
Image.asset('chocolate_image', fit: BoxFit.cover),
ClipRRect( // Clip it cleanly.
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 10, sigmaY: 10),
child: Container(
color: Colors.grey.withOpacity(0.1),
alignment: Alignment.center,
child: Text('CHOCOLATE'),
),
),
),
],
),
)
Without using Stack:
Container(
height: 200,
width: double.maxFinite,
decoration: BoxDecoration(
image: DecorationImage(
image: ExactAssetImage("your_chocolage_image"),
fit: BoxFit.cover,
),
),
child: ClipRRect( // make sure we apply clip it properly
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 10, sigmaY: 10),
child: Container(
alignment: Alignment.center,
color: Colors.grey.withOpacity(0.1),
child: Text(
"CHOCOLATE",
style: TextStyle(fontSize: 28, fontWeight: FontWeight.bold),
),
),
),
),
)
As I mentioned here, you should wrap your ImageFiltered widget in a ClipRRect to prevent it from flowing out the widget boundaries. Here's the code:
ClipRRect(
child: ImageFiltered(
imageFilter: ImageFilter.blur(sigmaX: 3, sigmaY: 3),
child: Image.asset('assets/flutter_image.png'),
),
),
This is the output:
ImageFiltered is the perfect widget for that . It creates a widget that applies an ImageFilter to its child.
ImageFilter is an easy way to blur or transform pixels in your app . You can import it from dart:ui
Code :
ImageFiltered(
imageFilter: ImageFilter.blur(sigmaY:5,sigmaX:5), //SigmaX and Y are just for X and Y directions
child: Image.asset('assets/image.png') //here you can use any widget you'd like to blur .
)
ImageFilter.blur() make anything blurry and
ImageFilter.matrix() lets you use any matrix for
transformation ,scaling , translating , skewing and rotating
Output :
A similar widget to ImageFiltered is BackdropFilter .
BackdropFilter lets you apply filter to everything that's painted
beneath a widget , instead of applying the filter to the widget
itself.
It's also less performant . If you can do your effect with
ImageFiltered , Use it instead of BackdropFilter.
You can learn more about ImageFiltered by watching this official video or by visiting flutter.dev
It's better if you put in ClipRRect, like this :
Container(
child: ClipRRect(
child: Stack(
children: <Widget>[
FadeInImage.assetNetwork(
placeholder: placeholder,
image: thumbnail,
fit: BoxFit.cover,
),
BackdropFilter(
child: Container(
color: Colors.black12,
),
filter: ImageFilter.blur(sigmaY: 10, sigmaX: 10),
)
],
),
),
width: double.infinity,
),
This case apply for Image (Thumbnail) list items correctly.
All the above answers are correct, I'll reply to #user123456 here since I can't comment yet.
can i make the BoxDecoration image clickeble – user123456
Just wrap the whole Container with a GestureDetector
GestureDetector(
onTap: () {...},
child: Container(
...
decoration: BoxDecoration(...),
),
);
You can use Image widget. It's very simple.
Image(
image: AssetImage("assets/images/news-media.png"),
color: Colors.black,
colorBlendMode: BlendMode.softLight,
fit: BoxFit.fill,
),