I am making an app project in Flutter, where I want a blurred background Bottom Navigation Bar. How can I implement a bottom navigation bar in scaffold with blurred background property?
My code of Scaffold in Flutter
You can use the below one as widget and change background as image or color you wish and remove unwanted params as per you need.
class GlassBox extends StatelessWidget {
final double blurRadius, cornerRadius, width, height;
final Border outline;
final BoxShadow shadow;
final Color backgroundColor;
final Widget child;
const GlassBox({
Key? key,
this.width = 100,
this.height = 100,
this.blurRadius = 4.0,
this.cornerRadius = 10,
required this.child,
required this.outline,
required this.shadow,
this.backgroundColor = const Color(0x44ffffff),
}) : super(key: key);
#override
Widget build(BuildContext context) {
final double blurSigma = blurRadius * 0.57735 + 0.5;
final borderRadius = BorderRadius.circular(cornerRadius);
return Container(
width: width,
height: height,
child: Stack(
clipBehavior: Clip.none,
children: [
ClipPath(
clipper: _InvRRectClipper(cornerRadius),
child: Container(
decoration: BoxDecoration(
borderRadius: borderRadius,
boxShadow: [
if (shadow != null) shadow,
],
),
),
),
Container(
decoration: BoxDecoration(borderRadius: borderRadius),
clipBehavior: Clip.antiAlias,
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: blurSigma, sigmaY: blurSigma),
child: Container(color: const Color(0x0), child: child),
),
),
Container(
foregroundDecoration:
BoxDecoration(border: outline, borderRadius: borderRadius),
decoration: BoxDecoration(
color: backgroundColor,
borderRadius: borderRadius,
),
),
],
),
);
}
}
class _InvRRectClipper extends CustomClipper<Path> {
final double radius;
_InvRRectClipper([this.radius = 12]);
#override
Path getClip(Size size) {
final p = Path()
..addRRect(RRect.fromLTRBR(
0,
0,
size.width,
size.height,
Radius.circular(radius),
))
..addRect(Rect.largest)
..fillType = PathFillType.evenOdd;
return p;
}
#override
bool shouldReclip(covariant CustomClipper<Path> oldClipper) => true;
}
Using stroke method, how to create gradient line with sharp end in flutter? I want to draw the line as below in flutter.
Use CustomPainter to draw:
import 'package:flutter/material.dart';
void main() => runApp(Example());
class Example extends StatefulWidget {
#override
_ExampleState createState() => _ExampleState();
}
class _ExampleState extends State<Example> {
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: CustomPaint(
size: Size(200, 5),
painter: CurvePainter(),
),
)));
}
#override
void dispose() {
super.dispose();
}
}
class CurvePainter extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
var paint = Paint();
paint.color = Colors.black;
paint.style = PaintingStyle.fill; // Change this to fill
var path = Path();
path.moveTo(0, 0);
path.quadraticBezierTo(size.width / 2, size.height / 2, size.width, 0);
path.quadraticBezierTo(size.width / 2, -size.height / 2, 0, 0);
canvas.drawPath(path, paint);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
modified sleepingkit answer:
import 'package:flutter/material.dart';
class PointedLinePainter extends CustomPainter {
final double width;
PointedLinePainter(this.width);
#override
void paint(Canvas canvas, Size size) {
var paint = Paint();
paint.color = Colors.white;
paint.style = PaintingStyle.fill;
var path = Path();
path.moveTo(0, 0);
path.quadraticBezierTo(width / 3, 0.5, width, 0);
path.quadraticBezierTo(width / 3, -0.5, 0, 0);
canvas.drawPath(path, paint);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
somewhere in code:
Container(
margin: EdgeInsets.symmetric(horizontal: 10.0),
alignment: Alignment.centerLeft,
width: MediaQuery.of(context).size.width,
height: 2,
child: CustomPaint(
painter:
PointedLinePainter(width - 2 * horizontalPointedLineMargin),
),
)
Can't see your picture.You can use the CustomPaint widget to draw lines, define a class that extends CustomPainter, and use the canvas.drawLine() method.
Divider class
A thin horizontal line, with padding on either side.
In the material design language, this represents a divider. Dividers can be used in lists, Drawers, and elsewhere to separate content.
To create a divider between ListTile items, consider using ListTile.divideTiles, which is optimized for this case.
The box's total height is controlled by height. The appropriate padding is automatically computed from the height.
[![// Flutter code sample for Divider
// This sample shows how to display a Divider between an orange and blue box
// inside a column. The Divider is 20 logical pixels in height and contains a
// vertically centered black line that is 5 logical pixels thick. The black
// line is indented by 20 logical pixels.
//
// !\[\](https://flutter.github.io/assets-for-api-docs/assets/material/divider.png)
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
/// This Widget is the main application widget.
class MyApp extends StatelessWidget {
static const String _title = 'Flutter Code Sample';
#override
Widget build(BuildContext context) {
return MaterialApp(
title: _title,
home: Scaffold(
appBar: AppBar(title: const Text(_title)),
body: MyStatelessWidget(),
),
);
}
}
/// This is the stateless widget that the main application instantiates.
class MyStatelessWidget extends StatelessWidget {
MyStatelessWidget({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Center(
child: Column(
children: <Widget>\[
Expanded(
child: Container(
color: Colors.amber,
child: const Center(
child: Text('Above'),
),
),
),
const Divider(
color: Colors.black,
height: 20,
thickness: 5,
indent: 20,
endIndent: 0,
),
Expanded(
child: Container(
color: Colors.blue,
child: const Center(
child: Text('Below'),
),
),
),
\],
),
);
}
}]
Here info how to change style enter link description here
Row(
children: [
Expanded(
child: SizedBox(
height: 3,
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.white, Colors.black],
begin: Alignment.centerRight,
end: Alignment.centerLeft
)
),
),
),
),
Expanded(
child: SizedBox(
height: 3,
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.white, Colors.black],
begin: Alignment.centerLeft,
end: Alignment.centerRight
)
),
),
),
),
],
)
I am creating a story app where two users telling the story like this in the below images. so here I want to create a dialog box like the below image. but I don't know how to create
You should be implement below way
class IntroPage extends StatefulWidget {
#override
State<StatefulWidget> createState() => _IntroPageState();
}
class _IntroPageState extends State<IntroPage>
with SingleTickerProviderStateMixin {
AnimationController animationController;
bool _menuShown = false;
#override
void initState() {
animationController =
AnimationController(vsync: this, duration: Duration(milliseconds: 500));
super.initState();
}
#override
Widget build(BuildContext context) {
Animation opacityAnimation =
Tween(begin: 0.0, end: 1.0).animate(animationController);
if (_menuShown)
animationController.forward();
else
animationController.reverse();
return Scaffold(
backgroundColor: Colors.amberAccent,
body: Stack(
overflow: Overflow.visible,
children: <Widget>[
Positioned(
right: 0,
top:90,
child: InkWell(
onTap: () {
setState(() {
_menuShown = !_menuShown;
});
},
child: Image.asset(
'assets/images/girls.png',
height: 250,
),
),
),
Positioned(
child: FadeTransition(
opacity: opacityAnimation,
child: _DialogUI(),
),
right: 40.0,
top: 300.0,
),
],
),
);
}
}
class _DialogUI extends StatelessWidget {
_DialogUI();
final double padding = 8.0;
#override
Widget build(BuildContext context) {
return Center(
child: Material(
clipBehavior: Clip.antiAlias,
shape: _DialogShapeBorder(
borderRadius: BorderRadius.all(Radius.circular(padding)),
padding: padding),
elevation: 4.0,
child: Container(
margin: const EdgeInsets.all(10),
padding: EdgeInsets.all(padding).copyWith(bottom: padding * 2),
child: Center(
child: Text(
'Filler text is text that shares \nsome characteristics of a real written text, \n but is random or otherwise generated.\n It may be used to display a sample of fonts,\n generate text for testing, or to spoof an e-mail spam filter.'),
),
)),
);
}
}
class _DialogShapeBorder extends RoundedRectangleBorder {
_DialogShapeBorder({
#required this.padding,
side = BorderSide.none,
borderRadius = BorderRadius.zero,
}) : super(side: side, borderRadius: borderRadius);
final double padding;
#override
Path getOuterPath(Rect rect, {TextDirection textDirection}) {
return Path()
..moveTo(rect.width - 18.0, rect.top)
..lineTo(rect.width - 20.0, rect.top - 36.0)
..lineTo(rect.width - 52.0, rect.top)
..addRRect(borderRadius.resolve(textDirection).toRRect(Rect.fromLTWH(
rect.left, rect.top, rect.width, rect.height - padding)));
}
}
Output
Negative margin is generally not needed but there are situations where it’s really useful. For example: why use negative margins?
For now, when I set margin for a container to a negative value, I got the following error:
I/flutter ( 3173): 'package:flutter/src/widgets/container.dart': Failed assertion: line 251: 'margin == null ||
I/flutter ( 3173): margin.isNonNegative': is not true.
The container has a useful transform property.
child: Container(
color: Theme.of(context).accentColor,
transform: Matrix4.translationValues(0.0, -50.0, 0.0),
),
I'm gonna give an answer for this, mostly because I had to find a way to do this.
I would like to say that it is not ideal and could likely be accomplished in a better way, but it does give the desired effect.
As you can see, the text can be pulled negatively outside its parent using a stack:
Container(
constraints: BoxConstraints.loose(Size.fromHeight(60.0)),
decoration: BoxDecoration(color: Colors.black),
child:
Stack(
alignment: Alignment.topCenter,
overflow: Overflow.visible,
children: [
Positioned(
top: 10.0,
left: -15.0,
right: -15.0,
child: Text("OUTSIDE CONTAINER", style: TextStyle(color: Colors.red, fontSize: 24.0),)
)
]
)
)
To answer this question you first have to define what "negative margins", or really "margins" in general, really are. In CSS, margins have various meanings in the various layout models, most commonly, they are one of several values that contribute to computing the offset that the block layout model uses to place subsequent children; a negative total margin in this case merely means the next child is placed above the bottom of the previous child instead of after it.
In Flutter, as in CSS, there are several layout models; however, there is currently no widget that is equivalent to the CSS block layout model (which supports margin collapsing, negative margins, skipping floats, etc). Such a layout model could certainly be implemented, it just hasn't been implemented yet, at least not in the framework itself.
To implement such a layout model, you would create a RenderBox descendant similar to RenderFlex or RenderListBody, probably providing a way to set the margins of each child using a ParentDataWidget in the same way that Flex children can have their flex configured using the Expanded widget.
Probably the most complicated part of designing a new layout model like this would be deciding how to handle overflow or underflow, when the children are too big or too small to fit the constraints passed to this new layout render object. The RenderFlex render object has a way to distribute the space if the children underflow, and considers it an error if they overflow (in debug mode, this is shown by a yellow-and-black striped warning area and a message logged to the console); the RenderListBody render object on the other hand takes the view that the constraints must be unbounded in the main axis, which means you can basically only use this layout model inside a list (hence the name).
If writing a new layout model is not attractive, you could use one of the existing layout widgets that allow overlapping children. Stack is the obvious choice, where you set the explicit positions of each child and they can overlap arbitrarily (this is vaguely similar to the CSS absolute position layout model). Another option is the CustomMultiChildLayout widget, which lets you layout and position each child in turn. With this, you could position each child one after the other, simulating negative margins by setting the position of the subsequent child to a value that's derived from the size and position of the previous child, but such that the subsequent child's top is above the previous child's bottom.
If there's interest in a block-like layout model, we could certainly implement it (please file a bug and describe the model you'd like implemented, or, implement it yourself and send a pull request for review). So far, though, we've not found that it has been that useful in practice, at least not useful enough to justify the complexity.
To extend the accepted answer, you can wrap any widget with Transform.translate. It takes a simple Offset as parameter.
I find it is easier to use than the translation Matrix.
Transform.translate(
// e.g: vertical negative margin
offset: const Offset(-10, 0),
child: ...
),
The short answer is "No, it doesn't".
To give few more details, Flutter has a sophisticated but effective algorithm for rendering its widgets. Margins and Paddings are analyzed at runtime, and the final size and position of the widget is determined. When you try to issue a negative margine you are purposefully creating a not valide layout where a widget is somehow dropping out of the space it is supposed to occupy.
Consider reading the doc here.
Anyhow I believe you should formulate better the question in another thread and really ask a solution for the behavior you are trying to achieve with those negative margins. I am sure you'll get much more that way.
Cheers
No, Flutter does not allow negative margins but just in case you still want your widgets to overlap each other, you can use a Stack with Positioned which will allow you to generate the layout which you can do with negative margins.
Here is an example :
import 'package:flutter/material.dart';
class MyHomePage extends StatefulWidget {
MyHomePageState createState() => new MyHomePageState();
}
class MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return new Scaffold(
body: new Center(
child: new Container(
padding: const EdgeInsets.all(8.0),
height: 500.0,
width: 500.0,
child: new Stack(
overflow: Overflow.visible,
children: <Widget>[
new Icon(Icons.pages, size: 36.0, color: Colors.red),
new Positioned(
left: 20.0,
child: new Icon(Icons.pages, size: 36.0, color: Colors.green),
),
],
),
),
)
);
}
}
void main() {
runApp(new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.deepPurple,
),
home: new MyHomePage(),
));
}
This will result in :
NOTE: You can also give negative values in Positioned Widget.
You can use OverflowBox to disregard certain constraints.
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Container(
color: Colors.blue.shade300,
child: Padding(
padding: const EdgeInsets.all(20),
child: Column(
children: [
Expanded(
child: Container(
color: Colors.white,
child: Center(
child: Text('Padding on this one.'),
),
),
),
SizedBox(height: 20),
Expanded(
child: OverflowBox(
maxWidth: MediaQuery.of(context).size.width,
child: Container(
color: Colors.red.shade300,
child: Center(
child: Text('No padding on this one!'),
),
),
),
),
SizedBox(height: 20),
Expanded(
child: Container(
color: Colors.yellow.shade300,
child: Center(
child: Text('Look, padding is back!'),
),
),
),
],
),
),
),
),
);
}
Result:
A hack if you really want this (for example, me) and need performance:
Disadvantage: The hit testing has problem on those edges. But if you only want to display the widget without wanting to click it, it is completely fine.
How to use it: As if you are using Padding widget, except that now your padding can be negative and no errors will happen.
import 'dart:math' as math;
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
class AllowNegativePadding extends SingleChildRenderObjectWidget {
const AllowNegativePadding({
Key key,
#required this.padding,
Widget child,
}) : assert(padding != null),
super(key: key, child: child);
/// The amount of space by which to inset the child.
final EdgeInsetsGeometry padding;
#override
RenderAllowNegativePadding createRenderObject(BuildContext context) {
return RenderAllowNegativePadding(
padding: padding,
textDirection: Directionality.of(context),
);
}
#override
void updateRenderObject(BuildContext context, RenderAllowNegativePadding renderObject) {
renderObject
..padding = padding
..textDirection = Directionality.of(context);
}
#override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(DiagnosticsProperty<EdgeInsetsGeometry>('padding', padding));
}
}
class RenderAllowNegativePadding extends RenderShiftedBox {
RenderAllowNegativePadding({
EdgeInsetsGeometry padding,
TextDirection textDirection,
RenderBox child,
}) : assert(padding != null),
// assert(padding.isNonNegative),
_textDirection = textDirection,
_padding = padding,
super(child);
EdgeInsets _resolvedPadding;
void _resolve() {
if (_resolvedPadding != null) return;
_resolvedPadding = padding.resolve(textDirection);
// assert(_resolvedPadding.isNonNegative);
}
void _markNeedResolution() {
_resolvedPadding = null;
markNeedsLayout();
}
/// The amount to pad the child in each dimension.
///
/// If this is set to an [EdgeInsetsDirectional] object, then [textDirection]
/// must not be null.
EdgeInsetsGeometry get padding => _padding;
EdgeInsetsGeometry _padding;
set padding(EdgeInsetsGeometry value) {
assert(value != null);
// assert(value.isNonNegative);
if (_padding == value) return;
_padding = value;
_markNeedResolution();
}
/// The text direction with which to resolve [padding].
///
/// This may be changed to null, but only after the [padding] has been changed
/// to a value that does not depend on the direction.
TextDirection get textDirection => _textDirection;
TextDirection _textDirection;
set textDirection(TextDirection value) {
if (_textDirection == value) return;
_textDirection = value;
_markNeedResolution();
}
#override
double computeMinIntrinsicWidth(double height) {
_resolve();
final double totalHorizontalPadding = _resolvedPadding.left + _resolvedPadding.right;
final double totalVerticalPadding = _resolvedPadding.top + _resolvedPadding.bottom;
if (child != null) // next line relies on double.infinity absorption
return child.getMinIntrinsicWidth(math.max(0.0, height - totalVerticalPadding)) + totalHorizontalPadding;
return totalHorizontalPadding;
}
#override
double computeMaxIntrinsicWidth(double height) {
_resolve();
final double totalHorizontalPadding = _resolvedPadding.left + _resolvedPadding.right;
final double totalVerticalPadding = _resolvedPadding.top + _resolvedPadding.bottom;
if (child != null) // next line relies on double.infinity absorption
return child.getMaxIntrinsicWidth(math.max(0.0, height - totalVerticalPadding)) + totalHorizontalPadding;
return totalHorizontalPadding;
}
#override
double computeMinIntrinsicHeight(double width) {
_resolve();
final double totalHorizontalPadding = _resolvedPadding.left + _resolvedPadding.right;
final double totalVerticalPadding = _resolvedPadding.top + _resolvedPadding.bottom;
if (child != null) // next line relies on double.infinity absorption
return child.getMinIntrinsicHeight(math.max(0.0, width - totalHorizontalPadding)) + totalVerticalPadding;
return totalVerticalPadding;
}
#override
double computeMaxIntrinsicHeight(double width) {
_resolve();
final double totalHorizontalPadding = _resolvedPadding.left + _resolvedPadding.right;
final double totalVerticalPadding = _resolvedPadding.top + _resolvedPadding.bottom;
if (child != null) // next line relies on double.infinity absorption
return child.getMaxIntrinsicHeight(math.max(0.0, width - totalHorizontalPadding)) + totalVerticalPadding;
return totalVerticalPadding;
}
#override
void performLayout() {
final BoxConstraints constraints = this.constraints;
_resolve();
assert(_resolvedPadding != null);
if (child == null) {
size = constraints.constrain(Size(
_resolvedPadding.left + _resolvedPadding.right,
_resolvedPadding.top + _resolvedPadding.bottom,
));
return;
}
final BoxConstraints innerConstraints = constraints.deflate(_resolvedPadding);
child.layout(innerConstraints, parentUsesSize: true);
final BoxParentData childParentData = child.parentData as BoxParentData;
childParentData.offset = Offset(_resolvedPadding.left, _resolvedPadding.top);
size = constraints.constrain(Size(
_resolvedPadding.left + child.size.width + _resolvedPadding.right,
_resolvedPadding.top + child.size.height + _resolvedPadding.bottom,
));
}
#override
void debugPaintSize(PaintingContext context, Offset offset) {
super.debugPaintSize(context, offset);
assert(() {
final Rect outerRect = offset & size;
debugPaintPadding(context.canvas, outerRect, child != null ? _resolvedPadding.deflateRect(outerRect) : null);
return true;
}());
}
#override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(DiagnosticsProperty<EdgeInsetsGeometry>('padding', padding));
properties.add(EnumProperty<TextDirection>('textDirection', textDirection, defaultValue: null));
}
}
To overcome some horizontal padding you can create such a Widget:
Usage (will take out 8pt from the padding left and right.
const ExpandWidth(
child: MyWidget(),
width: 8,
)
Implementation:
class ExpandWidth extends StatelessWidget {
final double width;
final Widget child;
const ExpandWidth({
super.key,
required this.child,
this.width = 0,
});
#override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
return IntrinsicHeight(
child: OverflowBox(
maxWidth: constraints.maxWidth + width * 2,
child: child,
),
);
},
);
}
}
EDIT:
Margin Widget
I played a little around and wanted to share this here:
It's far from perfect, but at least anything to start with.
You can modify horizontal, vertical, left and top.
The interesting part is the Margin widget.
In this example all the grey container have a padding of 16.
Result
Code example of the screenshot
Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: 360,
height: 300,
color: Colors.black12,
padding: const EdgeInsets.all(16),
child: Container(
color: Colors.black38,
padding: const EdgeInsets.all(16),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Margin(
horizontal: -24,
top: -8,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
color: Colors.greenAccent.withOpacity(0.8),
child: const Center(child: Text('Horizontal: -24 & Top: -8')),
),
),
// const SizedBox(height: 8),
Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
color: Colors.greenAccent.withOpacity(0.8),
child: const Center(child: Text('No modification')),
),
const SizedBox(height: 8),
Margin(
vertical: -16,
top: -16,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
color: Colors.greenAccent.withOpacity(0.8),
child: const Center(child: Text('Vertical: -24 & Top: -16')),
),
),
],
),
Margin(
vertical: -16,
top: 32,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
color: Colors.greenAccent.withOpacity(0.8),
child: const Center(child: Text('Third')),
),
),
],
),
),
),
const SizedBox(height: 16),
Container(
width: 360,
height: 300,
color: Colors.black12,
padding: const EdgeInsets.all(16),
child: Container(
color: Colors.black38,
padding: const EdgeInsets.all(16),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Row(
children: [
Flexible(
child: Margin(
vertical: -24,
// horizontal: 8,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 4),
color: Colors.greenAccent.withOpacity(0.8),
child: const Center(child: Text('V -24')),
),
),
),
const SizedBox(width: 16),
Flexible(
child: Margin(
vertical: 0,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 4),
color: Colors.greenAccent.withOpacity(0.8),
child: const Center(child: Text('Nothing')),
),
),
),
],
),
),
const SizedBox(width: 16),
Margin(
vertical: -16,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 4),
color: Colors.greenAccent.withOpacity(0.8),
child: const Center(
child: Text(
'V\n-16',
textAlign: TextAlign.center,
)),
),
),
],
),
),
),
],
),
);
margin.dart
import 'package:flutter/material.dart';
class SizeProviderWidget extends StatefulWidget {
final Widget child;
final Function(Size) onChildSize;
const SizeProviderWidget({
super.key,
required this.onChildSize,
required this.child,
});
#override
_SizeProviderWidgetState createState() => _SizeProviderWidgetState();
}
class _SizeProviderWidgetState extends State<SizeProviderWidget> {
#override
void initState() {
_onResize();
super.initState();
}
void _onResize() {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
if (context.size is Size) {
widget.onChildSize(context.size!);
}
});
}
#override
Widget build(BuildContext context) {
///add size listener for every build uncomment the fallowing
///_onResize();
return widget.child;
}
}
class Margin extends StatefulWidget {
const Margin({
super.key,
required this.child,
this.horizontal = 0,
this.vertical = 0,
this.left = 0,
this.top = 0,
});
final Widget child;
final double horizontal;
final double vertical;
final double top;
final double left;
#override
State<Margin> createState() => _MarginState();
}
class _MarginState extends State<Margin> {
Size childSize = Size.zero;
#override
Widget build(BuildContext context) {
final horizontalMargin = widget.horizontal * 2 * -1;
final verticalMargin = widget.vertical * 2 * -1;
final newWidth = childSize.width + horizontalMargin;
final newHeight = childSize.height + verticalMargin;
if (childSize != Size.zero) {
return LimitedBox(
maxWidth: newWidth,
maxHeight: newHeight,
child: OverflowBox(
maxWidth: newWidth,
maxHeight: newHeight,
child: Transform.translate(
offset: Offset(widget.left, widget.top),
child: SizedBox(
width: newWidth,
height: newHeight,
child: widget.child,
),
),
),
);
}
return SizeProviderWidget(
child: widget.child,
onChildSize: (size) {
setState(() => childSize = size);
},
);
}
}
You can try something like this:
import 'package:flutter/material.dart';
void main() => runApp(MaterialApp(
home: MyApp(),
));
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('text'),
),
body: Container(
child: Center(
child: Column(
children: <Widget>[
Container(
height: 300.0,
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(
"https://images.unsplash.com/photo-1539450780284-0f39d744d390?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=d30c5801b9fff3d4a5b7f1522901db9f&auto=format&fit=crop&w=1051&q=80"),
fit: BoxFit.cover)),
child: Stack(
alignment: Alignment.topCenter,
overflow: Overflow.visible,
children: [
Positioned(
top: 200.0,
child: Card(
child: Text("Why not?"),
))
]))
],
),
),
),
);
}
}