Flutter路由管理插件pop_scope_aware_cupertino_route的使用
Flutter路由管理插件pop_scope_aware_cupertino_route的使用
PopScopeAwareCupertinoRoute
PopScopeAwareCupertinoRoute是一个Flutter插件,它为CupertinoPageRoute
提供了增强功能。该插件不仅可以在iOS平台上使用,而且适用于所有平台。
PopScopeAwareCupertinoRouteTransition特性
此插件的关键在于对Flutter的CupertinoPageRoute进行了修改,并集成了Cupertino Will Pop Scope,以提供以下改进:
- 当用户尝试"滑动返回"时,提供视觉反馈——屏幕可以被拖拽一点后才会弹回原位。
- 如果包含的路由的
popDisposition
设置为doNotPop
,则会触发路由的onPopInvoked
回调。
一个使用了此包的工作示例应用程序可以在example文件夹中找到。
使用方法
要使用这个插件,在你的pubspec.yaml
文件中添加pop_scope_aware_cupertino_route
作为依赖项。
示例代码
导入库
// main.dart
import 'package:pop_scope_aware_cupertino_route/pop_scope_aware_cupertino_route.dart';
配置页面过渡效果
在主题配置中将所需平台的过渡构建器设置为PopScopeAwareCupertinoPageTransitionBuilder
。
// material_app.dart
final theme = ThemeData(
pageTransitionsTheme: const PageTransitionsTheme(
builders: {
TargetPlatform.android: ZoomPageTransitionsBuilder(),
TargetPlatform.iOS: PopScopeAwareCupertinoPageTransitionBuilder(),
},
),
);
确保将主题应用到应用程序中。
// material_app.dart
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: theme,
home: const HomeScreen(),
);
}
使用PopScope
// my_screen.dart
@override
Widget build(BuildContext context) {
return PopScope(
canPop: false, // 是否允许返回
onPopInvoked: (canPop) {
print(canPop); // 返回是否被允许
},
child: Container(), // 页面内容
);
}
完整示例Demo
下面是一个完整的示例,演示如何使用pop_scope_aware_cupertino_route
创建两个屏幕之间的导航,并控制返回行为。
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:pop_scope_aware_cupertino_route/pop_scope_aware_cupertino_route.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
pageTransitionsTheme: const PageTransitionsTheme(
builders: {
TargetPlatform.android: ZoomPageTransitionsBuilder(),
TargetPlatform.iOS: PopScopeAwareCupertinoPageTransitionBuilder(),
},
),
),
home: const HomeScreen(),
);
}
}
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
@override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
Future<String?> _goToSecondScreen(BuildContext context) =>
Navigator.of(context).push<String>(
MaterialPageRoute(builder: (_) => const SecondScreen()));
String? result;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Demo')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text('Result: $result'),
ElevatedButton(
onPressed: () async {
final newResult = await _goToSecondScreen(context);
setState(() {
result = newResult;
});
},
child: const Padding(
padding: EdgeInsets.symmetric(horizontal: 24.0, vertical: 12.0),
child: Text('Go to second screen'),
),
),
],
),
),
);
}
}
class SecondScreen extends StatefulWidget {
const SecondScreen({super.key});
@override
State<SecondScreen> createState() => _SecondScreenState();
}
class _SecondScreenState extends State<SecondScreen> {
bool _popAllowed = false;
_onWillPop(bool popAllowed, result) async {
if (!popAllowed) {
showAdaptiveDialog(
context: context,
barrierDismissible: true,
builder: (context) => AlertDialog.adaptive(
content: const Text('Back navigation is disabled.'),
actions: [
adaptiveAction(
context: context,
child: const Text('pop till home'),
onPressed: () => Navigator.of(context)
..pop()
..pop('popped in dialog'),
),
adaptiveAction(
context: context,
child: const Text('OK'),
onPressed: Navigator.of(context).pop,
),
],
),
);
}
}
Widget adaptiveAction({
required BuildContext context,
required VoidCallback onPressed,
required Widget child,
}) {
final ThemeData theme = Theme.of(context);
switch (theme.platform) {
case TargetPlatform.android:
case TargetPlatform.fuchsia:
case TargetPlatform.linux:
case TargetPlatform.windows:
return TextButton(onPressed: onPressed, child: child);
case TargetPlatform.iOS:
case TargetPlatform.macOS:
return CupertinoDialogAction(onPressed: onPressed, child: child);
}
}
void _updateChanges(bool value) => setState(() => _popAllowed = value);
@override
Widget build(BuildContext context) {
return PopScope(
canPop: _popAllowed,
onPopInvokedWithResult: _onWillPop,
child: Scaffold(
appBar: AppBar(title: const Text('Second Screen')),
body: Column(
children: [
SwitchListTile(
title: const Text('Back Navigation Enabled'),
value: _popAllowed,
onChanged: _updateChanges,
),
ListTile(
title: const Text('pop till home with result'),
onTap: () => Navigator.of(context).pop('popped till home'),
)
],
),
),
);
}
}
在这个例子中,我们创建了一个简单的Flutter应用,其中包含两个屏幕:HomeScreen
和SecondScreen
。通过PopScope
组件来控制是否允许从SecondScreen
返回到HomeScreen
,并且当返回操作被禁止时,会显示一个对话框给用户提示。此外,还展示了如何根据不同的平台(Android或iOS)自适应地选择不同的对话框样式。
更多关于Flutter路由管理插件pop_scope_aware_cupertino_route的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter路由管理插件pop_scope_aware_cupertino_route的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,pop_scope_aware_cupertino_route
是一个用于 Flutter 的路由管理插件,它扩展了 Cupertino 风格的路由,使其支持 WillPopScope
功能,这在 iOS 风格的应用中特别有用。当你需要在用户尝试返回上一页时执行某些操作时,这个插件会非常有用。
以下是一个如何使用 pop_scope_aware_cupertino_route
的代码示例:
1. 添加依赖
首先,在你的 pubspec.yaml
文件中添加 pop_scope_aware_cupertino_route
依赖:
dependencies:
flutter:
sdk: flutter
pop_scope_aware_cupertino_route: ^最新版本号 # 请替换为实际最新版本号
然后运行 flutter pub get
来获取依赖。
2. 导入并使用插件
接下来,在你的 Flutter 应用中导入并使用这个插件。假设你有一个简单的应用,有两个页面:HomePage
和 SecondPage
。
主文件 (main.dart)
import 'package:flutter/material.dart';
import 'package:pop_scope_aware_cupertino_route/pop_scope_aware_cupertino_route.dart';
import 'package:flutter/cupertino.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return CupertinoApp(
title: 'Flutter Demo',
home: HomePage(),
routes: {
'/second': (context) => SecondPage(),
},
navigatorObservers: [
RouteObserver<CupertinoPageRoute<dynamic>>(), // 添加一个 RouteObserver
],
);
}
}
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: Text('Home Page'),
trailing: CupertinoNavigationBar.trailing(
text: 'Next',
onPressed: () {
Navigator.of(context).pushNamed('/second');
},
),
),
child: Center(
child: Text('This is the Home Page'),
),
);
}
}
class SecondPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: Text('Second Page'),
),
child: WillPopScope(
onWillPop: () async {
// 在这里处理返回操作
bool? shouldPop = await showCupertinoDialog(
context: context,
builder: (context) {
return CupertinoAlertDialog(
title: Text('Are you sure?'),
content: Text('Do you want to go back?'),
actions: [
CupertinoDialogAction(
isDefaultAction: true,
child: Text('Cancel'),
onPressed: () => Navigator.pop(context, false),
),
CupertinoDialogAction(
child: Text('OK'),
onPressed: () => Navigator.pop(context, true),
),
],
);
},
);
return shouldPop ?? false;
},
child: CupertinoPageScaffold(
child: Center(
child: Text('This is the Second Page'),
),
),
),
);
}
}
// 自定义 CupertinoPageRoute 以支持 WillPopScope
class PopScopeAwareCupertinoRoute<T> extends PopScopeAwareRoute<T> {
PopScopeAwareCupertinoRoute({
required WidgetBuilder builder,
RouteSettings? settings,
}) : super(builder: builder, settings: settings);
@override
Widget buildPage(BuildContext context, _, __) {
final CupertinoPageScaffold scaffold = CupertinoPageScaffold(
child: builder!(context),
);
return scaffold;
}
@override
CupertinoPageRoute<T> getCupertinoPageRoute() {
return CupertinoPageRoute<T>(
builder: builder,
settings: settings,
);
}
}
// 自定义 RouterDelegate 和 CupertinoRouterDelegate
class MyRouterDelegate extends RouterDelegate<CupertinoRoute>
with ChangeNotifier, PopNavigatorRouterDelegateMixin<CupertinoRoute> {
@override
final List<NavigatorObserver> navigatorObservers = [];
@override
Widget build(BuildContext context) {
return CupertinoTabScaffold(
tabBar: CupertinoTabBar(
items: [
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.home),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.search),
label: 'Search',
),
],
),
tabBuilder: (context, index) {
switch (index) {
case 0:
return Navigator(
onGenerateRoute: (settings) {
if (settings.name == '/') {
return PopScopeAwareCupertinoRoute(
builder: (context) => HomePage(),
);
}
return null;
},
observers: navigatorObservers,
);
case 1:
return Navigator(
onGenerateRoute: (settings) {
if (settings.name == '/search') {
// 这里可以添加 SearchPage 的路由
return null;
}
return null;
},
observers: navigatorObservers,
);
default:
return Container();
}
},
);
}
@override
CupertinoRoute? currentRouteAfterPop() => null;
}
// 在 MyApp 中使用自定义 RouterDelegate
class MyAppWithRouter extends StatelessWidget {
@override
Widget build(BuildContext context) {
return CupertinoApp(
title: 'Flutter Demo',
onGenerateRouter: (_) => MyRouterDelegate(),
);
}
}
注意:
PopScopeAwareCupertinoRoute
类扩展了PopScopeAwareRoute
并实现了CupertinoPageRoute
的构建。- 在
MyApp
中,你可以使用自定义的RouterDelegate
(如MyRouterDelegate
)来管理路由,但这在上面的示例中未完全展示,仅展示了基本的CupertinoApp
结构。 - 在
SecondPage
中,WillPopScope
用于处理返回按钮的点击事件,显示一个确认对话框。
在实际项目中,你可能需要根据你的应用结构调整代码。这个示例提供了如何使用 pop_scope_aware_cupertino_route
的基本框架。