Reputation: 4701
I am trying to do a Page transition using a circle in the center of the first view that expands revealing second view.
In alternative, it's the same if I use a widget with a transparent hole in the center (and we can see the bottom widget through the hole), and with an animation that expands the hole revealing the widget in the bottom.
The only answer I found similar to what I'm trying to do is this:
How to create widget with transparent hole in flutter
but I am not able to use a widget instead of the circle ping the center of the screen.
Upvotes: 0
Views: 534
Reputation: 24720
use HoleMaterialPageRoute
instead of MaterialPageRoute
- note that you can completely remove transitionDuration
if the default duration is ok with you, also you can remove late final curve = CurvedAnimation(
and use animation.value
instead of curve.value
but in my opinion non linear radius growth looks better :-)
class HoleMaterialPageRoute extends MaterialPageRoute {
HoleMaterialPageRoute({required super.builder});
// the default transitionDuration is Duration(milliseconds: 300) so you can make
// it longer to see the better effect:
@override
Duration get transitionDuration => const Duration(milliseconds: 800);
@override
Widget buildTransitions(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
return ClipPath(
clipper: _HoleClipper(animation),
child: child,
);
}
}
class _HoleClipper extends CustomClipper<Path> {
_HoleClipper(this.animation);
final Animation<double> animation;
late final curve = CurvedAnimation(
parent: animation,
curve: Curves.easeOut,
reverseCurve: Curves.easeIn,
);
@override
Path getClip(Size size) {
final center = size.center(Offset.zero);
final radius = lerpDouble(0, center.distance, curve.value)!;
// print('size: $size, radius: $radius');
final oval = Rect.fromCircle(center: center, radius: radius);
return Path()
..addOval(oval);
}
@override
bool shouldReclip(covariant CustomClipper<Path> oldClipper) => true;
}
EDIT
in some cases a better solution is to use ThemeData.pageTransitionsTheme
so that you can use Navigator.pushNamed
or Navigator.push
with "normal" MaterialPageRoute
(you dont have to change your Navigator
related code)
to do so you have to create a custom PageTransitionsBuilder
:
class HolePageTransitionsBuilder extends PageTransitionsBuilder {
@override
Widget buildTransitions<T>(PageRoute<T> route, BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
return ClipPath(
clipper: _HoleClipper(animation),
child: child,
);
}
}
and use it like that (this is a case for linux platform where i tested my code):
MaterialApp(
theme: ThemeData.light(useMaterial3: false).copyWith(
pageTransitionsTheme: PageTransitionsTheme(
builders: {
TargetPlatform.linux: HolePageTransitionsBuilder(),
}
)
),
...
)
Upvotes: 1