Reputation: 373
I'm following the picture below but got some difficulties when I tried to make that white bubble.
I have tried a method using OverFlowBox
from another post Flutter mask a circle into a container but I got the circle stuck in the middle of the Container
and I don't know why alignment
won't help moving it. Here is what I've tried:
return Container(
alignment: Alignment.topCenter,
height: screenHeight/3.5,
width: screenWidth/3.5,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10),
topRight: Radius.circular(60),
bottomLeft: Radius.circular(10),
bottomRight: Radius.circular(10),
),
gradient: LinearGradient(
begin: FractionalOffset.topLeft,
end: FractionalOffset.bottomRight,
colors: [boxColorBegin, boxColorEnd]
),
),
child: ClipRect(
clipBehavior: Clip.hardEdge,
child: OverflowBox(
maxHeight: screenHeight/3.5 +20,
maxWidth: screenWidth/3.5 + 20,
child:Container(
decoration: BoxDecoration(
color: Colors.white,
shape: BoxShape.circle,
),
)
),
),
);
And the result was
Is there any ways to overflow something inside a widget so that it looks like clipped?
Thanks in advance!
Upvotes: 5
Views: 6898
Reputation: 373
I found the way to achieve what I want but am still confused why OverFlowBox
can't be aligned. I thought it is because the size of the OverFlowBox
is larger than its parent but it still don't work when I changed it to a smaller size.
I used Stack
and Positioned
widget and set the overflow
parameter of the Stack as overflow.clip
Here is the code:
return Container(
height: screenHeight/3.5,
width: screenWidth/3.2,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10),
topRight: Radius.circular(60),
bottomLeft: Radius.circular(10),
bottomRight: Radius.circular(10),
),
gradient: LinearGradient(
begin: FractionalOffset.topLeft,
end: FractionalOffset.bottomRight,
colors: [boxColorBegin, boxColorEnd]
),
),
child: Stack(
overflow: Overflow.clip,
alignment: Alignment.topCenter ,
children: <Widget>[
Positioned(
bottom: screenHeight / 8,
right: screenWidth / 12,
child: Container(
width: screenWidth / 3.5,
height: screenHeight / 3.5,
decoration: BoxDecoration(
color: Colors.white38,
shape: BoxShape.circle,
),
)
)
],
)
)
And the result is
EDIT
Turns out you can just use Container
as a clipper with the clipBehavior
parameter and use FractionalTranslation
widget as child to manipulate the position of the white circle. Thanks to pskink for the simple answer.
Here is the new code
return Container(
alignment: Alignment.topLeft,
clipBehavior: Clip.antiAlias,
height: screenHeight/3.5,
width: screenWidth/3.2,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10),
topRight: Radius.circular(60),
bottomLeft: Radius.circular(10),
bottomRight: Radius.circular(10),
),
gradient: LinearGradient(
begin: FractionalOffset.topLeft,
end: FractionalOffset.bottomRight,
colors: [boxColorBegin, boxColorEnd]
),
),
child: FractionalTranslation(
translation: Offset(-0.25, -0.5),
child: Container(
width: screenWidth / 3.5,
height: screenHeight / 3.5,
decoration: BoxDecoration(
color: Colors.white38,
shape: BoxShape.circle,
),
)
)
);
Upvotes: 5
Reputation: 876
You can easily accomplish this using ClipRRect as your root container for this widget. Provide it a border radius and it will clip all children and prevent them from painting outside the bounds. You can then use Transform.translate to render a circle and offset it outside its parent.
I created a sample pen for you to try
return ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(8),
bottomLeft: Radius.circular(8),
bottomRight: Radius.circular(8),
topRight: Radius.circular(125),
),
child: Container(
height: 400,
width: 250,
decoration: BoxDecoration(
color: Colors.red,
),
child: Stack(
children: [
Align(
alignment: Alignment.topLeft,
child: Transform.translate(
offset: Offset(-40, -100),
child: Container(
height: 220,
width: 220,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(110)),
color: Colors.white.withOpacity(0.4),
),
),
),
),
],
),
),
);
For more information on ClipRRect and Transform.translate visit the API docs.
Upvotes: 1
Reputation: 3822
you can use padding to move the OverflowBox
. you also need to clip the parent Container
with ClipRRect
here is your fix (tested and works):
return ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10),
topRight: Radius.circular(60),
bottomLeft: Radius.circular(10),
bottomRight: Radius.circular(10),
),
child: Container(
alignment: Alignment.topCenter,
height: screenHeight / 3.5,
width: screenWidth / 3.5,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10),
topRight: Radius.circular(60),
bottomLeft: Radius.circular(10),
bottomRight: Radius.circular(10),
),
gradient: LinearGradient(
begin: FractionalOffset.topLeft, end: FractionalOffset.bottomRight, colors: [boxColorBegin, boxColorEnd]),
),
child: ClipRect(
clipBehavior: Clip.hardEdge,
child: Padding(
padding: const EdgeInsets.only(right: 130, bottom: 150),
child: OverflowBox(
maxHeight: screenHeight / 3.5 + 20,
maxWidth: screenWidth / 3.5 + 20,
child: Container(
decoration: BoxDecoration(
color: Colors.white.withAlpha(80),
shape: BoxShape.circle,
),
)),
),
),
),
);
Upvotes: 0