Flutter在开发人员中越来越受欢迎。大多数构建应用程序的方法已经建立,并且每天都在电子商务应用程序的开发中使用。导航主题降为背景或第三计划。框架提供什么导航API?已经开发出什么方法?这些方法如何使用?它们有什么用?
介绍
让我们从导航开始。导航是一种允许您在具有指定参数的用户界面之间导航的方法。
例如,在IOS世界中,它组织导航UIViewController,而在Android中-导航组件。Flutter提供了什么?
航海家
Flutter中的屏幕称为路由。为了在路线之间移动,有一个Navigator类,该类具有用于实现各种类型导航的扩展API。
导航至新路线并从中返回
让我们开始简单。通过push()方法调用到新屏幕(路线)的导航,该方法带有一个参数-这是Route。
Navigator.push(MaterialPageRoute(builder: (BuildContext context) => MyPage()));
让我们仔细看一下push方法调用:
Navigator — , .
Navigator.push() — route .
MaterialPageRoute() — route, .
builder — MaterialPageRoute, .
MyPage — Stateful/Stateless Widget
route
pop().
Navigator.pop();
builder . Navigator, build.
Navigator.push(context, MaterialPageRoute(builder: (context) => MyPage(someData: data)));
MyPage ( ).
pop() .
Navigator.pop(data);
Navigator State
Navigator, MaterialApp/CupertinoApp/WidgetsApp. State API .
Stack. "call flow" NavigatorState.
vs
. route, .
:
, — ?
: , . .
, — ?
: , .
Imperative vs Declarative Programming
. . Route. Flutter route, MaterialPageRoute CupertinoPageRoute. CupertinoPageRoute title, settings.
:
Navigator.push(
context,
CupertinoPageRoute<T>(
title: "Setting",
builder: (BuildContext context) => MyPage(),
settings: RouteSettings(name:"my_page"),
),
);
route ViewModel/Controller/BLoC/… .
MyPage CupertinoPageRoute. push .
:
, route .
. .
:
Navigator.pushNamed(context, '/my_page');
. " " .
MaterialApp/CupertinoApp/WidgetsApp. 2 onGenerateRoute onUnknownRoute .
:
MaterialApp(
onUnknownRoute: (settings) => CupertinoPageRoute(
builder: (context) {
return UndefinedView(name: settings.name);
}
),
onGenerateRoute: (settings) {
if (settings.name == '\my_page') {
return CupertinoPageRoute(
title: "MyPage",
settings: settings,
builder: (context) => MyPage(),
);
}
//
},
);
:
onGenerateRoute — Navigator.pushNamed(). route.
onUnknownRoute — onGenerateRoute null. route, web — 404 page.
. , .
. .
:
- showAboutDialog
- showBottomSheet
- showDatePicker
- showGeneralDialog
- showMenu
- showModalBottomSheet
- showSearch
- showTimePicker
- showCupertinoDialog
- showDialog
- showLicensePage
- showCupertinoModalPopup
. API, .
?
, showGeneralDialog.
:
Future<T> showGeneralDialog<T>({
@required BuildContext context,
@required RoutePageBuilder pageBuilder,
bool barrierDismissible,
String barrierLabel,
Color barrierColor,
Duration transitionDuration,
RouteTransitionsBuilder transitionBuilder,
bool useRootNavigator = true,
RouteSettings routeSettings,
}) {
assert(pageBuilder != null);
assert(useRootNavigator != null);
assert(!barrierDismissible || barrierLabel != null);
return Navigator.of(context, rootNavigator: useRootNavigator).push<T>(_DialogRoute<T>(
pageBuilder: pageBuilder,
barrierDismissible: barrierDismissible,
barrierLabel: barrierLabel,
barrierColor: barrierColor,
transitionDuration: transitionDuration,
transitionBuilder: transitionBuilder,
settings: routeSettings,
));
}
. showGeneralDialog push NavigatorState _DialogRoute(). , .
— route .
route
"every thins is a route", . , route .
route Flutter — PageRoute PopupRoute.
PageRoute — route, .
PopupRoute — route, route.
PageRoute:
- MaterialPageRoute
- CupertinoPageRoute
- _SearchPageRoute
- PageRouteBuilder
PopupRoute:
- _ContexMenuRoute
- _DialogRoute
- _ModalBottomSheetRoute
- _CupertinoModalPopupRoute
- _PopupMenuRoute
PopupRoute , .
:
, .
Best practices
, " ?". , API , . .
:
- .
- BuildContext ( , BuildContext).
- . route, CupertinoPageRoute, BottomSheetRoute, DialogRoute ..
:
abstract class IRouter {
Future<T> routeTo<T extends Object>(RouteBundle bundle);
Future<bool> back<T extends Object>({T data, bool rootNavigator});
GlobalKey<NavigatorState> rootNavigatorKey;
}
:
routeTo - .
back — .
rootNavigatorKey — GlobalKey NavigatorState.
, .
class Router implements IRouter {
@override
GlobalKey<NavigatorState> rootNavigatorKey = GlobalKey<NavigatorState>();
@override
Future<T> routeTo<T>(RouteBundle bundle) async {
// Push logic here
}
@override
Future<bool> back<T>({T data, bool rootNavigator = false}) async {
// Back logic here
}
}
, routeTo().
@override
Future<T> routeTo<T>(RouteBundle bundle) async {
assert(bundle != null, "The bundle [RouteBundle.bundle] is null");
NavigatorState rootState = rootNavigatorKey.currentState;
assert(rootState != null, 'rootState [NavigatorState] is null');
switch (bundle.route) {
case "/routeExample":
return await rootState.push(
_buildRoute<T>(
bundle: bundle,
child: RouteExample(),
),
);
case "/my_page":
return await rootState.push(
_buildRoute<T>(
bundle: bundle,
child: MyPage(),
),
);
default:
throw Exception('Route is not found');
}
}
root NavigatorState ( WidgetsApp) push RouteBundle .
RouteBundle. , .
enum ContainerType {
/// The parent type is [Scaffold].
///
/// In IOS route with an iOS transition [CupertinoPageRoute].
/// In Android route with an Android transition [MaterialPageRoute].
///
scaffold,
/// Used for show child in dialog.
///
/// Route with [DialogRoute].
dialog,
/// Used for show child in [BottomSheet].
///
/// Route with [ModalBottomSheetRoute].
bottomSheet,
/// Used for show child only.
/// [AppBar] and other features is not implemented.
window,
}
class RouteBundle {
/// Creates a bundle that can be used for [Router].
RouteBundle({
this.route,
this.containerType,
});
/// The route for current navigation.
///
/// See [Routes] for details.
final String route;
/// The current status of this animation.
final ContainerType containerType;
}
enum ContainerType — , .
RouteBundle — - route.
_buildRoute. , route .
Route<T> _buildRoute<T>({@required RouteBundle bundle, @required Widget child}) {
assert(bundle.containerType != null, "The bundle.containerType [RouteBundle.containerType] is null");
switch (bundle.containerType) {
case ContainerType.scaffold:
return CupertinoPageRoute<T>(
title: bundle.title,
builder: (BuildContext context) => child,
settings: RouteSettings(name: bundle.route),
);
case ContainerType.dialog:
return DialogRoute<T>(
title: '123',
settings: RouteSettings(name: bundle.route),
pageBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
return child;
},
);
case ContainerType.bottomSheet:
return ModalBottomSheetRoute<T>(
settings: RouteSettings(name: bundle.route),
isScrollControlled: true,
builder: (BuildContext context) => child,
);
case ContainerType.window:
return CupertinoPageRoute<T>(
settings: RouteSettings(name: bundle.route),
builder: (BuildContext context) => child,
);
default:
throw Exception('ContainerType is not found');
}
}
ModalBottomSheetRoute DialogRoute, . route Material Flutter.
back.
@override
Future<bool> back<T>({T data, bool rootNavigator = false}) async {
NavigatorState rootState = rootNavigatorKey.currentState;
return await (rootState).maybePop<T>(data);
}
rootNavigatorKey App :
MaterialApp(
navigatorKey: widget.router.rootNavigatorKey,
home: Home()
);
, route. - "" , , Dependency Injection.
router.routeTo(RouteBundle(route: '/my_page', containerType: ContainerType.window));
, :
- BuildContext GlobalKey
- route View
Flutter , .