I want to use animated page route on my flutter project. Now all of my routes are Named Route and I don't wanna change them. Is there any way I can use Page Route Animation with named route? Like: If I am going from PageOne() to PageTwo() using Navigator.of(context).pushNamed(PageTwo.routename), I don't wanna see default transition, May be I want to use scale animation or fade animation. Is there any way to do that?
onTap: () {
Navigator.of(context).pushNamed(
ProductsSearch.routeName,
arguments: ScreenArguments(null, null, null, null, null, null, true, false),
);
},
As your Question I have solved this demo answer try once it will work .
import 'package:flutter/material.dart';
void main() {
runApp(
MaterialApp(
home: HomePage(),
onGenerateRoute: (RouteSettings settings) {
final SecondHome args = settings.arguments;
switch (settings.name) {
case '/':
return SlideRightRoute(widget:HomePage());
break;
case '/second':
return
SlideRightRoute(widget:SecondHome(args.data1,args.data2,args.boolvalue));
break;
}
},
),
);
}
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home'),
),
body: new Center(
child: RaisedButton(
onPressed: () {
Navigator.of(context).pushNamed(
'/second',
arguments:SecondHome("data1","data2",true),
);
},
child: Text('Second Home'),
),
),
);
}
}
class SecondHome extends StatelessWidget {
String data1;
String data2;
bool boolvalue;
SecondHome(this.data1,this.data2,this.boolvalue);
#override
Widget build(BuildContext context) {
print("Secoendhomedata${data1}");
return Scaffold(
appBar: AppBar(
title: Text('Second Home'),
),
body: new Center(
child: RaisedButton(
onPressed: () {
Navigator.pop(context);
},
child: Text('Go Back'),
),
),
);
}
}
class SlideRightRoute extends PageRouteBuilder {
final Widget widget;
SlideRightRoute({this.widget})
: super(
pageBuilder: (BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation) {
return widget;
},
transitionsBuilder: (BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child) {
return new SlideTransition(
position: new Tween<Offset>(
begin: const Offset(1.0, 0.0),
end: Offset.zero,
).animate(animation),
child: child,
);
},
);
}
Related
I want to use pushNamed from page 1 to page 2 and use Dismissible Widget to close page 2.
when pull down I got a black screen when close it.
I want to see page 1 when I pull down close page 2
I use this example
class FirstScreen extends StatelessWidget {
const FirstScreen({super.key});
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('First Screen'),
),
body: Center(
child: ElevatedButton(
// Within the `FirstScreen` widget
onPressed: () {
// Navigate to the second screen using a named route.
Navigator.pushNamed(context, '/second');
},
child: const Text('Launch screen'),
),
),
);
}
}
class SecondScreen extends StatelessWidget {
const SecondScreen({super.key});
#override
Widget build(BuildContext context) {
return Dismissible(
key: UniqueKey(),
movementDuration: const Duration(milliseconds: 0),
resizeDuration: const Duration(milliseconds: 1),
onDismissed: (d) => Navigator.of(context).pop(),
direction: DismissDirection.down,
child: Scaffold(
appBar: AppBar(
title: const Text('Second Screen'),
),
body: Center(
child: ElevatedButton(
// Within the SecondScreen widget
onPressed: () {
// Navigate back to the first screen by popping the current route
// off the stack.
Navigator.pop(context);
},
child: const Text('Go back!'),
),
),
),
);
}
}
if I use this one it works!! but I don't want use it
Navigator.of(context).push(
PageRouteBuilder(
opaque: false,
pageBuilder: (context, animation, secondaryAnimation) => const SecondScreen(),
));
void main() {
runApp(
MaterialApp(
title: 'Named Routes Demo',
initialRoute: '/',
routes: {
'/': (context) => const FirstScreen(),
'/second': (context) => const SecondScreen(), }, ),
);
}
Use MaterialApp.onGenerateRoute instead of MaterialApp.routes and use the PageRouteBuilder that works already.
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Named Routes Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
onGenerateRoute: (settings) {
switch (settings.name) {
case '/':
return MaterialPageRoute(builder: (context) => const FirstScreen());
case '/second':
return PageRouteBuilder(
opaque: false,
pageBuilder: (context, animation, secondaryAnimation) =>
const SecondScreen(),
);
}
},
);
}
}
Is there a way to set an animation between two specific pages? I'm using onGenerateRoute to change animations between pages, but it can only filter through the page it's being navigated to.
Example: I have PageA, PageB and PageC, i can change the navigation animation when i'm navigating to PageC, but it doesn't matter if i'm navigating from PageA or PageB, the animation will always be the same.
What i'm asking for is if there is a way to make a custom animation specifically when i'm navigating between PageA and PageC and PageB and PageC.
Create Animated Navigation like this:
import 'package:flutter/material.dart';
void main() {
runApp(
const MaterialApp(
home: Page1(),
),
);
}
class Page1 extends StatelessWidget {
const Page1({super.key});
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Center(
child: ElevatedButton(
onPressed: () {
Navigator.of(context).push(_createRoute());
},
child: const Text('Go!'),
),
),
);
}
}
Route _createRoute() {
return PageRouteBuilder(
pageBuilder: (context, animation, secondaryAnimation) => const Page2(),
transitionsBuilder: (context, animation, secondaryAnimation, child) {
const begin = Offset(0.0, 1.0);
const end = Offset.zero;
const curve = Curves.ease;
var tween = Tween(begin: begin, end: end).chain(CurveTween(curve: curve));
return SlideTransition(
position: animation.drive(tween),
child: child,
);
},
);
}
class Page2 extends StatelessWidget {
const Page2({super.key});
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: const Center(
child: Text('Page 2'),
),
);
}
}
My transition animation doesn't apply to pages that have TextField.
when I remove TextField the animation works properly.
anybody know what's wrong?
this is my slider animation:
class SlideLeftRoute extends PageRouteBuilder {
final Widget page;
SlideLeftRoute({this.page})
: super(
pageBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
) =>
page,
transitionsBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child,
) =>
SlideTransition(
position: Tween<Offset>(
begin: const Offset(1, 0),
end: Offset.zero,
).animate(animation),
child: child,
),
);
}
this is my page:
class VerifyAuthPage extends StatelessWidget {
final String phone;
final int expTime;
VerifyAuthPage({Key key, #required this.phone, #required this.expTime});
#override
Widget build(BuildContext context) {
return Scaffold(body: Container(color: Colors.red,
child: TextField(),
),);
}
this is my root app:
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
statusBarColor: BanijetColors.PRIMARY,
statusBarBrightness: Brightness.light,
));
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
fontFamily: 'IranSanse',
primaryColor: Colors.PRIMARY,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: Splash(),
initialRoute: 'splash',
onGenerateRoute: (RouteSettings setting) {
return mapNamesToRoutes(setting);
},
);
}
}
this is mapNamesToRoute function:
SlideLeftRoute mapNamesToRoutes(RouteSettings setting) {
Widget destination;
final requestAuthCubit = sl<RequestAuthCubit>();
final verifyAuthCubit = sl<VerifyAuthCubit>();
switch (setting.name) {
case 'splash':
destination = Splash();
break;
case 'auth/request':
destination = MultiBlocProvider(providers: [
BlocProvider(
create: (_) => InputValidationCubit(
inputType: InputType.Phone,
inputValidator: sl<InputValidator>())),
BlocProvider.value(value: requestAuthCubit)
], child: RequestAuthPage());
break;
case 'auth/verify':
final Map<String, Object> bundle = setting.arguments;
destination = MultiBlocProvider(providers: [
BlocProvider(
create: (_) => InputValidationCubit(
inputType: InputType.VerificationCode,
inputValidator: sl<InputValidator>())),
BlocProvider.value(value: requestAuthCubit),
BlocProvider.value(value: verifyAuthCubit),
BlocProvider.value(value: sl<TimerCubit>()),
], child: VerifyAuthPage(phone: bundle['phone'], expTime: bundle['exp']));
break;
default:
destination = null;
}
return SlideLeftRoute(page: destination);
}
and this is my Splash page:
class Splash extends StatelessWidget {
#override
Widget build(BuildContext context) {
return StatefulWrapper(
onInit: () async {
Future.delayed(const Duration(milliseconds: 2000), () {
Navigator.pushReplacementNamed(context, 'auth/verify',
arguments: {'phone': '**********', 'exp': 120});
});
},
child: Scaffold(
body: Container(
child: Center(child: Text('Splash Screen')
// child: Text('Splash Screen'),
),
),
));
}
}
I am trying to move through the multiple FloatingActionButton to a second page, but I am faced with the following problem after pressing any of the FloatingActionButton popups: Could not find a generator for route RouteSettings("SecondScreens", null) in the _WidgetsAppState.
Where is the problem and how can it be solved if someone knows it helps me.
full code
import 'package:flutter/material.dart';
import 'dart:math' as math;
void main() {
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
State createState() => new MyHomePageState();
}
class MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
AnimationController _controller;
static const List<IconData> icons = const [
Icons.sms,
Icons.mail,
Icons.phone
];
#override
void initState() {
_controller = new AnimationController(
vsync: this,
duration: const Duration(milliseconds: 500),
);
}
Widget build(BuildContext context) {
Color backgroundColor = Theme.of(context).cardColor;
Color foregroundColor = Theme.of(context).accentColor;
return new Scaffold(
appBar: new AppBar(title: new Text('Speed Dial Example')),
floatingActionButton: new Column(
mainAxisSize: MainAxisSize.min,
children: new List.generate(icons.length, (int index) {
Widget child = new Container(
height: 70.0,
width: 56.0,
alignment: FractionalOffset.topCenter,
child: new ScaleTransition(
scale: new CurvedAnimation(
parent: _controller,
curve: new Interval(0.0, 1.0 - index / icons.length / 2.0,
curve: Curves.easeOut),
),
child:
fabWidget(context, index, backgroundColor, foregroundColor),
),
);
return child;
}).toList()
..add(
new FloatingActionButton(
heroTag: null,
child: new AnimatedBuilder(
animation: _controller,
builder: (BuildContext context, Widget child) {
return new Transform(
transform: new Matrix4.rotationZ(
_controller.value * 0.5 * math.pi),
alignment: FractionalOffset.center,
child: new Icon(
_controller.isDismissed ? Icons.share : Icons.close),
);
},
),
onPressed: () {
if (_controller.isDismissed) {
_controller.forward();
} else {
_controller.reverse();
}
},
),
),
),
);
}
Widget fabWidget(BuildContext context, int index, Color backgroundColor,
Color foregroundColor) {
String route = "";
switch (index) {
case 0:
route = "SecondScreens";
break;
case 1:
route = "thirdScreen";
break;
default:
}
return FloatingActionButton(
heroTag: null,
backgroundColor: backgroundColor,
mini: true,
child: new Icon(icons[index], color: foregroundColor),
onPressed: () {
Navigator.pushNamed(context, route);
},
);
}
}
You're using Navigator.pushNamed which requires the routes that you put as the second parameter to be defined in the App routes property like this:
MaterialApp(
// Start the app with the "/" named route. In this case, the app starts
// on the FirstScreen widget.
initialRoute: '/',
routes: {
// When navigating to the "/" route, build the FirstScreen widget.
'/': (context) => FirstScreen(),
// When navigating to the "/second" route, build the SecondScreen widget.
'/second': (context) => SecondScreen(),
},
);
Each route is defined as MapEntry and the first part is the route name, so the argument that you called "routeName" and the second one is a Widget constructor which is the page that you want that route to correspond to.
In your case you would add something like:
MaterialApp(
// Start the app with the "/" named route. In this case, the app starts
// on the FirstScreen widget.
initialRoute: '/',
routes: {
// When navigating to the "/" route, build the FirstScreen widget.
'/': (context) => MyHomePage(),
// When navigating to the "/second" route, build the SecondScreens widget.
'/second': (context) => SecondScreens(),
// When navigating to the "/third" route, build the thirdScreens widget.
'/third': (context) => SecondScreens(),
///All the other screens in your app.
},
);
Then your fabWidget function could be changed to this:
Widget fabWidget(BuildContext context, int index, Color backgroundColor,
Color foregroundColor) {
String route = "";
switch (index) {
case 0:
route = "/second";
break;
case 1:
route = "/third";
break;
default:
}
return FloatingActionButton(
heroTag: null,
backgroundColor: backgroundColor,
mini: true,
child: new Icon(icons[index], color: foregroundColor),
onPressed: () {
Navigator.pushNamed(context, route);
},
);
}
How to make this page transaction effect on flutter
Example:
instagram stories
Edit
With package https://pub.dev/packages/swipedetector, you can detect SwipeDown
and In OnSwipeDown() execute your route change logical with PageRouteBuilder
SwipeDetector(
child: ... //You Widget Tree here
),
onSwipeUp: () {
setState(() {
_swipeDirection = "Swipe Up";
});
},
onSwipeDown: () {
setState(() {
_swipeDirection = "Swipe Down";
});
},
onSwipeLeft: () {
setState(() {
_swipeDirection = "Swipe Left";
});
},
onSwipeRight: () {
setState(() {
_swipeDirection = "Swipe Right";
});
},
)
please use PageRouteBuilder to build animation
full code
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or simply save your changes to "hot reload" in a Flutter IDE).
// Notice that the counter didn't reset back to zero; the application
// is not restarted.
primarySwatch: Colors.blue,
),
home: HomePage(),
onGenerateRoute: (RouteSettings settings) {
switch (settings.name) {
case '/':
return SlideRightRoute(widget:HomePage());
break;
case '/second':
return SlideRightRoute(widget:SecondHome());
break;
}
}
);
}
}
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home'),
),
body: new Center(
child: RaisedButton(
onPressed: () {
Navigator.pushNamed(context, '/second');
},
child: Text('Second Home'),
),
),
);
}
}
class SecondHome extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Second Home'),
),
body: new Center(
child: RaisedButton(
onPressed: () {
Navigator.pop(context);
},
child: Text('Go Back'),
),
),
);
}
}
class SlideRightRoute extends PageRouteBuilder {
final Widget widget;
SlideRightRoute({this.widget})
: super(
pageBuilder: (BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation) {
return widget;
},
transitionsBuilder: (BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child) {
return new SlideTransition(
position: new Tween<Offset>(
begin: const Offset(1.0, 0.0),
end: Offset.zero,
).animate(animation),
child: child,
);
},
);
}