release_schedule/lib/view/swipe_transition.dart

99 lines
2.2 KiB
Dart

import 'package:flutter/material.dart';
/// A widget that transitions between two child widget by clipping them so that
/// the first one slides out of view and the second one slides into view.
class SwipeTransition extends StatelessWidget {
final Widget first;
final Widget second;
late final CurvedAnimation firstAnimation;
late final CurvedAnimation secondAnimation;
final Animation<double> animation;
SwipeTransition({
Key? key,
required this.first,
required this.second,
required this.animation,
}) : super(key: key) {
firstAnimation = CurvedAnimation(
parent: animation,
curve: Curves.easeOutSine,
);
secondAnimation = CurvedAnimation(
parent: animation,
curve: Curves.easeInSine,
);
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: animation,
builder: (context, child) {
return Stack(
children: [
ClipWithRect(
clipRect: Rect.fromLTRB(
0,
firstAnimation.value,
1,
1,
),
child: first,
),
ClipWithRect(
clipRect: Rect.fromLTRB(
0,
0,
1,
secondAnimation.value,
),
child: second,
),
],
);
},
);
}
}
class ClipWithRect extends StatelessWidget {
final Widget child;
final Rect clipRect;
const ClipWithRect({
Key? key,
required this.child,
required this.clipRect,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return ClipRect(
clipper: _RectClipper(clipRect),
child: child,
);
}
}
class _RectClipper extends CustomClipper<Rect> {
final Rect clipRect;
_RectClipper(this.clipRect);
@override
Rect getClip(Size size) {
return Rect.fromLTRB(
clipRect.left * size.width,
clipRect.top * size.height,
clipRect.right * size.width,
clipRect.bottom * size.height,
);
}
@override
bool shouldReclip(covariant CustomClipper<Rect> oldClipper) {
return true;
}
}