Flutter SingledChildScrollView > Stack > Positioned is glitches on Scroll - flutter

I am using a SingleChildScrollView with a Stack as its first element. The Stack contains two containers. The second one is positioned at bottom: 0.0 using a Positioned.
I highly simplified my view for this post to focus only on this issue. When I scroll slowly, you can see that the white container is "glitching" and you see a line that is the bottom of the first child of the stack.
Here is the view:
Not that's what happen when I scroll down, I have no clue why it's glitching like that:
View:
return Container(color: Colors.white, child: SingleChildScrollView(child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
HeaderComponent(),
Container(height: 600, width: MediaQuery.of(context).size.width)
]
)));
Header Component
class _HeaderComponentState extends State<HeaderComponent> {
#override
Widget build(BuildContext context) {
return Stack(
children: [
Container(height: 245.0, width: MediaQuery.of(context).size.width, color: Colors.red),
Positioned(bottom: 0.0, child: Container(height: 40.0, width:
MediaQuery.of(context).size.width, color: Colors.white)),
],
);
}
}

If that, just add bottom padding 0.2 at first child.
class HeaderComponent extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Stack(
children: [
Container(
height: 245.0,
padding: EdgeInsets.only(bottom: 0.2),
width: MediaQuery.of(context).size.width,
color: Colors.red),
Positioned(
bottom: 0.0,
child: Container(
height: 40.0,
width: MediaQuery.of(context).size.width,
color: Colors.white)),
],
);
}
}

I don't know root cause. But Positoned's 'bottom: 0.0' occurs upper container's background color a little during scrolling.
So when I set 'bottom: -0.2', this problem is not occured.
But it does not looks cool...
class HeaderComponent extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Stack(
children: [
Container(
height: 245.0,
width: MediaQuery.of(context).size.width,
color: Colors.red),
Positioned(
bottom: -0.2,
child: Container(
height: 40.0,
width: MediaQuery.of(context).size.width,
color: Colors.white)),
],
);
}
}

I suggest another solution like below.
class HeaderComponent extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
height: 245.0,
child: Column(
children: <Widget>[
Expanded(
child: Container(
width: MediaQuery.of(context).size.width, color: Colors.red),
),
Container(
height: 40.0,
width: MediaQuery.of(context).size.width,
color: Colors.white)
],
),
);
}
}

Related

Flutter OverflowBox is behind the next widget in a column

I'm working on a Flutter project and I am trying to use the OverflowBox widget.
I have a list of widgets in a Column, one of them, in the middle is supposed to overflow the others based on some events by the user.
Here is a simplified version of my code.
The red Container needs to display the green Container that overflows it at the top and the bottom.
But as you can see on the image, the green Container is only visible above the previous Container (the blue one) but not on the next one (the black Container). It looks like it is behind.
class MyScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
height: 100,
width: 100,
color: Colors.blue,
),
Container(
height: 100,
width: 100,
color: Colors.red,
child: Center(
child: OverflowBox(
maxHeight: 150,
child: Container(
color: Colors.green,
height: 150,
width: 50,
),
),
),
),
Container(
height: 100,
width: 100,
color: Colors.black,
)
],
);
}
}
How can I get my green Container to be above the black one too ?
EDIT: For functionality purposes, I need the green Container to be a child/be created by the red Container (and not by the list where I could use a Stack widget). I need the logic to be inside the red and green ones.
It still uses Stack, but Green Container is still part of Red Container.
And it might be difficult to calculate margin if Container has dynamic height.
class MyScreen extends StatelessWidget {
const MyScreen({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
Container(
height: 100,
width: 100,
color: Colors.blue,
),
Container(
margin: const EdgeInsets.only(top: 200),
height: 100,
width: 100,
color: Colors.black,
),
Container(
margin: const EdgeInsets.only(top: 100),
height: 100,
width: 100,
color: Colors.red,
child: Center(
child: OverflowBox(
maxHeight: 150,
child: Container(
height: 150,
width: 50,
color: Colors.green,
),
),
),
),
],
),
);
}
}
Use of overlay, maybe solve your problem.
OverlayState? overlayState = Overlay.of(context);
I tried your code snipped and failed to getting the design that you particularly wishing to achieve.
I have anther way to get such type of design. Which ia using Stacl() widget
Here is an complete example code snippet
import 'package:flutter/material.dart';
final Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: MyScreen(),
),
),
);
}
}
class MyScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Stack(
children: [
Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
height: MediaQuery.of(context).size.height/3,
width: MediaQuery.of(context).size.width,
color: Colors.blue,
),
Container(
height: MediaQuery.of(context).size.height/3,
width: MediaQuery.of(context).size.width,
color: Colors.red,
),
Container(
height: MediaQuery.of(context).size.height/3,
width: MediaQuery.of(context).size.width,
color: Colors.black,
)
],
),
Positioned(
// to set a specific position of your widget use Positioned inside a Stack() widget
/*
bottom: 50,
top: MediaQuery.of(context).size.height/3,
left: 100,
right: 100,
*/
child: OverflowBox(
child: Container(
color: Colors.green,
height: MediaQuery.of(context).size.height/2,
width: 100,
),
),
),
],
);
}
}
Output:

is there a way to embed a SingleChildScrollView (Vertical) within another SingleChildScrollView(Horizontal) in Flutter

In my app there is a SingleChildScrollView(with scrollable direction as Horizontal) which has a N number of containers.
Is there a way to embed a the SingleChildScrollView(with scrollable direction as Horizontal) into a SingleChildScrollView (with scrollable direction as Vertical) in Flutter.
for example:
class HomeBody extends StatelessWidget {
#override
Widget build(BuildContext context) {
return SafeArea(
child: Padding(
padding: sidePadding,
child: Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
HomeAppbar(),
addVerticalSpace(15),
Text(
'Welcome, Jack',
style: themeData.textTheme.headline1,
),
addVerticalSpace(15),
SearchField(
width: mediasize.width - 2 * screenHorizontalPadding,
height: mediasize.height,
),
addVerticalSpace(25),
//I want to add a SingleChildScrollView (Vertical Direction) from this point to
TitleMoreBar(barTitle: 'Trending'),
addVerticalSpace(15),
//the FullProductCardHorizontalList() has a SingleChildScrollView(Horizontal direction)
FullProductCardHorizontalList(),
addVerticalSpace(25),
TitleMoreBar(barTitle: 'Popular Brands'),
addVerticalSpace(25),
//the BrandCardList() has a SingleChildScrollView(Horizontal direction)
BrandCardList(),
// this where the SingleChildScrollView (Vertical) should end
],
),
),
),
);
}
Yes, you can do this like:
import 'package:flutter/material.dart';
class ScrollTraining extends StatefulWidget {
#override
_ScrollingTraining createState() => _ScrollingTraining();
}
class _ScrollingTraining extends State<ScrollTraining> {
double mWidth;
#override
Widget build(BuildContext context) {
mWidth = MediaQuery.of(context).size.width;
return Scaffold(
appBar: AppBar(),
body: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: mWidth,
height: 400,
color: Colors.indigo,
margin: EdgeInsets.symmetric(vertical: 8.0),
alignment: Alignment.center,
child: Text("Fixed Box"),
),
Container(
width: mWidth,
height: 200,
margin: EdgeInsets.symmetric(vertical: 8.0),
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: getChildren(),
),
),
),
Container(
width: mWidth,
height: 400,
color: Colors.brown,
margin: EdgeInsets.symmetric(vertical: 8.0),
alignment: Alignment.center,
child: Text("Fixed Box"),
),
Container(
width: mWidth,
height: 200,
margin: EdgeInsets.symmetric(vertical: 8.0),
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: getChildren(),
),
),
),
],
),
),
);
}
List<Widget> getChildren() {
List<Widget> output = List();
List<Color> colorList = [
Colors.redAccent,
Colors.deepOrange,
Colors.orangeAccent,
Colors.yellow,
Colors.lightGreenAccent,
Colors.green,
Colors.greenAccent,
Colors.blue,
Colors.purpleAccent,
Colors.pink,
];
for (int i = 0; i < 10; i++) {
output.add(Container(
width: 140,
height: 200,
color: colorList[i],
));
}
return output;
}
}
I hope it is useful for you.

How can I add a header card to a flutter card

I am trying to add a header card which will be displayed on the upper-left edge of a flutter card, so far I haven't been able to achieve that. This is an example of what I want
Being new to flutter, I didn't know there was a Stack widget. The solution is to stack two cards wrapped in Positioned widgets.
class SummaryCard extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
Positioned(
left: 0,
top: 40,
height: 200,
width: 350,
child: Card(
color: Colors.blue,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20)
),
),
),
Positioned(
left: 20,
top: 0,
height: 100,
width: 100,
child: Card(
color: Colors.green,
elevation: 10.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20)
),
),
),
],
);
}
}
You need to wrap header card with Align Widget.
Here is a full code:
class Cards extends StatefulWidget {
#override
_CardsState createState() => _CardsState();
}
class _CardsState extends State<Cards> {
#override
Widget build(BuildContext context) {
return Container(
height: 200,
width: 200,
child: Card(
elevation: 20,
child: Align(
alignment: Alignment.topLeft,
child: Container(
width:100,
height: 60,
child: Card(
elevation: 10,
child: Text("header"),
),
),
),
),
);
}
}
Containers are just for height and width control.
And here is a screenshot:

Problem with scrolling body of my Flutter web page

I'm trying to do my first flutter web page.
I want make navigation app bar on the top and scrollable area with pictures and text below.
And I have a problem with renering my page. Body of my page is not scrolling and it overflows at the bottom. What I'm doing wrong?
Here is my sample code:
#override
Widget build(BuildContext context) {
return Column(
children: [
TopBar(),
SingleChildScrollView(
child: Column(
children: [
Container(
height: 300,
color: Colors.red,
),
Container(
height: 300,
color: Colors.green,
),
Container(
height: 300,
color: Colors.black,
)
],
),
)
],
);
}
}
You can combine Column and ListView like:
#override
Widget build(BuildContext context) {
return Column(
children: [
AppBar(),
Expanded(
child: ListView(
children: [
Container(
height: 300,
color: Colors.red,
),
Container(
height: 300,
color: Colors.green,
),
Container(
height: 300,
color: Colors.black,
)
],
),
),
],
);
}

Flutter - Overlay card widget on a container

In flutter, is it possible to place a part of a card on another container? In CSS, we would set margin-top to a negative value or use translate property. In flutter as we cannot set negative values to margin-top, is there an alternative to that?
Yes, you can acheive it with a Stack widget. You can stack a card over the background and provide a top or bottom padding.
A simple example would look like:
class StackDemo extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new Stack(
children: <Widget>[
// The containers in the background
new Column(
children: <Widget>[
new Container(
height: MediaQuery.of(context).size.height * .65,
color: Colors.blue,
),
new Container(
height: MediaQuery.of(context).size.height * .35,
color: Colors.white,
)
],
),
// The card widget with top padding,
// incase if you wanted bottom padding to work,
// set the `alignment` of container to Alignment.bottomCenter
new Container(
alignment: Alignment.topCenter,
padding: new EdgeInsets.only(
top: MediaQuery.of(context).size.height * .58,
right: 20.0,
left: 20.0),
child: new Container(
height: 200.0,
width: MediaQuery.of(context).size.width,
child: new Card(
color: Colors.white,
elevation: 4.0,
),
),
)
],
);
}
}
The output of the above code would look something like:
Hope this helps!
Screenshot:
Instead of hardcoding Positioned or Container, you should use Align.
Code:
#override
Widget build(BuildContext context) {
final size = MediaQuery.of(context).size;
return Scaffold(
body: Stack(
children: [
Column(
children: [
Expanded(flex: 2, child: Container(color: Colors.indigo)),
Expanded(child: Container(color: Colors.white)),
],
),
Align(
alignment: Alignment(0, 0.5),
child: Container(
width: size.width * 0.9,
height: size.height * 0.4,
child: Card(
elevation: 12,
child: Center(child: Text('CARD', style: Theme.of(context).textTheme.headline2)),
),
),
),
],
),
);
}
Here is running example with overlay:
class _MyHomePageState extends State<MyHomePage> {
double _width = 0.0;
double _height = 0.0;
#override
Widget build(BuildContext context) {
_width = MediaQuery.of(context).size.width;
_height = MediaQuery.of(context).size.height;
return Scaffold(
backgroundColor: Colors.white,
body: Stack(
children: <Widget>[
// The containers in the background and scrollable
getScrollableBody(),
// This container will work as Overlay
getOverlayWidget()
],
),
);
}
Widget getOverlayWidget() {
return new Container(
alignment: Alignment.bottomCenter,
child: new Container(
height: 100.0,
width: _width,
color: Colors.cyan.withOpacity(0.4),
),
);
}
Widget getScrollableBody() {
return SingleChildScrollView(
child: new Column(
children: <Widget>[
new Container(
height: _height * .65,
color: Colors.yellow,
),
new Container(
height: _height * .65,
color: Colors.brown,
),
new Container(
margin: EdgeInsets.only(bottom: 100.0),
height: _height * .65,
color: Colors.orange,
),
],
),
);
}
}
Here is Result of code:
Scrollable Body under customised Bottom Bar