Created
June 6, 2025 12:25
-
-
Save sajithlaldev/4e3f0919f47cc8ba4e594ce39585cf00 to your computer and use it in GitHub Desktop.
Smooth Transition animation in Flutter using flutter_physics
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/material.dart'; | |
import 'package:flutter_physics/flutter_physics.dart'; | |
class AnimationsControllerAdapter implements AnimationController { | |
AnimationsControllerAdapter(this.physicsController); | |
final PhysicsController physicsController; | |
@override | |
Duration? get duration => physicsController.duration; | |
@override | |
set duration(Duration? value) { | |
physicsController.duration = value; | |
} | |
@override | |
Duration? get reverseDuration => physicsController.reverseDuration; | |
@override | |
set reverseDuration(Duration? value) { | |
physicsController.reverseDuration = value; | |
} | |
@override | |
double get value => physicsController.value; | |
@override | |
set value(double value) { | |
physicsController.value = value; | |
} | |
@override | |
void addListener(VoidCallback listener) { | |
physicsController.addListener(listener); | |
} | |
@override | |
void addStatusListener(AnimationStatusListener listener) { | |
physicsController.addStatusListener(listener); | |
} | |
@override | |
TickerFuture animateBack( | |
double target, { | |
Duration? duration, | |
Curve curve = Curves.linear, | |
}) { | |
return physicsController.animateTo( | |
target, | |
duration: duration, | |
physics: curve, | |
); | |
} | |
@override | |
TickerFuture animateTo( | |
double target, { | |
Duration? duration, | |
Curve curve = Curves.linear, | |
}) { | |
return physicsController.animateTo( | |
target, | |
duration: duration, | |
physics: curve, | |
); | |
} | |
@override | |
TickerFuture animateWith(Simulation simulation) { | |
return physicsController.animateWith(simulation); | |
} | |
@override | |
AnimationBehavior get animationBehavior => | |
physicsController.animationBehavior; | |
@override | |
void clearListeners() { | |
physicsController.clearListeners(); | |
} | |
@override | |
void clearStatusListeners() { | |
physicsController.clearStatusListeners(); | |
} | |
@override | |
String? get debugLabel => physicsController.debugLabel; | |
@override | |
void didRegisterListener() { | |
// TODO: implement didRegisterListener | |
} | |
@override | |
void didUnregisterListener() { | |
physicsController.didUnregisterListener(); | |
} | |
@override | |
void dispose() { | |
physicsController.dispose(); | |
} | |
@override | |
Animation<U> drive<U>(Animatable<U> child) { | |
return physicsController.drive(child); | |
} | |
@override | |
TickerFuture fling({ | |
double velocity = 1.0, | |
SpringDescription? springDescription, | |
AnimationBehavior? animationBehavior, | |
}) { | |
return physicsController.fling( | |
velocity: velocity, | |
springDescription: springDescription, | |
animationBehavior: animationBehavior, | |
); | |
} | |
@override | |
TickerFuture forward({double? from}) { | |
return physicsController.forward(from: from); | |
} | |
@override | |
bool get isAnimating => physicsController.isAnimating; | |
@override | |
bool get isCompleted => physicsController.isCompleted; | |
@override | |
bool get isDismissed => physicsController.isDismissed; | |
@override | |
bool get isForwardOrCompleted => physicsController.isForwardOrCompleted; | |
@override | |
Duration? get lastElapsedDuration => physicsController.lastElapsedDuration; | |
@override | |
double get lowerBound => physicsController.lowerBound; | |
@override | |
void notifyListeners() { | |
physicsController.notifyListeners(); | |
} | |
@override | |
void notifyStatusListeners(AnimationStatus status) { | |
physicsController.notifyStatusListeners(status); | |
} | |
@override | |
void removeListener(VoidCallback listener) { | |
physicsController.removeListener(listener); | |
} | |
@override | |
void removeStatusListener(AnimationStatusListener listener) { | |
physicsController.removeStatusListener(listener); | |
} | |
@override | |
TickerFuture repeat({ | |
double? min, | |
double? max, | |
bool reverse = false, | |
Duration? period, | |
int? count, | |
}) { | |
return physicsController.repeat( | |
min: min, | |
max: max, | |
reverse: reverse, | |
period: period, | |
count: count, | |
); | |
} | |
@override | |
void reset() { | |
physicsController.reset(); | |
} | |
@override | |
void resync(TickerProvider vsync) { | |
physicsController.resync(vsync); | |
} | |
@override | |
TickerFuture reverse({double? from}) { | |
return physicsController.reverse(from: from); | |
} | |
@override | |
AnimationStatus get status => physicsController.status; | |
@override | |
void stop({bool canceled = true}) { | |
physicsController.stop(canceled: canceled); | |
} | |
@override | |
String toStringDetails() { | |
return physicsController.toStringDetails(); | |
} | |
@override | |
TickerFuture toggle({double? from}) { | |
throw UnimplementedError('toggle is not implemented yet'); | |
} | |
@override | |
double get upperBound => physicsController.upperBound; | |
@override | |
double get velocity => physicsController.velocity; | |
@override | |
Animation<double> get view => physicsController.view; | |
@override | |
TickerFuture animateBackWith(Simulation simulation) { | |
// TODO: implement animateBackWith | |
throw UnimplementedError(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class BottomSheetPage extends StatefulWidget { | |
const BottomSheetPage({super.key}); | |
@override | |
State<BottomSheetPage> createState() => _BottomSheetPageState(); | |
} | |
class _BottomSheetPageState extends State<BottomSheetPage> | |
with TickerProviderStateMixin { | |
late PhysicsController controller; | |
@override | |
void initState() { | |
controller = PhysicsController(vsync: this); | |
super.initState(); | |
} | |
@override | |
void dispose() { | |
controller.dispose(); | |
super.dispose(); | |
} | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
body: Center( | |
child: ElevatedButton( | |
onPressed: () { | |
showModalBottomSheet( | |
context: context, | |
transitionAnimationController: | |
AnimationsControllerAdapter(controller), | |
builder: (context) { | |
return Container( | |
height: 200, | |
color: Colors.blueGrey, | |
child: Center( | |
child: Column( | |
mainAxisAlignment: MainAxisAlignment.center, | |
mainAxisSize: MainAxisSize.min, | |
children: <Widget>[ | |
const Text('Modal BottomSheet'), | |
ElevatedButton( | |
child: const Text('Close BottomSheet'), | |
onPressed: () => Navigator.pop(context), | |
), | |
], | |
), | |
), | |
); | |
}, | |
); | |
}, | |
child: Text('Show bottom sheet'), | |
), | |
), | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment