Align widgets round a circle - flutter

I want to align a list of widgets round a circle, so the whole thing could appear circluar like this image
is there any widgets i can use, or a list of widgets that are could go and read up on, that can help me to achieve something like this?.

Using Aling widget is simpler than Positioned widget. On Positioned widget it was having extra size beyond text, and it might be handled by providing height and weight.
class CCSh extends StatelessWidget {
final double size;
const CCSh({Key? key, required this.size}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
alignment: Alignment.center,
width: size,
height: size,
decoration: BoxDecoration(
color: Colors.green,
shape: BoxShape.circle,
border: Border.all(color: Colors.red, width: 4)),
child: Stack(
children: [
Align(
alignment: Alignment(1, 0),
child: Text("D"),
),
Align(
alignment: Alignment(0, -1),
child: Text("W"),
),
Align(
alignment: Alignment(-1, 0),
child: Text("O"),
),
Align(
alignment: Alignment(0, 1),
child: Text("R"),
),
],
),
);
}
}
It is having Container size, you need to calculate if the widget gets beyond radius.
More about Align

Related

Align child widgets to a positioned child widget

I need to position a child widget (w1) at a relative position to its parent (in the example see the white box at 30%), and to position two other child widgets (w2, w3) to the right and left.
The positioned child (w1) is the anchor and should remain in 30%, regardless of w2 and w3 width, while the other child widgets should positioned accordingly.
Here's what I'm trying to achieve:
I tried to use Stack widget as the parent
The problem is I can't place the position child at 30%, as it only excepts const values
I also tried to placed them in Container with FractionalOffset - it works for single children, but I can't add another children to this Container.
Container(
height: 50,
color: Colors.blue[200],
alignment: const FractionalOffset(0.3, 0),
child: Text("50",style: const TextStyle(fontSize: 16, color: Colors.black))),
You can use CompositedTransformTarget widget.
class TestF133 extends StatelessWidget {
const TestF133({super.key});
#override
Widget build(BuildContext context) {
final LayerLink link = LayerLink();
return Scaffold(
backgroundColor: Colors.deepPurple,
body: Stack(
children: [
Align(
alignment: Alignment(.3, 0),
child: CompositedTransformTarget(
link: link,
child: Container(
height: 50,
width: 50, // you can handle theses
color: Colors.white,
),
),
),
CompositedTransformFollower(
link: link,
followerAnchor: Alignment.centerLeft,
targetAnchor: Alignment.centerRight,
child: Text("dynamic right Text"),
),
CompositedTransformFollower(
link: link,
followerAnchor: Alignment.centerRight,
targetAnchor: Alignment.centerLeft,
child: Text("dynamic left Text"),
)
],
),
);
}
}
I hope I got your question right. So, a quick solution would be:
class MyBar extends StatelessWidget {
const MyBar({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
double width = MediaQuery.of(context).size.width;
return Container(
color: Colors.blue,
child: Row(
children: [
SizedBox(
width: width * 3 / 10,
child: const Align(
alignment: Alignment.centerRight,
child: Text('left'),
),
),
Container(
height: 50,
color: Colors.lime.shade100,
margin: const EdgeInsets.symmetric(horizontal: 10),
child: const Text("50",
style: TextStyle(fontSize: 16, color: Colors.black)),
),
const Expanded(child: Text('right')),
],
),
);
}
}
For more accurate result, I think you can find the width of the handler and subtract the half of it from the width of the SizedBox (or something like that).
You can also use Stack with position with this approach.

Absolute positioning of text on a container - flutter

I want to absolutely position a text on a container.
return Container(
height: 150,
width: 150,
decoration: BoxDecoration(
color: Color(0xE5E5EAee), borderRadius: BorderRadius.circular(20)),
child: Text('Camping'),
);
This is the present image
This is what need to be acheived
Did tried to position it with the 'align positioned' dependency. But got stuck with the same result.
using your own example considering there is only one child in the container u can do the following but if u do have additional childrens the best way would be to use a Stack widget and use Align/Positioned widget to position the child widgets as per ur needs
Container(
height: 150,
width: 150,
padding: EdgeInsets.only(bottom: 10), // how much space from the bottom
alignment: Alignment.bottomCenter,
decoration: BoxDecoration(
color: Color(0xE5E5EAee),
borderRadius: BorderRadius.circular(20)),
child: Text('Camping'),
)
You can try this, use a Stack and positioned the Text with the widget Positioned as you need it, Positioned has 4 properties for position top, rigth, bottom and left for you to positioned the widget wherever you want.
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
height: 150,
width: 150,
decoration: BoxDecoration(
color: Color(0xE5E5EAee), borderRadius: BorderRadius.circular(20)),
child: Stack(
children: [
Positioned(
top: 120,
left: 48,
child: Text('Camping'))
,
],
),
);
;
}
}
Wrap the Text widget with Align widget and give alignment as the below code
Container(
height: 150,
width: 150,
decoration: BoxDecoration(
color: Color(0xE5E5EAee), borderRadius:
BorderRadius.circular(20)),
child: Align(
alignment: Alignment.bottomCenter, // ADD THIS
child: Text('Camping')),
),
Then give padding as per your need

Rounded corners Image inside PageView keeping ratio Flutter

I have a PageView with images list inside. I want to keep the image ratio and set a rounded corners to them.
Usually I had no problem to clip image inside simple list or single image.
But in this case, the ClipRRect is not wrapping the image and when I'm setting size to red Container nothing happened.
Result :
Code :
double maxiHeight = 250;
List<Widget> postList = [];
#override
void initState() {
for(Post p in Model.instance.postList) {
postList.add(post(p));
}
super.initState();
}
#override
Widget build(BuildContext context) {
return Container(
height: maxiHeight,
child: PageView(
controller: PageController(viewportFraction: 0.5),
children: postList
),
);
}
Widget post(Post post) {
return ClipRRect(
borderRadius: BorderRadius.circular(20),
child: Container(
margin: EdgeInsets.only(right: 10),
color: Colors.red,
child: Image.network(post.thumb, height: 50)
)
);
}
I want to keep my image ratio.
What am I missing here ?
About your code snippet, you are providing margin right 1st then wrapping with ClipRRect. Here the main Container is getting its size and then using margin, after wrapping with ClipRRect it is avoiding 10px from right to Clip. And this is how we are getting current output.
But we want padding outside The Container and without border radius. Means after decorating the image, just provide some padding. You can follow this and using fit: BoxFit.cover will cover the widget size.
Center(
child: Padding(
padding: EdgeInsets.only(right: 10),
child: ClipRRect(
borderRadius: BorderRadius.circular(20),
child: Container(
// margin: EdgeInsets.only(right: 10),// not here
color: Colors.red,
child: Image.network(
// post.thumb,
"https://unsplash.it/1440/3040?random",
// fit: BoxFit.fitHeight,
height: 150,
),
),
),
),
),
With the following modified code it should work:
#override
Widget build(BuildContext context) {
return Center(
child: SizedBox(
height: 500.0,
child: ListView(scrollDirection: Axis.horizontal, children: postList),
),
);
}
Widget post(String uri) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 5.0),
child: ClipRRect(
borderRadius: BorderRadius.circular(20),
child: Image.network(uri, fit: BoxFit.fitHeight)
),
);
}
Try to add BoxFit.cover to Image.network widget
Widget post(Post post) {
return ClipRRect(
borderRadius: BorderRadius.circular(20),
child: Container(
margin: EdgeInsets.only(right: 10),
color: Colors.red,
child: Image.network(post.thumb, height: 50, fit: BoxFit.cover,),
)
);
}

Asking how to achieve the design problem in flutter

Hello Guys I would like to ask is it possible to achieve this kind of design using code? I really got stuck, here is design I would like to achieve
but the real problem is I only achieve this
this is my sample code:
in my main:
return Scaffold(
backgroundColor: Color(0xff012a60),
body: Stack(children: <Widget>[
/*_AnimatedCircle(
outerController: outerController,
innerController: innerController,
),*/
_OuterCircle(circleColor: Colors.blueGrey[900].withOpacity(.8)),
Column(children: <Widget>[
const Spacer(flex: 50),
Expanded(flex: 30, child: Container(color: Colors.white)),
const Spacer(flex: 20),
]),
Row(children: <Widget>[
const Spacer(flex: 80),
Transform.scale(
scale: 2.5,
child: Container(
width: MediaQuery.of(context).size.width * 0.2,
decoration: const BoxDecoration(
color: Colors.red, shape: BoxShape.circle)),
),
]),
// _OuterCircle(circleColor: Colors.blueAccent.withOpacity(.25)),
Row(children: <Widget>[
const Spacer(flex: 80),
Column(children: [
Spacer(flex: 60),
Transform.scale(
scale: 2.5,
child: Container(
width: MediaQuery.of(context).size.width * 0.2,
height: MediaQuery.of(context).size.width * 0.05,
decoration: const BoxDecoration(color: Colors.green)),
),
Spacer(flex: 24),
]),
]),
]),
);
and this is my other class
class _OuterCircle extends StatelessWidget {
const _OuterCircle({Key key, this.circleColor}) : super(key: key);
final Color circleColor;
#override
Widget build(BuildContext context) {
return Transform.scale(
scale: 2,
child: Container(
width: MediaQuery.of(context).size.width * 0.47,
decoration: BoxDecoration(shape: BoxShape.circle, color: circleColor),
));
}
}
Please help I really stuck how to achieve this kind of design in dart code
I think it is easier to break down the geometry problem from the largest area to small area.
The key point of achieve this is using Clip (ClipOval, ClipRect...)
The upper part can be draw by using right circle to clip left circle
The lower part can be draw by using right circle to clip inner rectangle
Scale the stack area
Draw large left circle (area 1)
Draw middle white rectangle (area 2)
Draw right circle with rectangle inside (area 3)
Draw the middle intersection part (area 4)
Widgets in used: ClipOval, FractionallySizedBox, AspectRatio,
The left Big Circle
class BigCircle extends StatelessWidget {
const BigCircle({this.color,Key key}):super(key: key);
final Color color;
#override
Widget build(BuildContext context) {
return AspectRatio(
aspectRatio: 1,
child: Container(
decoration: BoxDecoration(
color: color,
shape: BoxShape.circle,
),
),
);
}
}
The custom oval clipper (clip right white circle area)
class CustomClipOval extends CustomClipper<Rect> {
#override
Rect getClip(Size size) {
final width = size.width * 0.42;
return Rect.fromLTRB(
size.width - width,
(size.height - width) * 0.5,
size.width,
(size.height + width) * 0.5,
);
}
#override
bool shouldReclip(covariant CustomClipper<Rect> oldClipper) {
return false;
}
}
Finally the stack
return Scaffold(
backgroundColor: const Color(0xff004471),
body: Transform.scale(
scale: 1.19,
child: Stack(children: <Widget>[
// Area 1
const Align(
alignment: Alignment.centerLeft,
child: BigCircle(
color: Color(0xff022c66),
),
),
// Area 2
Align(
alignment: const Alignment(0, 0.4),
child: FractionallySizedBox(
heightFactor: 0.23,
child: Container(
color: Colors.white,
),
),
),
// Area 3
ClipOval(
clipper: CustomClipOval(),
child: Container(
alignment: const Alignment(0, 0.46),
color: Colors.white,
child: FractionallySizedBox(
heightFactor: 0.14,
child: Container(
color: const Color(0xff335f86),
),
),
),
),
// Area 4
ClipOval(
clipper: CustomClipOval(),
child: const Align(
alignment: Alignment.centerLeft,
child: BigCircle(color: Color(0xff647294),),
),
),
]),
),
);

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.