Reputation: 419
How can I create a page that slides from the bottom of the screen and when it passes a certain threshold automatically fills the screen? Something like this:
Upvotes: 4
Views: 7700
Reputation: 429
You can use PageRouteBuilder
to build your own navigator transitions.
This is the CustomPageRouteBuilder
class as you need, and you can change it into other transitons like scale
fade
rotate
, etc.
class CustomPageRouteBuilder<T> extends PageRouteBuilder<T> {
CustomPageRouteBuilder({
this.widget,
})
: assert(widget != null),
super(
pageBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
return widget;
},
transitionsBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
final Widget transition = SlideTransition(
position: Tween<Offset>(
begin: Offset(0.0, 1.0),
end: Offset.zero,
).animate(animation),
child: SlideTransition(
position: Tween<Offset>(
begin: Offset.zero,
end: Offset(0.0, -0.7),
).animate(secondaryAnimation),
child: child,
),
);
return transition;
},
);
final Widget widget;
}
And how to use:
Navigator.push(
context,
CustomPageRouteBuilder(
widget: SecondPage(),
),
);
You can check the sample below:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: FirstPage(),
);
}
}
class FirstPage extends StatelessWidget {
const FirstPage({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
color: Colors.red,
child: Center(
child: Text(
'First Page',
style: TextStyle(
color: Colors.white,
fontSize: 24.0,
),
),
),
),
floatingActionButton: FloatingActionButton(
child: Icon(
Icons.arrow_forward_ios,
color: Colors.white,
),
onPressed: () {
Navigator.push(
context,
CustomPageRouteBuilder(
widget: SecondPage(),
),
);
},
),
);
}
}
class SecondPage extends StatelessWidget {
const SecondPage({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
color: Colors.blue,
child: Center(
child: Text(
'Second Page',
style: TextStyle(
color: Colors.white,
fontSize: 24.0,
),
),
),
),
floatingActionButton: FloatingActionButton(
child: Icon(
Icons.arrow_back_ios,
color: Colors.white,
),
onPressed: () {
Navigator.pop(context);
},
),
);
}
}
class CustomPageRouteBuilder<T> extends PageRouteBuilder<T> {
CustomPageRouteBuilder({
this.widget,
})
: assert(widget != null),
super(
pageBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
return widget;
},
transitionsBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
final Widget transition = SlideTransition(
position: Tween<Offset>(
begin: Offset(0.0, 1.0),
end: Offset.zero,
).animate(animation),
child: SlideTransition(
position: Tween<Offset>(
begin: Offset.zero,
end: Offset(0.0, -0.7),
).animate(secondaryAnimation),
child: child,
),
);
return transition;
},
);
final Widget widget;
}
Upvotes: 3
Reputation: 5876
Consider using DraggableScrollableSheet class or sliding up panel package
Upvotes: 9
Reputation: 6171
I would recommend the PageView
widget, you can see more here and view the documentation.
Using the scrollDirection
property, you can set it to vertical so that you can swipe up to reveal a new page and you can swipe down to go back.
Upvotes: 0