Skip to content

Instantly share code, notes, and snippets.

@sajithlaldev
Created June 6, 2025 12:25
Show Gist options
  • Save sajithlaldev/4e3f0919f47cc8ba4e594ce39585cf00 to your computer and use it in GitHub Desktop.
Save sajithlaldev/4e3f0919f47cc8ba4e594ce39585cf00 to your computer and use it in GitHub Desktop.
Smooth Transition animation in Flutter using flutter_physics
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();
}
}
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