Flutter: Overlap Edge of Widget with second Widget - flutter

I want to overlap the bottom edge of a widget with another widget so that it looks like this:
I am using a stack to position the arrow button over the card. At the moment I just set the position with an invisible box above it. The issue is that this method only works for that exact resolution - it should be screen size independent.
The necessary code for the widget:
Stack(
children: <Widget>[
Container( //background
height: 100,
width: 100,
),
FloatingActionButton(
child: Icon(Icons.arrow_forward),
onPressed: () {},
)
],
)

Update - April 2021
You can no longer use the overflow property in a Stack widget as it has been deprecated. Use clipBehaviour instead. Source: Flutter docs
You can use the Stack and Positioned widget to achieve this UI.
Stack(
clipBehavior: Clip.none,
children: <Widget>[
Container(
color: Colors.amber,
height: 150,
width: 150,
),
Positioned(
child: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
print('FAB tapped!');
},
backgroundColor: Colors.blueGrey,
),
right: 0,
left: 0,
bottom: -26,
),
],
),
Output:
Update - March 2022
The Area which is outside of Stack won't be clickable due to the platform limitation, and that is how the Stack widget works.
You can learn more about the same in this issue.

As of November 2019 I'd like to add a second solution:
Using package: https://pub.dev/packages/assorted_layout_widgets
var widget1 = ...;
var widget2 = ...;
ColumnSuper(
children: [widget1, widget2],
innerDistance: -26,
);
The difference from this solution to the one using Stack is that Positioned widgets in a Stack don't occupy vertical space. However, the ColumnSuper will have the size of all of its children widgets. Note I am the author of this package.

You could try my package (signed_spacing_flex). It's exactly the same as a normal Column (or Row and Flex). But it lets you set negative spacing which causes its children to overlap. You can also set which children should be on top when they overlap.
In your case it would be something like:
SignedSpacingColumn(
spacing: -16.0,
stackingOrder: StackingOrder.lastOnTop,
children: [
Container(
height: 100,
width: 100,
color: Colors.red,
),
FloatingActionButton(
child: const Icon(Icons.arrow_forward),
onPressed: () {},
)
],
)
It works with expanded children if you need.

Related

How to have Label text with graphics over image(product image of e commerce app) in flutter?

I am trying to get a text label with graphics over the image. Labels like new arrival, best seller, limited, on sale just like on the pic attached.
enter image description here
Here's what i think the skeletal layout would be :
return Stack(
children: [
Card(
color: Colors.black54,
child: Image.asset('assets/xyz.png'),
),
Align(
//for bottomRight
alignment: Alignment.bottomRight,
child: Image.asset(
'assets/fireimg.png',
), //can be an SVG converted to png
),
Align(
//for topLeft
alignment: Alignment.topLeft,
child: Image.asset(
'assets/label.png',
), //can be an SVG converted to png
),
],
);
Feel free to give the Padding of your choice.
it has so much code to write , so i will give some examples to achieve that output
in this image ,i mentioned 0 and one .
for all 1
solution 1
you can use image like this way
Stack(
children: [
Container(
width: 200,
height: 200,
color: Colors.amber,// added only for view this example
child:Image() // add Product image here
),
Positioned(
top: 20, //change according to your use case position
left: 0,// change according to your use case position
child: Container(
color: Colors.black, // added only for view this example
decoration: BoxDecoration(image: ),// add label image here
width: 100,
height: 50,
child: Row(
children: [Text('hi')],
),
))
],
)
solution 2
you can use custom paint for label layout
not that
in both solution you have to use stack and position widgets , you can control position according to your use case
for all 0
you can use RotationTransition widgets to achieve this
not that
you have to use stack and position widgets , you can control position according to your use case
for the vertical Text
use this example
String exText = "meta";
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('hi'),
),
body: Container(
width: 200,
height: 200,
color: Colors.amber,
child: Column(
children: exText.characters
.map((e) => Container(
child: Text('$e'),
))
.toList()),
),
out put will be

Flutter align two widgets in same position on stack

I have 2 widget in stack. One of them is aligned in center. And the widget which is on the top is other stack. And I want show second widget with first widget's top and left position. Here is the explain:
The yellow area is my stack. And first widget is setted like Center(child: myFirstWidget). My second widget is referenced from here it's a resizable widget so it's an another stack and it's childs are "positioned". So I need to set top and left value for initialize. But my main stack filled page So when I set my second widget's top and left to 0. It's shown as below.
But I want to show align it to centered child's top like:
My code snip:
child: Container(
color: Colors.red,
child: Stack(
children: [
Center(
child: Image.file(
File("myfilepath"),
),
),
ResizableWidget(
child: Container(
color: Colors.blue,
),
),
],
),
),
You can adjust the position of the widgets with the Position widget like this:
Positioned(
child: ResizableWidget(
child: Container(
color: Colors.blue,
),
),
top: 80,
right: -5,
),
The value of top and right are just random values, you should check what works for you!
You should make Center the parent of the Stack.
The Stack will be positioned at the center of its parent because of Center, it will get the dimensions of its biggest childs (height and width) and will position other childs according to the alignment value.
Edit : I modified the code to include a placeHolder image. Here I gave it a 6000x2000 size but you can change it to whatever value you want. Code is working as expected, see capture below.
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Center(
child: Stack(
alignment: AlignmentDirectional.topStart,
children: [
Image.network('https://via.placeholder.com/6000x2000'),
SizedBox(
height: 50,
width: 50,
child: Container(
color: Colors.green,
))
],
),
),
);
}

Flutter - How to wrap list of chipsets with a button horizontally together

I'm new to flutter and have been trying to get a list of chipsets wrapped in a Wrap widget with the ability to add more of them through a button shown in the image. However, the button isn't able to wrap along with the chipset horizontally. Below is an image of the design to make it clearer.
Code:
Container(
child: Wrap(
children: [
Container(
child: Wrap(
children: _chipsetList,
),
),
SizedBox(width: 2),
Container(
height: 35,
width: 35,
child: FittedBox(
child: FloatingActionButton(
heroTag: null,
elevation: 0,
shape: StadiumBorder(
side: BorderSide(width: 2.0)),
onPressed: () {
_getMoreChips(context);
},
child: Icon(Icons.add),
),
))
],
),),
I tried to experiment with SingleChildScrollView property or with Wrap direction but in vain. What could be a way to get this design working?
Seems you want to put chips and the button in the single wrap. To do so, combine them in a single list and use this list as wrap's children
List<Widget> items = List.from(_chipsetList); // copy
Widget button = FloatingActionButton();
items.add(button);
Wrap(
children: items,
)
Or, using spread operator
Wrap(
children: [
..._chipsetList,
FloatingActionButton(),
],
)

How do I place my widget in the top Center location using Media Query in Flutter?

I have the following dial located at the center of my screen.
I have called three different part to construct this dial.
However it seems to be stuck in the center of my screen and I want to shift it to the top center portion. Ive tried changing the alignments but it doesn't seem to work.
This is my code:
This is the dependency I'm using: https://pub.dev/packages/flutter_neumorphic
import 'package:flutter_neumorphic/flutter_neumorphic.dart';
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
pedometerOuterDial(context),
pedometerInnerDial(context),
Center(child: stepText()),
],
);
}
Widget stepText() {
return Text(
'4800\nSteps',
style: khomeStyle.copyWith(color: kOrange),
);
}
Widget pedometerOuterDial(context) {
final percentage = 30.0;
return Padding(
padding: const EdgeInsets.all(80.0),
child: Align(
alignment: Alignment.topCenter,
child: Neumorphic(
boxShape: NeumorphicBoxShape.circle(),
padding: EdgeInsets.all(10),
style: NeumorphicStyle(
depth: NeumorphicTheme.embossDepth(context),
),
child: CustomPaint(
painter: NeuProgressPainter(
circleWidth: 20,
completedPercentage: percentage,
defaultCircleColor: Colors.transparent,
),
child: Center(),
),
),
),
);
}
Widget pedometerInnerDial(context) {
return Align(
child: Neumorphic(
boxShape: NeumorphicBoxShape.circle(),
padding: EdgeInsets.all(80),
style: NeumorphicStyle(
color: Colors.white,
depth: NeumorphicTheme.depth(context),
),
),
);
}
Also I haven't used Media Query here for any of the dials, so will that be an issue for displaying on other devices?
Since you are using a stack widget, the best way to do this is to use a positioned widget. You can place the widget on top by wrapping it with Positioned and setting the top property to 0.
Here is an example:
Positioned(
top:0,
child:YourWidget(),
),
Alignment won't work for the stack widget because it only aligns the items when there are extra space around it. Example: It works in a Column or Row since they occupy space and allow the widgets inside it to be placed and move around the occupied space.

The equivalent of wrap_content and match_parent in flutter?

In Android match_parent and wrap_content are used to resize the widgets automatically relative to their parent to the content the widget contains.
In Flutter it seems by default all widgets are set to wrap_content, how would I change it such that I can fill its width and height to that of its parent?
You can do with little Trick:
Suppose you have requirement of :
( Width,Height )
Wrap_content ,Wrap_content :
//use this as child
Wrap(
children: <Widget>[*your_child*])
Match_parent,Match_parent:
//use this as child
Container(
height: double.infinity,
width: double.infinity,child:*your_child*)
Match_parent,Wrap_content :
//use this as child
Row(
mainAxisSize: MainAxisSize.max,
children: <Widget>[*your_child*],
);
Wrap_content ,Match_parent:
//use this as child
Column(
mainAxisSize: MainAxisSize.max,
children: <Widget>[your_child],
);
In order to get behavior for match_parent and wrap_content we need to
use mainAxisSize property in Row/Column widget, the mainAxisSize
property takes MainAxisSize enum having two values which is
MainAxisSize.min which behaves as wrap_content and MainAxisSize.max
which behaves as match_parent.
Link of the original Article
The short answer is that the parent doesn't have a size until the child has a size.
The way layout works in Flutter is that each widget provides constraints to each of its children, like "you can be up to this wide, you must be this tall, you have to be at least this wide", or whatever (specifically, they get a minimum width, a maximum width, a minimum height, and a maximum height). Each child takes those constraints, does something, and picks a size (width and height) that matches those constraints. Then, once each child has done its thing, the widget can can pick its own size.
Some widgets try to be as big as the parent allows. Some widgets try to be as small as the parent allows. Some widgets try to match a certain "natural" size (e.g. text, images).
Some widgets tell their children they can be any size they want. Some give their children the same constraints that they got from their parent.
There are actually some options available:
You can use SizedBox.expand to make your widget match parents dimensions, or SizedBox(width: double.infinity) to match only the width or SizedBox(heigth: double.infinity) to match only the heigth.
If you want a wrap_content behavior it depends on the parent widget you are using, for example if you put a button on a column it will behave like wrap_content and to use it like match_parent you can wrap the button with a Expanded widget or a sizedbox.
With a ListView the button gets a match_parent behavior and to get a wrap_content behavior you can wrap it with a Flex widget like Row.
Using an Expanded widget makes a child of a Row, Column, or Flex
expand to fill the available space in the main axis (e.g., horizontally for
a Row or vertically for a Column).
https://docs.flutter.io/flutter/widgets/Expanded-class.html
Using a Flexible widget gives a child of a Row, Column, or Flex the flexibility to expand to fill the available space in the main axis (e.g., horizontally for a Row or vertically for a Column), but, unlike Expanded, Flexible does not require the child to fill the available space.
https://docs.flutter.io/flutter/widgets/Flexible-class.html
Use the widget Wrap.
For Column like behavior try:
return Wrap(
direction: Axis.vertical,
spacing: 10,
children: <Widget>[...],);
For Row like behavior try:
return Wrap(
direction: Axis.horizontal,
spacing: 10,
children: <Widget>[...],);
For more information: Wrap (Flutter Widget)
I used this solution, you have to define the height and width of your screen using MediaQuery:
Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width
)
To make a child fill its parent, simply wrap it into a FittedBox
FittedBox(
child: Image.asset('foo.png'),
fit: BoxFit.fill,
)
A simple workaround:
If a container has only one top level child, then you can specify alignment property for the child and give it any available value. it'll fill all the space in the container.
Container(color:Colors.white,height:200.0,width:200.0,
child:Container(
color: Colors.yellow,
alignment:Alignment.[any_available_option] // make the yellow child match the parent size
)
)
Another way:
Container(color:Colors.white,height:200.0,width:200.0,
child:Container(
color: Colors.yellow,
constraints: BoxConstraints.expand(height: 100.0), // height will be 100 dip and width will be match parent
)
)
Stack(
children: [
Container(color:Colors.red, height:200.0, width:200.0),
Positioned.fill(
child: Container(color: Colors. yellow),
)
]
),
Use FractionallySizedBox widget.
FractionallySizedBox(
widthFactor: 1.0, // width w.r.t to parent
heightFactor: 1.0, // height w.r.t to parent
child: *Your Child Here*
}
This widget is also very useful when you want to size your child at a fraction of its parent's size.
Example:
If you want the child to occupy 50% width of its parent, provide widthFactor as 0.5
Match Parent
To match or fill the parent (height & width) we can use additional constraints on Container:
Container(
constraints: BoxConstraints.expand(), // ← this guy
child: Text('Center > Container > Text')
)
In Flutter, constraints are the space you can fill (or must fill, if "tight" constraints).
Constraints are given... no actually, imposed by parents.
By default, Container will wrap its content (child:) & size itself to its child, unless overriden (or not allowed by tight constraints).
Using the constraints: argument, we can give Container additional constraints to override default Container constraint behavior (such as wrapping content).
Using Container(constraints: BoxConstraints.something) doesn't overwrite incoming/parent constraints; It just allows us to override default behavior, where allowed, such as wrapping content.
Code Sample - BoxConstraints
Here's a copy/paste code example showing effects of various constraints we can apply to a Container that has "loose" incoming/parental constraints (provided by Center).
import 'package:flutter/material.dart';
class MatchParentPage extends StatefulWidget {
#override
_MatchParentPageState createState() => _MatchParentPageState();
}
class _MatchParentPageState extends State<MatchParentPage> {
BoxConstraints constraints;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Match Parent'),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Expanded( // shares space constraint evenly with other Expanded
child: Center( // ← fills tight parent constraint & loosens ↓ child constraint ↓
child: Container( // got loose constraint from Center...
constraints: constraints, // can apply many additional constraints
color: Colors.lightBlueAccent.withOpacity(.3),
child: Text('Center > Container > Text')),
),
),
Expanded(
child: Container(
color: Colors.orangeAccent,
child: Wrap(
children: [
_button('default', null),
_button('*expand()', BoxConstraints.expand()),
_button('*tight(Size.infinite)', BoxConstraints.tight(Size.infinite)),
_button('tight(Size.zero)', BoxConstraints.tight(Size.zero)),
_button('tight(Size.fromHeight(100))', BoxConstraints.tight(Size.fromHeight(100))),
_button('tight(Size.fromWidth(100))', BoxConstraints.tight(Size.fromWidth(100))),
_button('tightForFinite(width: 100, height: 100)', BoxConstraints.tightForFinite(width: 100, height: 100)),
_button('loose(Size.infinite)', BoxConstraints.loose(Size.infinite)),
_button('tightFor(width: double.infinity)', BoxConstraints.tightFor(width: double.infinity)),
_button('tightFor(height: double.infinity)', BoxConstraints.tightFor(height: double.infinity)),
])
),
)
],
),
);
}
Widget _button(String label, BoxConstraints _constraints) {
bool _active = _constraints == constraints;
return Padding(
padding: const EdgeInsets.only(top:8, left: 8),
child: RaisedButton(
color: _active ? Colors.cyanAccent : null,
child: Text(label),
onPressed: () {
setState(() => constraints = _constraints);
},
),
);
}
}
Use this line of codes inside the Column.
For wrap_content : mainAxisSize: MainAxisSize.min
For match_parent : mainAxisSize: MainAxisSize.max
MATCH_PARENT
FractionallySizedBox(
widthFactor: 1.0, // width w.r.t to parent
heightFactor: 1.0, // height w.r.t to parent
child: ElevatedButton(
onPressed: () {},
child: Text("+"),
),
)
OR
Container(
height: double.infinity,
width: double.infinity,
child: ElevatedButton(
onPressed: () {},
child: Text("+"),
),
)
OR
Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: ElevatedButton(
onPressed: () {},
child: Text("+"),
),
)
OR
Container(
constraints: BoxConstraints.expand(),
child: ElevatedButton(
onPressed: () {},
child: Text("+"),
),
)
WRAP_CONTENT
Wrap(children: [
Container(
child: ElevatedButton(
onPressed: () {},
child: Text("+"),
),
),
])
OR
Container(
constraints: BoxConstraints.tightFor(),
child: ElevatedButton(
onPressed: () {},
child: Text("+"),
),
)
Match_parent,Wrap_content :
Row(
children: [
Expanded(
child: Container(
child: ElevatedButton(
onPressed: () {},
child: Text("+"),
),
),
),
])
Wrap_content,Match_parent :
Column(
children: [
Expanded(
child: Container(
child: ElevatedButton(
onPressed: () {},
child: Text("+"),
),
),
),
])
For match parent option you can wrap your widget by a container and give it a width like this
width: double.infinity
this approach will make the widget fill max space available for it on the screen.