Related
I can't figure out how to make the FAB smaller inside the first Container in the list. It seems to want to occupy the complete container, no matter what I try. Ive even tried a container within a container. The complete Orange area is clickable. I tried SizedBox, same result. Here is the code.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
final title = 'Horizontal List';
return MaterialApp(
title: title,
home: Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Container(
margin: EdgeInsets.symmetric(vertical: 20.0),
padding: EdgeInsets.all(30),
height: 200.0,
child: ListView(
scrollDirection: Axis.horizontal,
children: <Widget>[
Container(
width: 160,
color: Colors.yellowAccent,
child: SizedBox(
height: 50,
width: 50,
child: FittedBox(
child: FloatingActionButton(
backgroundColor: Colors.deepOrange,
foregroundColor: Colors.indigo,
child: Icon(Icons.add, size: 20),
onPressed: () {},
),
),
),
),
Container(
width: 160.0,
color: Colors.red,
),
Container(
width: 160.0,
color: Colors.blue,
),
Container(
width: 160.0,
color: Colors.green,
),
Container(
width: 160.0,
color: Colors.yellow,
),
Container(
width: 160.0,
color: Colors.orange,
),
],
),
),
),
);
}
}
I have 2 samples. And Please refer Basic Widgets for more detail.
Use margin of Container. Please refer the code as below:
child: SizedBox(
height: 50,
width: 50,
child: Container(
margin: EdgeInsets.only(left:80.0, top:80.0, bottom: 10.0) ,
child: FloatingActionButton(
backgroundColor: Colors.deepOrange,
foregroundColor: Colors.indigo,
child: Icon(Icons.add),
onPressed: () {},
),
),
),
Use Row or Column. Please refer the code as below:
child: SizedBox(
height: 50,
width: 50,
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[ FloatingActionButton(
backgroundColor: Colors.deepOrange,
foregroundColor: Colors.indigo,
child: Icon(Icons.add),
onPressed: () {},
),
]),
),
I am using this kind of style in an app I'm trying to create for learning. Now the problem I have is that I only can make this using a RaisedButton but obviously sometimes I would need it to just be a container or sizebox, with no click effect. for example I use this code:
Widget titleSettings(String title){
return Container(
margin: EdgeInsets.fromLTRB(80.0, 0.0, 80.0, 20.0),
width: MediaQuery.of(context).size.width,
child: new RaisedButton(
padding: EdgeInsets.all(10.0),
elevation: 0.0,
color: Colors.white.withOpacity(.8),
highlightElevation: 0.0,
onPressed: () {
print("titleSettingPressed");
},
splashColor: Colors.white.withOpacity(.8),
highlightColor: Colors.white.withOpacity(.8),
shape: BeveledRectangleBorder(
side: BorderSide(color: Colors.black, width: 2.5),
borderRadius: new BorderRadius.circular(15.0)),
child: AutoSizeText("$title", style: TextStyle(fontSize: 30.0),),
)
);
}
but in this case I don't need to manage any click, It should only contain a text like it is in the child.
I've extracted below sample from the raised button definition inside flutter packages. check if its the same thing you're trying to reach:
child: Material(
elevation: 0.0,
type: MaterialType.button,
color: Colors.white.withOpacity(.8),
shape: BeveledRectangleBorder(
side: BorderSide(color: Colors.black, width: 2.5),
borderRadius: new BorderRadius.circular(15.0)),
child: IconTheme.merge(
data: IconThemeData(
color: Colors.white.withOpacity(.8),
),
child: Container(
padding: EdgeInsets.all(10.0),
child: Center(
widthFactor: 1.0,
heightFactor: 1.0,
child: Text(
"Timers",
style: TextStyle(fontSize: 30.0),
),
),
),
),
),
I've a Material widget to wrap a MaterialButton to make border radius, but I can't set the width attribute to it. I tried use a SizedBox but not works, the Material widget keep using all space of screen.
Code:
return new SizedBox(
width: 40,
child: Material(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(22.0)),
elevation: 18.0,
color: Color(0xFF801E48),
clipBehavior: Clip.antiAlias,
child: MaterialButton(
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
height: 30.0,
child: new Text('Sair',
style:
new TextStyle(fontSize: 16.0, color: Colors.white)),
),
),
);
Result:
Clearly it not have 40.0 of width size.
A better approach is using Container widget. When you need to change width, height or add padding/margin to any widget you should wrap the target widget into a container. The container widget is for this kind of job.
Container(
width: myWidthValue, // Container child widget will get this width value
height: myHeghtValue, // Container child widget will get this height value
padding: allowPaddingToo, // padding is allowed too
child: Material(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(22.0)),
elevation: 18.0,
color: Color(0xFF801E48),
clipBehavior: Clip.antiAlias, // Add This
child: MaterialButton(
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
height: 30.0,
child: new Text('Sair',
style:
new TextStyle(fontSize: 16.0, color: Colors.white)),
onPressed: () {
setState(() {
_isNeedHelp = false;
});
},
),
),
);
This is how you can set the size, padding, and margin of widgets in general. here is an example for Button:
Container(
margin: EdgeInsets.only(top: 10), // Top Margin
child:
ElevatedButton(
style: TextButton.styleFrom(
// Inside Padding
padding: EdgeInsets.symmetric(horizontal: 0, vertical: 20),
// Width,Height
minimumSize: Size(300, 30),
),
child: Text('Upload Data'),
onPressed: () {submitForm();},
),
),
Solved using Padding:
return Padding(
padding: EdgeInsets.fromLTRB(50, 0, 50, 0),
child: Material(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(22.0)),
elevation: 18.0,
color: Color(0xFF801E48),
clipBehavior: Clip.antiAlias, // Add This
child: MaterialButton(
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
height: 30.0,
child: new Text('Sair',
style:
new TextStyle(fontSize: 16.0, color: Colors.white)),
onPressed: () {
setState(() {
_isNeedHelp = false;
});
},
),
),
);
Result:
The red rectangle center of my widget is too big and is not responsive to width and height arguments.
I have updated flutter, and android studio. I started with a container in the shape of a circle then, I used a flatbutton and gave it a shape. but when it becomes the rectangle it is the same size as the circle it resizes in. _isRecord is a boolean that is toggled when the button is pressed.
return Container(
width: 80.0,
height: 80.0,
child: Container(
child: FlatButton(
onPressed: _press,
),
decoration: new BoxDecoration(
color: Colors.red,
shape: _isRecording ? BoxShape.rectangle : BoxShape.circle,
borderRadius: _isRecording ? BorderRadius.all(Radius.circular(8.0)) : null,
),
),
decoration: new BoxDecoration(
color: Colors.black,
shape: BoxShape.circle,
border: Border.all(width: 5.0, color: Colors.white),
),
);
It should look and function like the Voice Memos' record button. It should be a white circle stroke with a red center that when pressed becomes a smaller, rounded rectangle.
You can use your Widget inside Padding
exam:
InkWell(
splashColor: Colors.transparent,
highlightColor: Colors.transparent,
onTap: () {
setState(() {
_isRecording = !_isRecording;
});
},
child: DecoratedBox(
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(width: 5.0, color: Colors.white),
),
child: Padding(
padding: EdgeInsets.all(32.0),
child: Container(
width: 40.0,
height: 40.0,
child: Container(
decoration: new BoxDecoration(
color: Colors.red,
shape:
_isRecording ? BoxShape.rectangle : BoxShape.circle,
borderRadius: _isRecording
? BorderRadius.all(Radius.circular(8.0))
: null,
),
),
),
),
),
)
I need to stack widgets like this:
I wrote the code below. However the coins are coming one after another with some default padding. How can I get something like the image above?
Row(
children: <Widget>[
Icon(
Icons.monetization_on, size: 36.0,
color: const Color.fromRGBO(218, 165, 32, 1.0),
),
Icon(
Icons.monetization_on, size: 36.0,
color: const Color.fromRGBO(218, 165, 32, 1.0),
),
],
),
You can use a Stack with Positioned to achieve this:
class StackExample extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(),
body: new Container(
padding: const EdgeInsets.all(8.0),
height: 500.0,
width: 500.0,
// alignment: FractionalOffset.center,
child: new Stack(
//alignment:new Alignment(x, y)
children: <Widget>[
new Icon(Icons.monetization_on, size: 36.0, color: const Color.fromRGBO(218, 165, 32, 1.0)),
new Positioned(
left: 20.0,
child: new Icon(Icons.monetization_on, size: 36.0, color: const Color.fromRGBO(218, 165, 32, 1.0)),
),
new Positioned(
left:40.0,
child: new Icon(Icons.monetization_on, size: 36.0, color: const Color.fromRGBO(218, 165, 32, 1.0)),
)
],
),
),
)
;
}
}
And this how you get some nice shadow drop so the icon stands out more:
class StackExample extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(),
body: new Container(
padding: const EdgeInsets.all(8.0),
height: 500.0,
width: 500.0,
// alignment: FractionalOffset.center,
child: new Stack(
//alignment:new Alignment(x, y)
children: <Widget>[
new Container(
decoration: new BoxDecoration(
borderRadius: BorderRadius.circular(25.0),
boxShadow: [
new BoxShadow(
blurRadius: 5.0,
offset: const Offset(3.0, 0.0),
color: Colors.grey,
)
]
),
child: new Icon(Icons.monetization_on, size: 36.0, color: const Color.fromRGBO(218, 165, 32, 1.0))),
new Positioned(
left: 20.0,
child: new Container(
decoration: new BoxDecoration(
borderRadius: BorderRadius.circular(25.0),
boxShadow: [
new BoxShadow(
blurRadius: 5.0,
offset: const Offset(3.0, 0.0),
color: Colors.grey,
)
]
),
child: new Icon(Icons.monetization_on, size: 36.0, color: const Color.fromRGBO(218, 165, 32, 1.0))),
),
new Positioned(
left:40.0,
child: new Container(
decoration: new BoxDecoration(
borderRadius: BorderRadius.circular(25.0),
boxShadow: [
new BoxShadow(
blurRadius: 5.0,
offset: const Offset(3.0, 0.0),
color: Colors.grey,
)
]
)
,child: new Icon(Icons.monetization_on, size: 36.0, color: const Color.fromRGBO(218, 165, 32, 1.0))),
)
],
),
),
)
;
}
}
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 = ...;
RowSuper(
children: [widget1, widget2],
innerDistance: -20.0,
);
This will overlap row cells by 20 pixels.
The difference from this solution to the one using Stack is that Positioned widgets in a Stack don't occupy space. So you can't make the Stack the size of its contents, unless you know their sizes in advance. However, the RowSuper will have the size of all of its children widgets.
Note, there is also a ColumnSuper. Also note I am the author of this package.
I wanted something without dependencies and without hardcoded layout.
You could enhance by making overlap use a media query to overlap in terms of %.
Widget overlapped() {
final overlap = 10.0;
final items = [
CircleAvatar(child: Text('1'), backgroundColor: Colors.red),
CircleAvatar(child: Text('2'), backgroundColor: Colors.green),
CircleAvatar(child: Text('3'), backgroundColor: Colors.blue),
];
List<Widget> stackLayers = List<Widget>.generate(items.length, (index) {
return Padding(
padding: EdgeInsets.fromLTRB(index.toDouble() * overlap, 0, 0, 0),
child: items[index],
);
});
return Stack(children: stackLayers);
}
Here is my code on Profile Picture overlapped by camera image in flutter.
Output:
Click here to view output image
Container(
constraints: new BoxConstraints(
maxHeight: 200.0,
maxWidth: 200.0
),
padding: new EdgeInsets.only(left: 16.0, bottom: 8.0, right: 16.0),
decoration: new BoxDecoration(
shape: BoxShape.circle,
image: new DecorationImage(
image: new AssetImage('assets/images/profile.png'),
fit: BoxFit.cover,
),
),
child: Stack(
children: [
new Positioned(
right: 0.0,
bottom: 3.0,
child: Container(
constraints: new BoxConstraints(
maxHeight: 50.0,
maxWidth: 50.0
),
decoration: new BoxDecoration(
boxShadow: [
BoxShadow(
color:Color(0xFFdedede),
offset: Offset(2,2)
),
],
color: Colors.white,
shape: BoxShape.circle,
),
child: GestureDetector(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Icon(
Icons.photo_camera,
size: 34,
color: Color(0xFF00cde7),
),
),
),
),
),
],
),
)
Wraping your elements with OverflowBox and giving the maxWidth value will achieve this effect.
The following can be used in a row or a listview
return SizedBox(
width: 35, //--> list children will be 35 in width
child: OverflowBox(
maxWidth: 50, // --> allowing the child to overflow will cause overlap between elements
child: Container(
width: 50,
child: Text((index + 1).toString()),
),
),
);
You could try my package (signed_spacing_flex). It's exactly the same as a normal Row (or Column and Flex). But it also 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:
SignedSpacingRow(
spacing: -12.0,
stackingOrder: StackingOrder.lastOnTop,
children: <Widget>[
Icon(
Icons.monetization_on, size: 36.0,
color: const Color.fromRGBO(218, 165, 32, 1.0),
),
Icon(
Icons.monetization_on, size: 36.0,
color: const Color.fromRGBO(218, 165, 32, 1.0),
),
],
),
It also works with expanded children if you need.
Reverse variant based on #Lee Higgins
const size = 32.0;
const overlap = size - 6.0;
final containers = [
Container(
decoration: BoxDecoration(
color: Colors.grey[300],
shape: BoxShape.circle,
),
width: size,
height: size,
),
Container(
decoration: BoxDecoration(
color: Colors.grey[400],
shape: BoxShape.circle,
),
width: size,
height: size,
),
];
List<Widget> stackLayers = List<Widget>.generate(containers.length, (index) {
return Padding(
padding: EdgeInsets.fromLTRB(0, 0, index * overlap, 0),
child: containers[index],
);
});
return Stack(alignment: AlignmentDirectional.topEnd, children: stackLayers);
Stack is very much confusing.
The best solution is to use enter link description here