Stack Widget Error when using SingleChildScrollView - android

I have this code as profile screen which I need it to be able to fill a text like "HELLO" on this code example. But when I put a lot of text in it, the screen become overflow.
The problem is everytime I put SingleChildScrollView to avoid the overflow, I got another error instead.
Please tell me how I can fix this problem.
#override
Widget build(BuildContext context) {
return Container(
child: SafeArea(
child: FutureBuilder<Profile>(
future: dataService.getHttp(),
builder: ...
),
),
);
}
Widget _buildView(detail) {
return Stack(
alignment: Alignment.center,
children: <Widget>[
Column(
children: <Widget>[
Container(
height: 200.0,
child: Center(
child: Image.network(
'https://i.imgur.com/2F3Al82.jpg',
fit: BoxFit.cover,
height: double.infinity,
width: double.infinity,
),
),
),
Padding(
padding: EdgeInsets.fromLTRB(0.0, 50.0, 0.0, 0.0),
),
Expanded(
child: Container(
color: Colors.white,
child: Column(
children: <Widget>[
Text('HELLO'),
]
),
)
),
],
),
Positioned(
top: 150.0,
child: Container(
height: 100.0,
width: 100.0,
decoration: BoxDecoration(
shape: BoxShape.circle,
image: new DecorationImage(
fit: BoxFit.fill,
image: NetworkImage('https://i.imgur.com/2F3Al82.jpg'),
),
),
),
)
],
);
}
this is the error

You are getting this error because of the Expanded widget. SingleChildScrollView allows for infinite height and expanded will take up as much space as it can these two thing are incompatible if you remove the Expanded widget it should work. If you want some space around that container I suggest the Containers margin property.

Related

Flutter Stack Widget inside ListView widget?

I am using the Stack widget in my app and it is working great but now I have a problem with wrapping this Stack widget inside ListView Widget.
I am getting error
RenderBox was not laid out: RenderPointerListener#20d10 relayoutBoundary=up7 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
'package:flutter/src/rendering/box.dart':
Failed assertion: line 1979 pos 12: 'hasSize'
My Stack Widget is
Widget? stackW() {
return Stack(
alignment: Alignment.center,
children: <Widget>[
Positioned(
top: 70,
width: MediaQuery.of(context).size.width * .9,
height: 150,
child: Center(
child: Container(
width: MediaQuery.of(context).size.width * .9,
decoration: BoxDecoration(
color: Colors.grey[200],
borderRadius: BorderRadius.circular(15)),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
"Product Designer",
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
const SizedBox(
height: 10,
),
],
),
),
),
),
Positioned(
top: 30,
left: MediaQuery.of(context).size.width / 2.5,
width: 80,
height: 80,
child: CircleAvatar(
backgroundColor: Colors.white,
child: CircleAvatar(
backgroundColor: Colors.green[100],
radius: 35,
child: const FaIcon(
FontAwesomeIcons.apple,
size: 30,
color: Colors.black,
),
),
),
),
],
);
}
When I am passing stackWidget directly in body then it is working fine but after wrapping inside ListView, it is creating problem.
so Please guide me to achieve my listview data with Stack Widget.
body: stackW()!, //working
body: ListView(
scrollDirection: Axis.vertical,
children: [
stackW()!,
],
),
``` //not working
Both widgets are getting infinite height, you can wrap stackW() with SizedBox widget.
body: LayoutBuilder(
builder: (context, constraints) => ListView(
scrollDirection: Axis.vertical,
children: [
SizedBox(
height: constraints.maxHeight,
width: constraints.maxWidth,
child: stackW()!,
)
],
),
),

How to display vertical items in the card view in Flutter

I'm trying to display items in the card vertically, but in the card content I'm facing an issue that is, "Bottom overflowed by 52 pixels".
Here, I'm attaching code, my design's screenshot, and the screenshot of what actually I need.
Please help!
Below is my code.
Widget buildRowItemsGrid(BuildContext context, int index) {
FlutterMoneyFormatter formatter =
FlutterMoneyFormatter(amount: items[index].price);
return Container(
child: Card(
elevation: 5.0,
margin: EdgeInsets.all(8.0),
child: Column(
children: [
Container(
child: Image.network(
"https://fiverr-res.cloudinary.com/images/q_auto,f_auto/gigs/118898040/original/870e2763755963f5a300574bbea5977fa8b18460/sell-original-football-and-basketball-teams-jersey.jpg",
width: 100,
height: 100,
fit: BoxFit.fill),
),
Column(
children: [
Container(
child: Text(items[index].title,
style: titleTextStyle,
maxLines: 2,
overflow: TextOverflow.ellipsis),
margin: EdgeInsets.fromLTRB(10.0, 5.0, 10.0, 5.0),
),
Align(
alignment: Alignment.centerLeft,
child: Container(
margin: EdgeInsets.fromLTRB(10.0, 5.0, 10.0, 5.0),
child: Text(items[index].subtitle,
style: subtitleTextStyle)),
),
Container(
margin: EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(formatter.output.symbolOnLeft,
style: priceTextStyle),
Text("ADD TO CART", style: addToCardTextStyle)
],
),
)
],
),
],
),
),
);
Code of Grid View
Widget buildGridView() {
return Expanded(
child: GridView.count(
crossAxisCount: 2,
scrollDirection: Axis.vertical,
physics: PageScrollPhysics(),
shrinkWrap: true,
children: List.generate(items.length, (index) {
return buildRowItemsGrid(context, index);
})),
);
You need to set an appropriate childAspectRatio in the GridView like this.
GridView.count(
crossAxisCount: 2,
childAspectRatio: 2/3, //<-- width/height ratio depending on the child's content. Set accordingly.
//...
)
Edit:
The above part will solve the overflow problem. In addition to that, you can make the size of the Image widget adaptive like this so it can take up more space when available.
Image.network(
"https://fiverr-res.cloudinary.com/images/q_auto,f_auto/gigs/118898040/original/870e2763755963f5a300574bbea5977fa8b18460/sell-original-football-and-basketball-teams-jersey.jpg",
width: MediaQuery.of(context).size.width / 2.8,
height: MediaQuery.of(context).size.width / 2.8,
fit: BoxFit.fill,
)
You can also set the Column's mainAxisAlignment to spaceEvenly so its children can take up the space evenly when more space is available vertically.
Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
//...
)
I can't see the ScreenShot, but from the code I suggest you wrap The Second Column with Expanded and then the first column wrap it with SingleChildScrollView, that way it won't overflowed and you can scroll through if the contain inside were higher
I guess you have a fixed size for your Grid item. So it will overflow if the height of the Grid is not enough.
I have two ideas for you:
Use auto_size_text https://pub.dev/packages/auto_size_text
Expanded(
child: AutoSizeText(
'The text to display',
style: TextStyle(fontSize: 20),
maxLines: 2,
minFontSize: 1,
),
)
Increase the height of your Grid.
Would it work? Have you given it some fixed height in its parents? If given remove that, and then try this.
Widget buildRowItemsGrid(BuildContext context, int index) {
FlutterMoneyFormatter formatter =
FlutterMoneyFormatter(amount: items[index].price);
return Container(
child: Card(
elevation: 5.0,
margin: EdgeInsets.all(8.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
child: Image.network(
"https://fiverr-res.cloudinary.com/images/q_auto,f_auto/gigs/118898040/original/870e2763755963f5a300574bbea5977fa8b18460/sell-original-football-and-basketball-teams-jersey.jpg",
width: 100,
height: 100,
fit: BoxFit.fill),
),
Column(
children: [
Container(
child: Text(items[index].title,
style: titleTextStyle,
maxLines: 2,
overflow: TextOverflow.ellipsis),
margin: EdgeInsets.fromLTRB(10.0, 5.0, 10.0, 5.0),
),
Align(
alignment: Alignment.centerLeft,
child: Container(
margin: EdgeInsets.fromLTRB(10.0, 5.0, 10.0, 5.0),
child: Text(items[index].subtitle,
style: subtitleTextStyle)),
),
Container(
margin: EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(formatter.output.symbolOnLeft,
style: priceTextStyle),
Text("ADD TO CART", style: addToCardTextStyle)
],
),
)
],
),
],
),
),
);
Try wrapping the overflowing widget with a Flexible widget. The child of the Flexible widget will fill the available space in the main axis.

Flutter | border radius not apply on Android

I want to find out why border radius wouldn't apply top half of the widget on Android.
Here is the image on Android
However on the web, it's working like image below.
Does anyone know why?
Code
Center(
child: Card(
elevation: 1.5,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(16.0))),
child: SizedBox(
width: 250.0,
height: 150.0,
child: Column(
children: <Widget>[
Container(
width: double.infinity,
height: 60.0,
color: Colors.pink[200].withOpacity(0.95),
child: Center(
child: Text('Felicity Jones'),
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: Center(
child: Text('9:15'),
),
),
)
],
),
),
),
),
If you observe carefully by changing the opacity of the color for time being to:
color: Colors.pink[200].withOpacity(0.2),
You'll see that the top left and top right corners are cut-off and not filled by the color:
In order to avoid this, use Card widget's clipBehavior: Clip.antiAlias, property that covers all corners of the card with the given color. Here's the updated result:
Hope this answers your question.
You can try the following:
Center(
child:
Card(
elevation: 1.5,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(16.0))),
child: SizedBox(
width: 250.0,
height: 150.0,
child: Column(
children: <Widget>[
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.vertical(
top: new Radius.circular(16.0)
),
color: Colors.pink[200].withOpacity(0.95),
),
width: double.infinity,
height: 60.0,
child: Center(
child: Text('Felicity Jones'),
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: Center(
child: Text('9:15'),
),
),
)
],
),
),
),
),
Note that the color was moved inside the BoxDecoration as it will fail to compile otherwise.
I kept the shape attribute so that the lower part of the card will be rounded as well. You could tinker with that and remove it, if necessary.
Edit: In your case like #Darshan mentioned you can just set clipBehavior: Clip.antiAlias in Card widget.
You can use also use ClipRRect to force the child to have the given border radius, if you don't have clipBehavior.
Center(
child: Card(
elevation: 1.5,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16.0),
),
child: ClipRRect(
borderRadius: BorderRadius.circular(16.0),
child: SizedBox(
width: 250.0,
height: 150.0,
child: Column(
children: <Widget>[
Container(
width: double.infinity,
height: 60.0,
color: Colors.pink[200].withOpacity(0.95),
child: Center(
child: Text('Felicity Jones'),
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: Center(
child: Text('9:15'),
),
),
)
],
),
),
),
),
)

Flutter: Background image is squeezing when keyboard appears

Background image squeeze when the keyboard appears .
Scaffold(
body: Stack(
children: <Widget>[
Container(
width:double.infinity ,
height: double.infinity ,
child: Image.asset('assets/images/bg.png')),
Container(
child: SingleChildScrollView(
padding: EdgeInsets.all(width*0.10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
SizedBox(height: height*0.10,),
Container(decoration: BoxDecoration(color:Colors.transparent),child: Container(margin: EdgeInsets.only(bottom: height*0.02,left: 20.0,right: 20.0),child: Image.asset('assets/images/logo.png'),),),
SizedBox(height: height*0.05,),
Container(
decoration: BoxDecoration(color: Colors.transparent),
child: new Form(
key: _formKey,
autovalidate: _autoValidate,
child: LoginFrom(width,height))),
],
),
),
),
],
)
)
Or you should use a Scaffold parameter
resizeToAvoidBottomInset: false
Scaffold(
resizeToAvoidBottomInset: false,
body: (your_code)
)
If Layout of you contain TextField inside ScrollView then resizeToAvoidBottomInset: false makes you unable to scroll.
You can do this to fix it:
Wrap the Scaffold with Container. After make the background color of Scaffold to transparent.
#override
Widget build(BuildContext context) {
return Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/images/bg.png'),
fit: BoxFit.cover,
)),
child: Scaffold(
backgroundColor: Colors.transparent,
body: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: SingleChildScrollView(
-----------SingleChildScrollView with TextField-------------
Add resizeToAvoidBottomInset: false property to Scaffold.
to Scaffold
Scaffold(
resizeToAvoidBottomInset: false,
body: BodyWidget
)
Looks like you just need to move the background image to become the parent widget. i.e
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: Container(
width: double.infinity,
height: double.infinity,
decoration: BoxDecoration(
image: DecorationImage(
image: ExactAssetImage('assets/images/bg.png'),
fit: BoxFit.fill,
alignment:Alignment.topCenter,
),
),
child: Stack(
children: <Widget>[
Container(
child: SingleChildScrollView(
padding: EdgeInsets.all(width * 0.10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
SizedBox(
height: height * 0.10,
),
Container(
decoration: BoxDecoration(color: Colors.transparent),
child: Container(
margin: EdgeInsets.only(
bottom: height * 0.02, left: 20.0, right: 20.0),
child: Image.asset('assets/images/logo.png'),
),
),
SizedBox(
height: height * 0.05,
),
Container(
decoration:
BoxDecoration(color: Colors.transparent),
child: Container()
new Form(
key: _formKey,
autovalidate: _autoValidate,
child: LoginFrom(width, height))
),
],
),
),
),
],
)) // This trailing comma makes auto-formatting nicer for build methods.
);
height = max(height, MediaQuery.of(context).size.height);
Container(
decoration: BoxDecoration(
image: DecorationImage(
fit: BoxFit.cover,
image: imageProvider,
),
),
height: height,
child: Scaffold(...),
);
Wrap both of them(BG image, front) in SingleChildScrollView will do the trick
resizeToAvoidBottomPadding = false resolve with set this property in scaffold.
Scaffold(
resizeToAvoidBottomPadding: false,
)

How to set a BackdropFilter using dynamic-sized widgets in Flutter

I have a column: header with text, body with image, footer with text, all widgets have transparent backgrounds.
I want to set the background using a blur of the main image but I keep reaching dead ends.
In some situations this would be straight forward but in my scenario the image could be of any size and aspect ratio, and I need the effect to be wrapped with the column.
Here are my two failed attempts:
Method 1
I have a Stack with the image as the first item, then a BackdropFilter with ImageFilter blur, then my Column.
This works but the Image bleeds out from under the Column because of the image size (which can be any size).
I want to constrain it to the height of my Column.
return Container(
child: Stack(
alignment: AlignmentDirectional.topCenter,
children: <Widget>[
Positioned.fill(child: Image.network(_imgUrl)),
BackdropFilter(
filter: ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0),
child: Container(
decoration: BoxDecoration(color: Colors.white.withOpacity(0.0)),
)),
Container(
child: Column(
mainAxisSize: MainAxisSize.min,
// https://stackoverflow.com/a/41846093/3429021
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Header(),
BodyPhoto(),
Footer()
],
),
),
],
),
Method 2
Putting the column in a Container with a DecorationImage, which sizes the image perfectly, but I have no way of applying the blur effect.
(_streamItem is my Column wrapped in a container)
body: Container(child: _streamItem,
decoration: new BoxDecoration(image: DecorationImage(
image: NetworkImage(_streamItem.imgUrl),
fit: BoxFit.cover)
)
)
Any ideas?
I think you can consider using Positioned widget - it has width and height property. We can combine these widgets: Positioned > ClipRect > BackdropFilter. Please refer to the Gist: https://gist.github.com/anticafe/dc84cf6488d9defea437b702b13e2749#file-blur_multiple_widgets_with_dynamic_region-dart
Let take a look at this article to see more about BackdropFilter.
You can explicitly give a fix height to the container that contains the image, which will even look better.
In this example I have set three images of very different dimensions and has no problem rendering.
Refer the below code:
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('So Help'),
),
body: new ListView(
children: <Widget>[
MyContainer(
imageUrl:
'https://i.dailymail.co.uk/i/pix/2017/01/16/20/332EE38400000578-4125738-image-a-132_1484600112489.jpg',
),
MyContainer(
imageUrl:
'http://static.guim.co.uk/sys-images/Guardian/Pix/pictures/2014/4/11/1397210130748/Spring-Lamb.-Image-shot-2-011.jpg',
),
MyContainer(
imageUrl:
'http://wackymania.com/image/2011/6/vertical-panoramic-photography/vertical-panoramic-photography-15.jpg',
),
],
),
);
}
}
class MyContainer extends StatelessWidget {
final String imageUrl;
MyContainer({#required this.imageUrl});
#override
Widget build(BuildContext context) {
return new Container(
height: 300.0,
child: new Stack(
children: <Widget>[
new Container(
child: Image.network(
this.imageUrl,
width: MediaQuery.of(context).size.width,
fit: BoxFit.cover,
),
),
BackdropFilter(
filter: Dui.ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0),
child: new Container(
color: Colors.transparent,
),
),
new Container(
height: 300.0,
child: new Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
width: MediaQuery.of(context).size.width,
),
Padding(
padding: const EdgeInsets.all(20.0),
child: new Text(
'Header',
style: new TextStyle(color: Colors.white),
),
),
new Expanded(
child: Image.network(imageUrl),
),
Padding(
padding: const EdgeInsets.all(20.0),
child: new Text(
'Footer',
style: new TextStyle(color: Colors.white),
),
),
],
),
)
],
),
);
}
}

Categories

Resources