Flutter - Overlay card widget on a container - flutter

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

Related

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 to overlap a widget with a custom appbar

I want to achieve an effect similar to this one:
Here's what I have: (Blue container is hidden below the appBar)
And this is my current code:
Widget build(BuildContext context) {
return Scaffold(
appBar: GradesAppBar(
title: "Grades",
gradientBegin: Colors.red[200],
gradientEnd: Colors.red,
),
body: Stack(
fit: StackFit.expand,
overflow: Overflow.visible,
children: <Widget>[
Positioned(
top: -20,
left: MediaQuery.of(context).size.width / 2 - 150,
child: Container(
color: Colors.blue,
width: 300,
height: 60,
),
),
],
),
);
}
The GradesAppBar is a Container with boxShadow, borderRadius and gradient decoration.
When you're using stack to achieve this UI approach you should remove the AppBar and make it like this :-
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
alignment: Alignment.center,
fit: StackFit.expand,
overflow: Overflow.visible,
children: <Widget>[
GradesAppBar(
title: "Grades",
gradientBegin: Colors.red[200],
gradientEnd: Colors.red,
),
Positioned(
top: -20,
left: MediaQuery.of(context).size.width / 2 - 150,
child: Container(
color: Colors.blue,
width: 300,
height: 60,
),
),
],
),
);
}
The most important thing; if your GradesAppBar extends PreferredSizeWidget I think you should replace it with Container and give it some cool decorations as you want :")

Widget with width and offset relative to parent

I would like to render something that looks a bit like a scrollbar to indicate that I am on page 2/5. To do this, I would need a widget with the following:
The width is 20% width relative to the size of the parent
Top-left of the widget is offset by 40% relative to the size of the parent
I was able to accomplish the first point using a FractionallySizedBox but I'm not sure how to compose this to accomplish the offset. Thanks!
Here is a Flutter codepen illustrating what I have so far. I would like to offset this by 40% relative to the parent while still preserving the 20% width.
https://codepen.io/venkatd-the-bashful/pen/jOWYQXz
Snippet of the example below
class PagePositionDisplay extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: SizedBox(
height: 30,
width: 300,
child: Container(
color: Colors.grey,
child: FractionallySizedBox(
alignment: Alignment.topLeft,
heightFactor: 1,
widthFactor: 0.2,
child: Container(
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color: Colors.blue,
),
),
),
),
),
),
);
}
}
Try using Layout Builder with some row:
class PagePositionDisplay extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: SizedBox(
height: 30,
width: 300,
child: Container(
color: Colors.grey,
child: LayoutBuilder(builder: (context, constraints) {
return Row(
children: <Widget>[
SizedBox(
// your offset percentage * total width
width: (2 / 5) * constraints.maxWidth,
),
Container(
// your 'scrollbar' percentage * total width
width: (1 / 5) * constraints.maxWidth,
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color: Colors.blue,
),
),
],
);
}),
),
),
),
);
}
}

Flutter SingledChildScrollView > Stack > Positioned is glitches on Scroll

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)
],
),
);
}
}

transform crushed the container above flutter

I have a code that contains a column, and in the column there are 3 widgets, a widget container that has a height of 200 and a width of 200 in red, and the second widget contains a container with a child a transform scale that contains an image that I want to scale, and widget 3 contains the same as the first widget, every time I scale the image, what happens to the second container is always past the first container but does not occur with continaer to 3, if in css I will definitely use zindex, is there some kind of flutter zindex
this is the code
SingleChildScrollView(
physics: AlwaysScrollableScrollPhysics(),
child: Column(
children: <Widget>[
Container(
height: 300,
color: Colors.red,
),
Container(
// height: 397,
child: Transform.scale(
scale: 2.0,
child: Container(
width: MediaQuery.of(context).size.width,
child: Image(
image: NetworkImage(
"https://s3-ap-southeast-1.amazonaws.com//kriyapeople/8fa208d6-1486-4028-bd23-243581b4d3a7"),
fit: BoxFit.fitWidth,
),
),
),
),
Container(
height: 300,
color: Colors.red,
),
],
)));
and the result of that code
Use Stack widget,
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: HomePage(),
);
}
}
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: ListView(
children: <Widget>[
_buildHeader(),
for (final i in List.generate(20, (i) => i))
ListTile(title: Text("Tile $i")),
],
),
);
}
_buildHeader() {
double height = 250;
return SizedBox(
height: height,
child: Stack(
children: <Widget>[
Column(
children: <Widget>[
Container(
color: Colors.red,
height: height * 2 / 3,
),
Container(
color: Colors.grey[200],
height: height / 3,
),
],
),
Align(
alignment: Alignment.bottomCenter,
child: Image(
image: NetworkImage(
"https://s3-ap-southeast-1.amazonaws.com//kriyapeople/8fa208d6-1486-4028-bd23-243581b4d3a7"),
height: height * 2/3,
width: height * 2/3,
fit: BoxFit.cover,
),
),
],
),
);
}
}