How to align elements inside a stack in flutter? - flutter

I have an image slider. On top of the image slider three dots should be displayed the change the image. The dots should be centered at the bottom of the image. Additionaly I need a button also as an overlay. The button should be displayed on the right side vertically centered.
I use a stack but I'm not able to align the control elements.
Stack(children: [
CarouselSlider(
items: children,
options: CarouselOptions(
autoPlay: false,
viewportFraction: 1.0,
aspectRatio: 2.0,
enableInfiniteScroll: false,
onPageChanged: (newIndex, reason) {
setState(() {
currentImage = newIndex;
});
}),
),
// This row should be at the bottom of the image slider
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.end,
children: children.map((url) {
index++;
return Container(
width: 8.0,
height: 8.0,
margin: EdgeInsets.symmetric(vertical: 10.0, horizontal: 2.0),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: currentImage == index - 1
? Color.fromRGBO(255, 255, 255, 0.9)
: Color.fromRGBO(255, 255, 255, 0.4),
),
);
}).toList(),
),
// This row should be centered on the right
Align(alignment: Alignment.centerRight,child: PhotoButtons(eventId: widget.event.id, preview: true))
]),

You can align the children widgets in a Stack by using the alignment property.
Stack(
alignment: Alignment.bottomCenter,
children: [
// Your widgets
],
),
This will align all the children at the bottom center, but we don't want that, right?
So, we will use another widget know as Positioned widget. We can specify the exact position of our widget from the top, left, right or bottom. By using MediaQuery, you can easily display it in the center-right position.
Stack(
alignment: Alignment.bottomCenter,
children: [
// Your widgets
Positioned(
top: MediaQuery.of(context).size.height * 0.45,
right: 0, // the position from the right
),
],
),
Please note that Positioned widget can be used only in a Stack widget.

Use Positioned widget instead of Align, take a look this example

Add the align widget in the stack and then change its alignment to wherever you want the widget to show in that stack space
Stack(
children: [
Align(
alignment: Alignment.bottomCenter,
child: Row(
mainAxisAlignment:
MainAxisAlignment.center,
children: <Widget>[
for (var i = 0;i < localImages.length;i++)
Text('.',style: TextStyle(fontSize: 60,color:Colors.grey),)
],
))
])

Related

How to achieve this card UI image flutter

How do I place the image in this way in a card
You can use Stack widget. You can determine the position of the image with Positioned Widget.
For Example :
Stack(
children: <Widget>[
Card()
Positioned(
top: 0,
bottom 10,
// vs...
child :Image(),
)
],
),
You can do this way:
Container(
decoration: BoxDecoration(
// insert all decorations here (color, shape)...
),
child: Row(
children: [
Container(
child: Image()
transform: Matrix4.translationValues(0.0, -50.0, 0.0),
),
Container (
// insert here the other things that are in that card
),
]
),
);

How can I achieve the following layout in flutter?

The thing I want to reach is something like this:
These are the main constraints I want to reach:
"text"-s being centered above the lower "button"-s and "thing2" being able to go in between "texts"-s when the screen is short enough.
I want the "button"-s to always be the same height/width (this is easily done by something like SizedBox) and the same distance from the top/bottom .
I want the "thing1" to be x height at max and scale with screen downwards if needed (either by making its texts smaller or making it scrollable, I haven't yet decided, this isn't the main problem).
I want "thing2" to always scale with screen.
When the screen is big enough, I want "thing1" and "thing2" to share the space between them evenly, and each being in the center of its own space.
Right now my layout is the following:
Column: MainAxisAlignment.SpaceBetween, height fixed
Container: height fixed
Row: MainAxisAlignment.SpaceBetween
Button
Button
Container: height fixed
thing1
Container: height calculated based on screen height and other Containers' height
thing2
Container: height fixed
Row: MainAxisAlignment.SpaceBetween
Button
Button
This is of course not all, I tried to include all relevant information about my layout without giving too much information pointlessly.
How would one go about adding the "text"-s above the "button"-s? (I tried Stack, but then I dont't know how to make them appear above the "button"-s while at the same time making "thing2" be above them too.
I managed achieve the things with this code (where MyBox is a simple widget with a colored container with width and height):
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
const double buttonHeight = 35;
const double buttonWidth = 100;
const double textHeight = 40;
const double textWidth = 30;
return Padding(
padding: const EdgeInsets.all(8.0),
child: Stack(
children: [
Align(
alignment: Alignment.topLeft,
child: SizedBox(
width: buttonWidth,
height: buttonHeight,
child: MyBox(Colors.red),
),
),
Align(
alignment: Alignment.topRight,
child: SizedBox(
width: buttonWidth,
height: buttonHeight,
child: MyBox(Colors.yellow),
),
),
Align(
alignment: Alignment.bottomLeft,
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: SizedBox(
width: textWidth,
height: textHeight,
child: MyBox(Colors.green),
),
),
SizedBox(
width: buttonWidth,
height: buttonHeight,
child: MyBox(Colors.cyan),
),
],
),
),
Align(
alignment: Alignment.bottomRight,
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: SizedBox(
width: textWidth,
height: textHeight,
child: MyBox(Colors.indigo),
),
),
SizedBox(
width: buttonWidth,
height: buttonHeight,
child: MyBox(Colors.blue),
),
],
),
),
Align(
alignment: Alignment.bottomCenter,
child: SizedBox(
width: buttonWidth,
height: buttonHeight,
child: MyBox(Colors.orange),
),
),
Positioned(
left: 0,
top: 0,
right: 0,
bottom: buttonHeight,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Flexible(
fit: FlexFit.loose,
child: MyBox(Colors.purple),
),
Flexible(
fit: FlexFit.loose,
child: MyBox(Colors.brown),
),
],
),
),
],
),
);
}
}
TLDR: I used a Stack widget to hold my other widgets, and Align widget to align (duh) my widgets in the Stack.
I used a Column to center my texts above my lower buttons. "mainAxisAlignment: MainAxisAlignment.end" was important so this column is at the bottom and not at the topside.
Finally I wrapped the Stack in a Padding.

How do I get one element of Stack to appear outside another element?

Here's the issue visually explained I am trying to use Stack widget to stack a text widget over a circle avatar placed on the center.
The text widget seems to get clipped when I try to use Positioned widget to place it to the bottom&right outside of the circle Avatar.
Stack(
children: <Widget>[
// circle avatar has to be on the center
CircleAvatar(
radius: 40, //making the border of circleAvatar appear amber colored
backgroundColor: Colors.amber[900],
child: CircleAvatar(
// backgroundImage:
// AssetImage('assets/images/img1.png'),
radius: 38,
),
),
// this has to be on the right near the circle avatar on the same row
Positioned(
bottom: 0,
right: 0,
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text('Dummytext1'),
SizedBox(
height: 5,
width: 5,
),
Text('dummytext2')
],
),
),
]),
Add clipBehaviour to the Stack
Stack(
clipBehaviour: Clip.none,
children: <Widget>[
]
),
This will force it to not clip any overflowing content

Hide overflow flutter, without overflowed message

I have an animation that I want to be partially visible.
Basically the end of the screen should cut the animation in half. So the animation is overflowing but that's intended. How do I remove the overflowed message then ?
return ClipRect(
child: Container(
width: MediaQuery.of(context).size.width - 32,
child: Padding(
padding: const EdgeInsets.fromLTRB(spacingM, spacingM, 0, spacingM),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
TextInfo(
location: location, dateFormatter: dateFormatter, date: date),
Transform.translate(
offset: Offset(30, 0),
child: WeatherAnimation(),
),
],
),
),
),
);
Try using wrapping what is overflowing with a FittedBox. This will clip out what is overflowing.
In this scenario, I believe you should wrap the Padding widget or perhaps the Row widget with FittedBox which would allow the FittedBox to take shape of its parent and clip the children to fit.
Instead of ClipRect, you can use Stack with fit as StackFit.expand.
return Stack(
fit: StackFit.expand,
children: [
Container(
width: MediaQuery.of(context).size.width - 32,
child: Padding(
padding: const EdgeInsets.fromLTRB(spacingM, spacingM, 0, spacingM),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
TextInfo(
location: location, dateFormatter: dateFormatter, date: date),
Transform.translate(
offset: Offset(30, 0),
child: WeatherAnimation(),
),
],
),
),
),
]
);
let me know, if this work.

Flutter Row widget solve RenderFlex overflow by cutting off remaining area

There are a lot of questions here already about Renderflex overflow, but I believe my use case might be a bit different.
Just the usual problem - having a Widget that is too big in a Row widget, and I get the A RenderFlex overflowed by X pixels ... error.
I want to create a Row that cuts off it's overflowing child Widget if they would be rendered outside it's area without getting an error.
First off, wrapping the last element in the Row widget with Expanded or Flexible does not work in my case, as recommended here and here and many other places. Please see code and image:
class PlayArea extends StatelessWidget {
#override
Widget build(BuildContext context) {
final dummyChild = Container(
color: Colors.black12,
width: 100,
child: Text('important text'),
);
final fadeContainer = Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: [
Colors.black26,
Colors.black87,
],
),
),
width: 600,
);
return Padding(
padding: const EdgeInsets.all(20.0),
child: Container(
color: Colors.redAccent,
child: Column(children: [
Expanded(
child: Row(
children: <Widget>[
dummyChild,
fadeContainer,
],
),
),
Expanded(
child: Row(
children: <Widget>[
dummyChild,
Expanded(
child: fadeContainer,
),
],
),
),
Expanded(
child: Row(
children: <Widget>[
Container(
color: Colors.black12,
width: 1100,
child: Text('important text'),
),
Expanded(
child: fadeContainer,
),
],
),
),
]),
),
);
}
}
Key points:
Using Expanded changes the width of Container, which changes the gradient's slope. I want to keep the gradient as it is
Even with Expanded widget, the Row is not prepared for the case when important text's area is too wide and does not fit the screen horizontally - it will get an overflow error for that Widget
it is technically working in the first case, because no red color is drawn on the right side on the green field, it 'just' has an error
How do I cut off the remaining space dynamically without any error - regardless of any screen size and content?
One solution I found is that
Row(
children: <Widget>[
dummyChild,
fadeContainer,
],
)
can be converted to
ListView(
scrollDirection: Axis.horizontal,
physics: const NeverScrollableScrollPhysics(),
children: <Widget>[
dummyChild,
fadeContainer,
],
)
Creating a horizontal list and preventing scroll on that.
edit.: just found out it that you'll get unbounded vertical height, so it's not the same.