Animating navigation only to and from specific pages in Flutter - flutter

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'),
),
);
}
}

Related

Flutter: How to combine PageRoute Animation with Navigator.of(context).pushNamed

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,
);
},
);
}

Sliding form steps in Flutter?

I'm creating a registration form in Flutter, and I would like the user to go through steps. Every step should transition to the next step with a sliding effect. For example, if I am on Step 1, moving to Step 2 should slide the form to the left, and I should get Form 2. Then if I go back to form 1, it should slide the form to the right.
Here's an illustration:
I tried to do that with multiple routes:
routes: {
'/': (context) => HomePage(),
'/step1': (context) => FormStep1(),
'/step2': (context) => FormStep2(),
},
Then on submit:
Navigator.push(
context,
EnterExitRoute(exitPage: FormStep1(), enterPage: FormStep2())
);
EnterExitRoute
But that makes the App Bar slide as well, and I want only the form to slide.
With an advice from a friend, I ended up using PageView. That way I didn't have to make a new route for every step.
class _RegisterFormState extends State<RegisterForm> {
final _formsPageViewController = PageController();
List _forms;
#override
Widget build(BuildContext context) {
_forms = [
WillPopScope(
onWillPop: () => Future.sync(this.onWillPop),
child: Step1Container(),
),
WillPopScope(
onWillPop: () => Future.sync(this.onWillPop),
child: Step2Container(),
),
];
return Expanded(
child: PageView.builder(
controller: _formsPageViewController,
physics: NeverScrollableScrollPhysics(),
itemBuilder: (BuildContext context, int index) {
return _forms[index];
},
),
);
}
void _nextFormStep() {
_formsPageViewController.nextPage(
duration: Duration(milliseconds: 300),
curve: Curves.ease,
);
}
bool onWillPop() {
if (_formsPageViewController.page.round() ==
_formsPageViewController.initialPage) return true;
_formsPageViewController.previousPage(
duration: Duration(milliseconds: 300),
curve: Curves.ease,
);
return false;
}
}
Explanation:
I'm wrapping every form with WillPopScope so "back" button will
affect navigation.
I'm using physics: NeverScrollableScrollPhysics() option on the PageView builder so it will not be affected by a swipe gesture.
On each button of a form step (except last step) I call the _nextFormStep()
method, which moves to the next form.
The child of each WillPopScope() in the list is simply the form / widget you want to be slided.
as an option you can wrap pages with Navigator widget
something like this
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
final GlobalKey<NavigatorState> _navigatorKey = GlobalKey<NavigatorState>();
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Title')),
body: SafeArea(
child: WillPopScope(
onWillPop: () async => !await _navigatorKey.currentState.maybePop(),
child: Navigator(
key: _navigatorKey,
onGenerateRoute: (settings) {
switch (settings.name) {
case '/':
return MaterialPageRoute(builder: (context) => HomePage());
break;
case '/step1':
return CupertinoPageRoute(builder: (context) => FormStep1());
break;
case '/step2':
return CupertinoPageRoute(builder: (context) => FormStep2());
break;
}
},
),
),
),
),
);
}
}
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
color: Colors.green[200],
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('HomePage'),
RaisedButton(
onPressed: () => Navigator.pushNamed(context, '/step1'),
child: Text('Start'),
),
],
),
);
}
}
class FormStep1 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
color: Colors.blue[200],
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('FormStep1'),
RaisedButton(
onPressed: () => Navigator.pushNamed(context, '/step2'),
child: Text('Next'),
),
],
),
);
}
}
class FormStep2 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
color: Colors.yellow[200],
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('FormStep2'),
RaisedButton(onPressed: () {}, child: Text('Next')),
],
),
);
}
}
also instead of CupertinoPageRoute you can use any custom Route with any transition

Flutter Transition Exit

On Android API we can use
overridePendingTransition(int enterAnim, int exitAnim)
to define the enter and exit transitions.
How to do it in Flutter?
I have implemented this code
class SlideLeftRoute extends PageRouteBuilder {
final Widget enterWidget;
SlideLeftRoute({this.enterWidget})
: super(
pageBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
return enterWidget;
},
transitionsBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
return SlideTransition(
position: new Tween<Offset>(
begin: const Offset(1.0, 0.0),
end: Offset.zero,
).animate(animation),
child: child
);
},
);
}
but it only defines the enter transition. How can i define de exit transition?
UPDATE
Imagine that i have two screens (Screen1 and Screen2), when i execute
Navigator.push(
context, SlideLeftRoute(enterWidget: Screen2()));
i'd like to apply an animation to both Screen1 and Screen2 and not only to Screen2
The correct way of achieving this is to use the secondaryAnimation parameter that is given in the transitionBuilder of a PageRouteBuilder object.
Here you can read more about the secondaryAnimation parameter in the documentation in the flutter/lib/src/widgets/routes.dart file in the flutter sdk:
///
/// When the [Navigator] pushes a route on the top of its stack, the
/// [secondaryAnimation] can be used to define how the route that was on
/// the top of the stack leaves the screen. Similarly when the topmost route
/// is popped, the secondaryAnimation can be used to define how the route
/// below it reappears on the screen. When the Navigator pushes a new route
/// on the top of its stack, the old topmost route's secondaryAnimation
/// runs from 0.0 to 1.0. When the Navigator pops the topmost route, the
/// secondaryAnimation for the route below it runs from 1.0 to 0.0.
///
/// The example below adds a transition that's driven by the
/// [secondaryAnimation]. When this route disappears because a new route has
/// been pushed on top of it, it translates in the opposite direction of
/// the new route. Likewise when the route is exposed because the topmost
/// route has been popped off.
///
/// ```dart
/// transitionsBuilder: (
/// BuildContext context,
/// Animation<double> animation,
/// Animation<double> secondaryAnimation,
/// Widget child,
/// ) {
/// return SlideTransition(
/// position: AlignmentTween(
/// begin: const Offset(0.0, 1.0),
/// end: Offset.zero,
/// ).animate(animation),
/// child: SlideTransition(
/// position: TweenOffset(
/// begin: Offset.zero,
/// end: const Offset(0.0, 1.0),
/// ).animate(secondaryAnimation),
/// child: child,
/// ),
/// );
/// }
/// ```
This is a working example using the secondaryAnimation parameter:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
initialRoute: '/',
onGenerateRoute: (RouteSettings settings) {
if (settings.name == '/') {
return PageRouteBuilder<dynamic>(
pageBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) => Page1(),
transitionsBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child,
) {
final Tween<Offset> offsetTween = Tween<Offset>(begin: Offset(0.0, 0.0), end: Offset(-1.0, 0.0));
final Animation<Offset> slideOutLeftAnimation = offsetTween.animate(secondaryAnimation);
return SlideTransition(position: slideOutLeftAnimation, child: child);
},
);
} else {
// handle other routes here
return null;
}
},
);
}
}
class Page1 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Page 1")),
backgroundColor: Colors.blue,
body: Center(
child: RaisedButton(
onPressed: () => Navigator.push(
context,
PageRouteBuilder<dynamic>(
pageBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) => Page2(),
transitionsBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child,
) {
final Tween<Offset> offsetTween = Tween<Offset>(begin: Offset(1.0, 0.0), end: Offset(0.0, 0.0));
final Animation<Offset> slideInFromTheRightAnimation = offsetTween.animate(animation);
return SlideTransition(position: slideInFromTheRightAnimation, child: child);
},
),
),
child: Text("Go to Page 2"),
),
),
);
}
}
class Page2 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Page 2"), backgroundColor: Colors.green),
backgroundColor: Colors.green,
body: Center(child: RaisedButton(onPressed: () => Navigator.pop(context), child: Text("Back to Page 1"))),
);
}
}
Result:
Screenshot (Null Safe):
I used a different way, but similar logic provided by diegodeveloper
Full code:
void main() => runApp(MaterialApp(home: Page1()));
class Page1 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey,
appBar: AppBar(title: Text('Page 1')),
body: Center(
child: ElevatedButton(
onPressed: () => Navigator.push(
context,
MyCustomPageRoute(
parent: this,
builder: (context) => Page2(),
),
),
child: Text('2nd Page'),
),
),
);
}
}
class Page2 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.blueGrey,
appBar: AppBar(title: Text('Page 2')),
body: Center(
child: ElevatedButton(
onPressed: () => Navigator.pop(context),
child: Text('Back'),
),
),
);
}
}
class MyCustomPageRoute<T> extends MaterialPageRoute<T> {
final Widget parent;
MyCustomPageRoute({
required this.parent,
required WidgetBuilder builder,
RouteSettings? settings,
}) : super(builder: builder, settings: settings);
#override
Widget buildTransitions(_, Animation<double> animation, __, Widget child) {
var anim1 = Tween<Offset>(begin: Offset.zero, end: Offset(-1.0, 0.0)).animate(animation);
var anim2 = Tween<Offset>(begin: Offset(1.0, 0.0), end: Offset.zero).animate(animation);
return Stack(
children: <Widget>[
SlideTransition(position: anim1, child: parent),
SlideTransition(position: anim2, child: child),
],
);
}
}
Good question , the PageRouteBuilder use an AnimationController by default to handle the animation transition so, when you dismiss your view, it just call 'reverse' method from the animationController and you will see the same animation you are using but in reverse.
In case you want to change the animation when you dismiss your view you can do it checking the status of the current animation and compare with AnimationStatus.reverse
This is your code with a Fade animation when it's in reverse.
class SlideLeftRoute extends PageRouteBuilder {
final Widget enterWidget;
SlideLeftRoute({this.enterWidget})
: super(
pageBuilder: (BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation) {
return enterWidget;
},
transitionsBuilder: (BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child) {
if (animation.status == AnimationStatus.reverse) {
//do your dismiss animation here
return FadeTransition(
opacity: animation,
child: child,
);
} else {
return SlideTransition(
position: new Tween<Offset>(
begin: const Offset(1.0, 0.0),
end: Offset.zero,
).animate(animation),
child: child);
}
},
);
}
WORKAROUND
class SlideLeftRoute extends PageRouteBuilder {
final Widget enterWidget;
final Widget oldWidget;
SlideLeftRoute({this.enterWidget, this.oldWidget})
: super(
transitionDuration: Duration(milliseconds: 600),
pageBuilder: (BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation) {
return enterWidget;
},
transitionsBuilder: (BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child) {
return Stack(
children: <Widget>[
SlideTransition(
position: new Tween<Offset>(
begin: const Offset(0.0, 0.0),
end: const Offset(-1.0, 0.0),
).animate(animation),
child: oldWidget),
SlideTransition(
position: new Tween<Offset>(
begin: const Offset(1.0, 0.0),
end: Offset.zero,
).animate(animation),
child: enterWidget)
],
);
});
}
Usage:
Navigator.of(context)
.push(SlideLeftRoute(enterWidget: Page2(), oldWidget: this));
#janosch's answer worked the best for me (so be sure to upvote him if this works for you), but #bihire boris's point about not being able to have more than 2 page routes in a navigation stack was true.
What worked for me was this:
class SlidingPageRouteBuilder extends PageRouteBuilder {
SlidingPageRouteBuilder({
required RoutePageBuilder pageBuilder,
}) : super(
transitionDuration: const Duration(milliseconds: 300),
reverseTransitionDuration: const Duration(milliseconds: 300),
pageBuilder: pageBuilder,
transitionsBuilder: (BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child) {
final pushingNext =
secondaryAnimation.status == AnimationStatus.forward;
final poppingNext =
secondaryAnimation.status == AnimationStatus.reverse;
final pushingOrPoppingNext = pushingNext || poppingNext;
late final Tween<Offset> offsetTween = pushingOrPoppingNext
? Tween<Offset>(
begin: const Offset(0.0, 0.0), end: const Offset(-1.0, 0.0))
: Tween<Offset>(
begin: const Offset(1.0, 0.0), end: const Offset(0.0, 0.0));
late final Animation<Offset> slidingAnimation = pushingOrPoppingNext
? offsetTween.animate(secondaryAnimation)
: offsetTween.animate(animation);
return SlideTransition(position: slidingAnimation, child: child);
},
);
}
And the implementation:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
initialRoute: Routes.first,
onGenerateRoute: Routes.generateRoutes,
},
);
}
}
class Routes {
static const String first = '/first';
static const String second = '/second';
static Route<dynamic>? generateRoutes(RouteSettings settings) {
switch (settings.name) {
case first:
return SlidingPageRouteBuilder(
pageBuilder: (context, animation, secondaryAnimation) =>
const FirstPage(),
);
case second:
return SlidingPageRouteBuilder(
pageBuilder: (BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation) =>
const SecondPage(),
);
default:
return null;
}
}
}
Result:
The one downside to this method (and all other methods I've seen) is that the user cannot drag their finger along the left edge of the screen towards the right to pop, in the way that a MaterialPageRoute lets you.
There is another way to do it. The problem of initState() getting called in oldWidget won't be there anymore.
void main() => runApp(MaterialApp(theme: ThemeData.dark(), home: HomePage()));
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Page 1")),
body: RaisedButton(
child: Text("Next"),
onPressed: () {
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (c, a1, a2) => Page2(),
transitionsBuilder: (context, anim1, anim2, child) {
return SlideTransition(
position: Tween<Offset>(end: Offset(0, 0), begin: Offset(1, 0)).animate(anim1),
child: Page2(),
);
},
),
);
},
),
);
}
}
class Page2 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Page 2")),
body: RaisedButton(
child: Text("Back"),
onPressed: () => Navigator.pop(context),
),
);
}
}

Flutter Navigator, Horizontal Transiation with PageRoutebuilder

I'm trying to force a horizontal Transiation in the Flutter Navigator Widget. Navigator uses the platform Default Transition from one screen to the next. In iOS, the transition is Right to left. Pops Left to Right. In Android it is Bottom to Top. I believe solution is to use a PageRouteBuilder, but no luck getting it to work. I marked the method with the Navigator Widget that I'd like to modify with a PageRouteBuilder to get desired Horizontal transition.
Code Snippet 2, is the Transition code I have been trying to make work with no luck.
This code works as default transition.
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'Flutter Demo Home Page'),
initialRoute: "/",
routes: {
'/Second': (context) => SecondScreen(),
},
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ButtonMaterial02(),
new Text('NAV DEMO...',),
new Text('How do I get a Horizontal Transition in Android?',),
],
),
),
// This trailing comma makes auto-formatting nicer for build methods.
);
}
//================================================================
//================================================================
Padding ButtonMaterial02() {
return Padding(
padding: const EdgeInsets.all(18.0),
child: new MaterialButton(
onPressed: MatButton02_onPress,
child: new Text("Material Button 02"),
padding: EdgeInsets.all(50.0),
minWidth: double.infinity,
color: Theme.of(context).primaryColor,
),
);
}
// add Horizontal code here
void MatButton02_onPress() {
print(" MaterialButton02 onPressed...");
Navigator.pushNamed(context, '/Second');
//*************************************************
//*************************************************
// HOW do I replace the Navigator above to use
// PageRouteBuilder so I can force ANDROID to
// Transition Right to Left instead of BottomToTop?
//*************************************************
//*************************************************
}
}
//================================================================
//================================================================
class SecondScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text("Second Screen"),
),
body: Center(
child: RaisedButton(
child: new Text("RETURN"),
onPressed: (){
Navigator.pop(context);
},
),
),
);
}
}
//================================================================
//================================================================
Code Snippet 2... transition code I have been trying to use.
transitionsBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child) {
return SlideTransition(
position: new Tween<Offset>(
begin: const Offset(1.0, 0.0),
end: Offset.zero,
).animate(animation),
child: new SlideTransition(
position: new Tween<Offset>(
begin: Offset.zero,
end: const Offset(1.0, 0.0),
).animate(secondaryAnimation),
child: child,
),
);
},
);
Navigator.of(context).push('Second');
You're interested in using the CupertinoPageRoute.
It animates from right to left, designed to imitate iOS's transition animation.
Following the example here, replace MaterialPageRoute references with CupertinoPageRoute and you'll be set!

flutter, PageRouteBuilder, adding Horizontal Transition

The native navigation transition for iOS is RightToLeft. The Native Navigation transition for ANDROID is Bottom to Top. I would like to override the Native Navigation transition in Flutter to have the same RIght to Left transtion across iOS and ANDROID. To do this, I am trying to use PageRouteBuilder but no luck getting it to work. The first code block, I have a very basic screen that works... but natively. The second snippet includes the navigation transition code I am attempting to integrate.
The Code I am trying to fix.
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
//==============================================
// How would I force a horizontal transition?
mbNav001(context),
new Text(
'Screen 1',
),
],
),
),
);
}
}
//===================================================
Padding mbNav001(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(28.0),
child: new MaterialButton(
height: 80.0,
padding: EdgeInsets.all(50.0),
minWidth: double.infinity,
color: Theme.of(context).primaryColor,
textColor: Colors.white,
child: new Text(
"material button a",
style: new TextStyle(
fontSize: 20.0,
color: Colors.yellow,
),
),
splashColor: Colors.redAccent,
// ----- This line is giving me error...
onPressed: () {
print('click mb');
//===========================================================
// How to force a horizontal trans in Navigation?
//===========================================================
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondScreen()),
);
}
// expecting to find... :
),
);
}
//===================================================
class SecondScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Second Screen"),
),
body: Center(
child: RaisedButton(
onPressed: () {
// Navigate back to first screen when tapped!
Navigator.pop(context);
},
child: Text('Go back!'),
),
),
);
}
}
this is the transition code I am trying to add.
transitionsBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child) {
return SlideTransition(
position: new Tween<Offset>(
begin: const Offset(1.0, 0.0),
end: Offset.zero,
).animate(animation),
child: new SlideTransition(
position: new Tween<Offset>(
begin: Offset.zero,
end: const Offset(1.0, 0.0),
).animate(secondaryAnimation),
child: child,
),
);
},
);
Navigator.of(context).push(pageRoute);
Using CupertinoPageRoute instead of MaterialPageRoute resolved the same issue in my case, without trying to apply any custom animation.
Navigator.of(context).push(CupertinoPageRoute(builder: (context) => MyPanel()));
This is the code i've used to achieve the slide up from the bottom animation on iOS. You'd just need to edit the tween values to achieve a left to right animation.
var builder = PageRouteBuilder(
pageBuilder: (BuildContext context,
Animation animation,
Animation secondaryAnimation) {
return YourChildWidgetHere();
},
transitionsBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child,
) {
return new SlideTransition(
position: new Tween<Offset>(
begin: const Offset(0.0, 1.0),
end: Offset.zero,
).animate(animation),
child: child,
);
});
Navigator.of(context).push(builder);