I'm trying to add the "Protection Icon" on top of the "Box Shape" border and make sure that when it moves, it's within Its borderlines on each screen size:
Code:
return Scaffold(
body: Container(
decoration: BoxDecoration(
color: const Color(0xff182341),
),
child: Stack(
children: [
Container(
decoration: BoxDecoration(
border: Border.all(color: const Color(0xff5F687E)),
shape: BoxShape.circle,
),
),
Stack( // Using stack here because of other elements that will be added.
children: [
AnimatedPositioned(
top: 280,
left: 130,
duration: Duration(milliseconds: 500),
child: Container(
child: Image(image: AssetImage('images/g8.png')),
),
),
]
),
]),
),
);
Result:
However, I only got the iPhone 13 Pro's screen right, the other's aren't where they should be
Don't use Positioned to specify an absolute offset, instead try to use widgets that allow you to set a relative offset (like a percentage), so they will scale well with different screen sizes.
For example, you can replace your Positioned for Align, like this:
Align(
alignment: Alignment(-0.75, 0.48), // play around with these values
child: ...
)
The two arguments for Alignment class are used to set a percentage offset on x and y axis, each ranging from -1.0 to +1.0, with 0.0 being the center.
Related
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:
I use stack to place images, my back image is drawn on top of the other one, how can i fix the posterpath to be on top, also top image doesn't round the edges:
return Stack(
children: [
Positioned(
child: AspectRatio(
aspectRatio: 390 / 220,
child: ColorFiltered(
colorFilter: ColorFilter.mode(
Colors.black.withOpacity(0.3),
BlendMode.dstATop,
),
child: backdropPath != null
? Image.network(ImageDownloader.imageUrl(backdropPath))
: Image.asset(AppImages.noImageBig),
),
),
),
Positioned(
child: Center(
child: Padding(
padding: const EdgeInsets.only(top: 110.0),
child: Container(
clipBehavior: Clip.antiAlias,
decoration: const BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(12)),
),
height: 212.0,
width: 174.0,
child: posterPath != null
? Image.network(ImageDownloader.imageUrl(posterPath))
: Image.asset(AppImages.noImageBig),
),
),
),
),
The ordering of children in a Stack is determined by their order in the source code - later items in the list are drawn on top. If you want to switch the z-order of the two children, swap them in the source code.
For your second question, you can achieve "rounded corner" with ClipRRect widget.
I have two icons in a stack. I want one to hide the other, but instead it's semi-transparent and the other is shown behind it.
This is the code:
Stack(
children: [
Container(child: Icon(Icons.account_circle_rounded), padding: EdgeInsets.only(left: 10),),
Container(child: Icon(Icons.account_circle_rounded), padding: EdgeInsets.only(left: 20),),
],
)
This is how it looks:
Icons are more like SVG, use vector to draw shape. There are some empty spaces inside the icon to draw the path, and we can see the background though this. Also, it contains padding around it, You can use your assets to draw the UI.
We can wrap with another ColoredBox to hide the background icon, but it will get extra padding from IconData.
This snippet shows basic level structure.
SizedBox(
height: 24,
width: 24 * 1.7,
child: Stack(
alignment: Alignment.center,
children: [
Align(
alignment: Alignment.centerLeft,
child: Container(
child: const Icon(
Icons.account_circle_rounded,
),
decoration: const BoxDecoration(
color: Colors.white,
shape: BoxShape.circle,
),
),
),
Align(
alignment: Alignment.centerRight,
child: Container(
child: const Icon(
Icons.account_circle_sharp,
),
decoration: const BoxDecoration(
color: Colors.white,
shape: BoxShape.circle,
),
),
),
],
),
),
Widget renders bottom to top.
The Center widget centers a widget horizontally and vertically in the center of a Stack. How can one center a widget ONLY horizontally or vertically?
Centering a widget in a Stack is possible with a Row or Column widget. Can it be done without using those widgets?
Conditions:
Cannot use Row / Column.
The size of the Stack is not known before layout (cannot use hardcoded Positioned values).
Center widget:
Container(
decoration:
BoxDecoration(border: Border.all(color: Colors.black87, width: 10)),
child: Stack(
children: [
Center(
child: Container(color: Colors.amber, width: 50, height: 50),
),
],
),
);
Center horizontally w/Row:
Row(mainAxisAlignment: MainAxisAlignment.center)
Center vertically w/Column:
Column(mainAxisAlignment: MainAxisAlignment.center)
The alignment above is the desired result. Can those results be achieved with other Flutter widgets?
Use Align Widget
Align(
alignment: Alignment.topCenter, // This will horizontally center from the top
child: Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.black87, width: 10)),
child: Stack(
children: [
Container(color: Colors.amber, width: 50, height: 50),
],
),
),
)
1. For Top Center use alignment: Alignment.topCenter
2. For Center Left use alignment: Alignment.centerLeft
3. For Center right use alignment: Alignment.centerRight
3. For Bottom center use alignment: Alignment.bottomCenter
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.