Flutter widget positioning - flutter

I wonder how to manage to do this kind of widgets.
I couldn't figure out how to describe and google it.
in this image how to positioned filter and sorting widgets floats on blue world image and background and aligned for perfect i mean responsive
or in this image expand arrow positioned on the edge of column

You can use MediaQuery to get the screen size and use Positioned inside the Stack to adjust the location of the buttons, here's an example i just made:
double screenHeight = MediaQuery.of(context).size.height;
double topContainerHeight = screenHeight / 3;
double buttonLocation = topContainerHeight - 40;
return Stack(
alignment: Alignment.topCenter,
children: [
Container(
color: Colors.red,
),
Container(
height: topContainerHeight,
decoration: const BoxDecoration(
color: Colors.black,
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(20.0),
bottomRight: Radius.circular(20.0),
),
),
),
Positioned(
top: buttonLocation,
child: Row(
children: [
Container(
height: 80,
width: 160,
color: Colors.white,
),
const SizedBox(width: 30.0),
Container(
height: 80,
width: 160,
color: Colors.white,
),
],
),
),
],
);
The black container in the top uses 1/3 of the screen height and i know my buttons have an height of 80 so i just remove half of the height of my buttons from 1/3 of the screen to position them in the stack.
Here's how it looks:

Related

In Flutter, I can't properly position in Stack

Stack(
children: [
Container(
height: MediaQuery.of(context).size.height * 0.5,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(100.0),
bottomRight: Radius.circular(100.0)),
color: darkBlue,
),
),
Positioned(
bottom: 0,
left: MediaQuery.of(context).size.width / 3,
child: CircleAvatar(
backgroundColor: white,
radius: 70,
child: Image.asset('assets/images/homepage.png'))),
],
)
When I set the value as bottom : 0 in the code, since the image is inside the Stack, it sees it as a border and moves the image to the bottom of the Stack. But what I want is to place the image in the center of the Container, as shown by the black circle in the image.
You need to pass negative half of height to bottom value to get that, don't forget to set Stack's clipBehavior to none. Try this:
Stack(
clipBehavior: Clip.none,// <-- add this
children: [
Container(
height: MediaQuery.of(context).size.height * 0.5,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(100.0),
bottomRight: Radius.circular(100.0)),
color: darkBlue,
),
),
Positioned(
bottom: -100/2,// <-- add this
left: MediaQuery.of(context).size.width / 3,
child: CircleAvatar(
backgroundColor: white,
radius: 70,
child: Image.asset('assets/images/homepage.png'))),
],
),
try this:
Stack(
alignment: Alignment.center
children: [
Container(
height: MediaQuery.of(context).size.height * 0.5,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(100.0),
bottomRight: Radius.circular(100.0)),
color: darkBlue,
),
),
CircleAvatar(
backgroundColor: white,
radius: 70,
child: Image.asset('assets/images/homepage.png'))
],
)
Placing bottom on half image will be bottom:-halfImageHeight, And the default clipBehavior of Stack is hardEdge which is needed to to set Clip.none
Stack(
clipBehavior: Clip.none,
children: [
/// background widgets
Position(
bottom: -70 // while radius is 70
left: MediaQuery.of(context).size.width / 2 - 70, // remove half width , maybe left:0 and right:0 will work as well
Placing center you can use Align widget
Align(
alignment: Alignment.center, //default
child: CircleAvatar(
)

Flutter half circle with multiple fill colors

I would like to create this in Flutter:
I know you can create a half circle like this.
But how I can get these multiple fill colors?
I know there is way to get this done with LinearGradient. (something like this)
But this might work, but I need to each color-section as a separated part/widget because I want to animate them in the next step.
How could I get this done?
You can do this using Custom Painter but then I understand it would be challenging to animate each color bar. I have been able to create something like you need
I used the ClipRRect widget to cut out the bottomLeft and bottomRight portions of a square -> SemiCircle.
Each Color bar is a Container and since you would like to animate each bar you can easily replace the Container with an AnimatedContainer and proceed from there. You might also need to make the widget stateful for animations.
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
// Assuming constraints here.
// Play with width and height values
const double widgetWidth = 100;
const double widgetHeight = 60;
// To get a semicircle
const double bottomRadius = widgetWidth / 2;
//Since we have 5 colors . Each color bars height is 60/5 = 12
const double colorBarHeight = widgetHeight / 5;
return ClipRRect(
borderRadius: const BorderRadius.only(
bottomLeft: Radius.circular(bottomRadius),
bottomRight: Radius.circular(bottomRadius)),
child: SizedBox(
width: widgetWidth,
height: widgetHeight,
child: Column(
children: [
Container(
width: widgetWidth,height: colorBarHeight,color: Colors.green),
Container(
width: widgetWidth,height: colorBarHeight,color: Colors.orange),
Container(
width: widgetWidth,height: colorBarHeight,color: Colors.yellow),
Container(
width: widgetWidth, height: colorBarHeight, color: Colors.red),
Container(
width: widgetWidth, height: colorBarHeight, color: Colors.blue),
])));
}
}
Please try this below code:
class SemiCircle extends StatelessWidget {
const SemiCircle({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Center(
child: ClipRRect(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(300),
bottomRight: Radius.circular(300),
),
child: Container(
alignment: Alignment.center,
height: 100,
width: 200,
child: Column(
children: [
Container(
height: 10,
color: Colors.red,
),
Container(
height: 10,
color: Colors.yellow,
),
Container(
height: 10,
color: Colors.green,
),
Container(
height: 10,
color: Colors.red,
),
Container(
height: 10,
color: Colors.yellow,
),
Container(
height: 10,
color: Colors.green,
),
Container(
height: 10,
color: Colors.red,
),
Container(
height: 10,
color: Colors.yellow,
),
Container(
height: 10,
color: Colors.green,
),
Container(
height: 10,
color: Colors.red,
),
],
),
),
),
),
],
),
);
}
}
You will get an output like below:

Matching Width of Positioned Container to Container in Stack

I'm having issues getting the positioned container to match the width of the first container. Essentially, I want the original container to be as wide as possible hence the width is set to double.infinity. The positioned container is meant to be an overlay to help with the visibility of the text that is stacked on top of the original container. However, the issue here is if I set the width of the overlay container to double.infinity I get an error saying BoxConstraints forces an infinite width. So right now I set the width to the size of the screen...but we can see that the border radius isn't drawn because it's too large.
How do I get the overlay container to match the original container containing the image?
Stack activityDetails(BuildContext context) {
var smallRadius;
return Stack(
children: <Widget>[
ClipRRect(
borderRadius: smallRadius,
child: Container(
width: double.infinity,
height: 200,
child: CachedNetworkImage(
imageUrl: image,
fit: BoxFit.cover,
),
),
),
Positioned(
top: 0,
left: 0,
child: Container(
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10.0),
topRight: Radius.circular(10.0),
bottomLeft: Radius.circular(0),
bottomRight: Radius.circular(0),
),
),
child: Text(
category.toUpperCase(),
),
),
),
],
);
}
If the sole goal is to only have the above display then I would suggest you replace the contents of your Positioned with this code and remove the entire ClipRRect chunk
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
image: const DecorationImage(
image:NetworkImage('src'),
fit:BoxFit.cover,
),
),
width: double.infinity,
height: 200,
child: Row(
crossAxisAlignment:CrossAxisAlignment.start,
children:const[
Text('Events'),
],
),
),
Remember to put it inside the Positioned() and edit the necessary parts like Cached and the Text() removing the const flag
However, if you still want to stick to this approach then I would suggest you try moving the Positioned top down by a few pixels

Set Container height equal to width in Flutter

I am learning Flutter development. I want to display some rounded square shaped containers with short text in a row. However, the possible shapes are either a circle or rectangle. So I decided to set the width and height of the rectangle so that they would be equal.
The following is the code I used to create the Container
Container(
width: double.maxFinite,
height:
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color: ThemeProvider.themeOf(context).data.primaryColor,
borderRadius: BorderRadius.circular(10),
),
child: Text(keyText),
),
When I set the shape in Box decoration alone, the Container resized to the size of the text. When I set the width property of the Container, I was able to divide the available width of the screen among the containers, which ensures flexibility of size if the screen was smaller or bigger, instead of hard coding it. Now I want to make the height the exact same size that the width turns out to be, thus obtaining a square container. Any idea how I could do that?
EDIT: I tried the following code and this is how the containers are looking like in both cases:
Container(
alignment: Alignment.center,
width: double.maxFinite,
height: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color: ThemeProvider.themeOf(context).data.primaryColor,
borderRadius: BorderRadius.circular(10),
),
Container(
alignment: Alignment.center,
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color: ThemeProvider.themeOf(context).data.primaryColor,
borderRadius: BorderRadius.circular(10),
),
After using MediaQuery.of(context).size.width for height property or both
Here is a solution without using MediaQuery:
AspectRatio(
aspectRatio: 1,
child: Container(
width: double.infinity,
child: Text(),
),
)
Use MediaQuery. MediaQuery.of(context).size.width gives you the Screen width size value.
Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color: ThemeProvider.themeOf(context).data.primaryColor,
borderRadius: BorderRadius.circular(10),
),
child: Text(keyText),
)
check this quick example that I made just for you!
// This function is just an example
List<Widget> buildContainers(BuildContext context, int containerCount) {
// Here you get the width of all your containers
final containerWidth = MediaQuery.of(context).size.width / containerCount;
// Make height = width for squares!
final containerHeight = containerWidth;
// We will gather all containers in this list
List containerList = <Container>[];
for (var i = 0; i < containerCount; i++) {
containerList.add(
Container(
// Use the predefined width and height here!
width: containerWidth,
height: containerHeight,
// Random color to differentiate each container
// You could replace this with your child widget
color: Color(
Random().nextInt(0xFFFFFFFF),
),
),
);
}
return containerList;
}
#override
Widget build(BuildContext context) {
return Container(
child: Row(
children: [
// If you are wondering what are these dots (...)
// they are called "spread operators" and you can find more about them here:
// https://dart.dev/guides/language/language-tour#spread-operator
...buildContainers(context, 7),
],
),
);
}
Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color: ThemeProvider.themeOf(context).data.primaryColor,
borderRadius: BorderRadius.circular(10),
),
child: Text(keyText),
),

Transformation distorts the border radius of container in flutter

Align(
alignment: Alignment.bottomCenter,
child: Container(
//padding: EdgeInsets.all(20.0),
height: 50,
width: 320,
decoration: BoxDecoration(
color: Colors.white,
shape: BoxShape.rectangle,
borderRadius: BorderRadius.all(Radius.circular(15.0))),
child: Stack(children: <Widget>[
Align(
alignment: Alignment.center,
child: Transform(
alignment: Alignment.topRight,
transform: Matrix4.diagonal3Values(4.0, 1.0, 1.0),
child: Container(
height: 45,
width: 45,
decoration: BoxDecoration(
//color: Color(0xffff8d27),
color: Colors.grey,
shape: BoxShape.rectangle,
borderRadius: BorderRadius.all(Radius.circular(10.0))
)),
),
),
Row(
children: <Widget>[
Expanded(
child: Center(
child: Text(
'Reservation',
style: TextStyle(fontWeight: FontWeight.bold),
),
),
),
Align(
alignment: Alignment.center,
child: Icon(Icons.attach_money)),
Expanded(
child: Center(
child: Text(
'Now',
style: TextStyle(fontWeight: FontWeight.bold),
),
),
)
],
)
])))
This is the current result
I have used a stack with the bottom layer being a container with grey color and 15.0 border radius aligned in the center, and the top layer containing text in two expandables and an icon in centre. I am trying to implement a two way slider button. I have not implemented the sliding part yet but that won't be an issue. When the user slides on a particular side the grey colored container in the bottom of stack streches on the respective side of the slide in turn depicting a selection. I am using the transform widget to scale the container in x dimension or simply speaking stretching it. The problem is that this transformation tends to distort the border radius of the container which is not producing the desired effect.
How can I stretch or transform the container so that it does not affect the border radius?
final _transformRight = Matrix4.identity()..translate(130.0);
final _transformLeft = Matrix4.identity(); //It means zero.
bool _shouldTransformRight = false;
#override
Widget build(BuildContext context) {
...
body: GestureDetector(
child: Container(
...
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(15.0),
),
child: Stack(
children: <Widget>[
AnimatedContainer(
...
duration: Duration(milliseconds: 200),
decoration: BoxDecoration(
color: Colors.grey,
//You can create a variable to unify the
//borderRadius for all containers.
borderRadius: BorderRadius.circular(15.0),
),
transform: _shouldTransformRight
? _transformRight
: _transformLeft,
),
Row(...),
],
),
),
onHorizontalDragEnd: (details) {
setState(() {
_shouldTransformRight = !_shouldTransformRight;
});
}
),
...
}
Summary of the edits that I've made to your code:
No need to provide a shape and a corner radius for the container at the same time. Using one of them alone is sufficient.
In the corner radius of the container I used BorderRadius.circular(...) instead of BorderRadius.all(...), because it's shorter.
I've replaced the first child of the Stack with AnimatedContainer and used it's transform argument to position it accordingly. The Matrix4.diagonal3Values(4.0, 1.0, 1.0) it was the cause for the distorted border radius.
Lastly, I wrapped the whole widget tree in a GestureDetector, so that I can get the user input, which based on it I'm gonna translate the AnimatedContainer. You can configure which callBack of GestureDetector to use, here I've used onHorizontalDragEnd.