This commit is contained in:
toly
2023-12-10 15:25:12 +08:00
parent 2ceed8b9b5
commit 7b16b52761
86 changed files with 3635 additions and 930 deletions

View File

@@ -0,0 +1,25 @@
import 'package:flutter/cupertino.dart';
Map<String, String> kRouteLabelMap = {
'': '',
'/color': '颜色板',
'/color/add': '添加颜色',
'/color/detail': '颜色详情',
'/counter': '计数器',
'/sort': '排序算法',
'/sort/player': '',
'/sort/settings': '排序配置',
'/user': '我的',
'/settings': '系统设置',
};
String calcRouteName(BuildContext context,String path){
String? result = kRouteLabelMap[path];
if(result !=null) return result;
if(path.startsWith('/sort/player/')){
return path.split('/sort/player/')[1];
}
return '未知路由';
}

View File

@@ -0,0 +1,108 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
class RouterHistoryScope extends InheritedNotifier<RouterHistory> {
const RouterHistoryScope({super.key, required super.child, super.notifier});
static RouterHistory of(BuildContext context) {
return context
.dependOnInheritedWidgetOfExactType<RouterHistoryScope>()!
.notifier!;
}
static RouterHistory read(BuildContext context) {
return context
.getInheritedWidgetOfExactType<RouterHistoryScope>()!
.notifier!;
}
}
class RouterHistory with ChangeNotifier {
final List<String> exclusives;
final GoRouterDelegate delegate;
final List<RouteMatchList> _histories = [];
final List<RouteMatchList> _backHistories = [];
List<RouteMatchList> get histories => _histories;
RouterHistory(this.delegate, {this.exclusives = const []}) {
delegate.addListener(_onRouteChange);
}
/// 用于记录当前历史记录
/// 清空历史之后,切换时,先记录 _current
RouteMatchList? _current;
void _onRouteChange() {
/// 当没有历史,且 _current 非空
if (_histories.isEmpty && _current != null) {
_histories.add(_current!);
}
RouteMatchList matchList = delegate.currentConfiguration;
if (_histories.isNotEmpty && matchList == _histories.last
|| matchList.isEmpty
) return;
String uri = matchList.last.matchedLocation;
if (exclusives.contains(uri)) {
return;
}
_recode(matchList);
}
/// 将 [history] 加入历史记录
void _recode(RouteMatchList history) {
_current = history;
_histories.add(history);
if (hasHistory) {
notifyListeners();
}
}
bool get hasHistory => _histories.length > 1;
bool get hasBackHistory => _backHistories.isNotEmpty;
/// 历史回退操作
/// 将当前顶层移除,并加入 [_backHistories] 撤销列表
/// 并转到前一路径 [_histories.last]
void back() {
if (!hasHistory) {
return;
}
RouteMatchList top = _histories.removeLast();
_backHistories.add(top);
if (_histories.isNotEmpty) {
delegate.setNewRoutePath(_histories.last);
notifyListeners();
}
}
/// 撤销回退操作
/// 取出回退列表的最后元素,跳转到该路径
void revocation() {
RouteMatchList target = _backHistories.removeLast();
delegate.setNewRoutePath(target);
notifyListeners();
}
void close(RouteMatchList history) {
_histories.remove(history);
notifyListeners();
}
void clear() {
_histories.clear();
notifyListeners();
}
void select(RouteMatchList history) {
_histories.remove(history);
delegate.setNewRoutePath(history);
}
}

View File

@@ -0,0 +1,44 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import '../../../pages/counter/counter_page.dart';
import '../../../pages/user/user_page.dart';
import '../../../pages/settings/settings_page.dart';
import '../../../pages/empty/empty_panel.dart';
import '../views/app_navigation.dart';
import 'color.dart';
import 'sort.dart';
final RouteBase appRoute = ShellRoute(
builder: (BuildContext context, GoRouterState state, Widget child) {
return AppNavigation(navigator: child);
},
routes: <RouteBase>[
colorRouters,
GoRoute(
path: 'counter',
builder: (BuildContext context, GoRouterState state) {
return const CounterPage();
}),
sortRouters,
GoRoute(
path: 'user',
builder: (BuildContext context, GoRouterState state) {
return const UserPage();
},
),
GoRoute(
path: 'settings',
builder: (BuildContext context, GoRouterState state) {
return const SettingPage();
},
),
GoRoute(
path: '404',
builder: (BuildContext context, GoRouterState state) {
String msg = '无法访问: ${state.extra}';
return EmptyPanel(msg: msg);
},
)
],
);

View File

@@ -0,0 +1,35 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import '../../../pages/color/color_add_page.dart';
import '../../../pages/color/color_detail_page.dart';
import '../../../pages/color/color_page.dart';
final RouteBase colorRouters = GoRoute(
path: 'color',
builder: (BuildContext context, GoRouterState state) {
return const ColorPage();
},
routes: <RouteBase>[
GoRoute(
path: 'detail',
name: 'colorDetail',
builder: (BuildContext context, GoRouterState state) {
String? selectedColor = state.uri.queryParameters['color'];
Color color = Colors.black;
if (selectedColor != null) {
color = Color(int.parse(selectedColor, radix: 16));
}
return ColorDetailPage(color: color);
},
),
GoRoute(
path: 'add',
builder: (BuildContext context, GoRouterState state) {
return const ColorAddPage();
},
),
],
);

View File

@@ -0,0 +1,27 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import '../../../pages/login/login.dart';
import 'app.dart';
final RouteBase rootRoute = GoRoute(
path: '/',
redirect: _redirect,
routes: [
appRoute,
GoRoute(
path: 'login',
builder: (BuildContext context, GoRouterState state) {
return const LoginPage();
},
),
],
);
FutureOr<String?> _redirect(BuildContext context, GoRouterState state) {
if(state.fullPath=='/'){
return '/color';
}
return null;
}

View File

@@ -0,0 +1,44 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import '../../../pages/sort/provider/state.dart';
import '../../../pages/sort/views/player/sort_player.dart';
import '../../../pages/sort/views/settings/sort_setting.dart';
import '../../../pages/sort/views/sort_page/sort_page.dart';
final RouteBase sortRouters = ShellRoute(
builder: (BuildContext context, GoRouterState state, Widget child) {
return SortNavigation(navigator: child);
},
routes: [
GoRoute(
path: 'sort',
redirect: _redirectSort,
routes: [
GoRoute(
path: 'player/:name',
builder: (BuildContext context, GoRouterState state) {
print(state.pathParameters);// 获取路径参数
return const SortPlayer();
},
),
GoRoute(
path: 'settings',
builder: (BuildContext context, GoRouterState state) {
return const SortSettings();
},
),
],
),
],
);
FutureOr<String?> _redirectSort(BuildContext context, GoRouterState state) {
if (state.fullPath == '/sort') {
String name = SortStateScope.read(context).config.name;
return '/sort/player/$name';
}
return null;
}

View File

@@ -0,0 +1,43 @@
import 'package:flutter/material.dart';
class FadePageTransitionsBuilder extends PageTransitionsBuilder {
const FadePageTransitionsBuilder();
@override
Widget buildTransitions<T>(
PageRoute<T>? route,
BuildContext? context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child,
) {
return _FadePagePageTransition(
animation: animation,
secondaryAnimation: secondaryAnimation,
child: child,
);
}
}
class _FadePagePageTransition extends StatelessWidget {
const _FadePagePageTransition({
required this.animation,
required this.secondaryAnimation,
required this.child,
});
final Animation<double> animation;
final Animation<double> secondaryAnimation;
final Widget child;
@override
Widget build(BuildContext context) {
var curveTween = CurveTween(curve: Curves.easeIn);
return FadeTransition(
opacity: animation.drive(curveTween),
child: child,
);
}
}

View File

@@ -0,0 +1,52 @@
// Copyright 2021, the Flutter project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:flutter/material.dart';
class FadeTransitionPage<T> extends Page<T> {
final Widget child;
final Duration duration;
const FadeTransitionPage({
super.key,
required this.child,
this.duration = const Duration(milliseconds: 300),
});
@override
Route<T> createRoute(BuildContext context) => PageBasedFadeTransitionRoute<T>(this);
}
class PageBasedFadeTransitionRoute<T> extends PageRoute<T> {
final FadeTransitionPage<T> _page;
PageBasedFadeTransitionRoute(this._page) : super(settings: _page);
@override
Color? get barrierColor => null;
@override
String? get barrierLabel => null;
@override
Duration get transitionDuration => _page.duration;
@override
bool get maintainState => true;
@override
Widget buildPage(BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation) {
var curveTween = CurveTween(curve: Curves.easeIn);
return FadeTransition(
opacity: animation.drive(curveTween),
child: (settings as FadeTransitionPage).child,
);
}
@override
Widget buildTransitions(BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation, Widget child) =>
child;
}

View File

@@ -0,0 +1,47 @@
// Copyright 2021, the Flutter project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:flutter/material.dart';
class NoTransitionPage<T> extends Page<T> {
final Widget child;
const NoTransitionPage({
super.key,
required this.child,
});
@override
Route<T> createRoute(BuildContext context) => NoTransitionRoute<T>(this);
}
class NoTransitionRoute<T> extends PageRoute<T> {
final NoTransitionPage<T> _page;
NoTransitionRoute(this._page) : super(settings: _page);
@override
Color? get barrierColor => null;
@override
String? get barrierLabel => null;
@override
Duration get transitionDuration => const Duration(milliseconds: 0);
@override
bool get maintainState => true;
@override
Widget buildPage(BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation) {
return (settings as NoTransitionPage).child;
}
@override
Widget buildTransitions(BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation, Widget child) =>
child;
}

View File

@@ -0,0 +1,50 @@
import 'package:flutter/material.dart';
import 'app_navigation_rail.dart';
import 'app_top_bar/app_top_bar.dart';
class AppNavigation extends StatefulWidget {
final Widget navigator;
const AppNavigation({super.key,required this.navigator});
@override
State<AppNavigation> createState() => _AppNavigationState();
}
class _AppNavigationState extends State<AppNavigation> {
@override
void initState() {
print('======_AppNavigationState#initState==============');
super.initState();
}
@override
void dispose() {
print('======_AppNavigationState#dispose==============');
super.dispose();
}
@override
Widget build(BuildContext context) {
double px1 = 1/View.of(context).devicePixelRatio;
return Scaffold(
body: Row(
children: [
const AppNavigationRail(),
Expanded(
child: Column(
children: [
const AppTopBar(),
Divider(height: px1,),
Expanded(
child: widget.navigator,
),
],
),
),
],
),
);
}
}

View File

@@ -0,0 +1,65 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:iroute/components/components.dart';
class AppNavigationRail extends StatefulWidget {
const AppNavigationRail({super.key});
@override
State<AppNavigationRail> createState() => _AppNavigationRailState();
}
class _AppNavigationRailState extends State<AppNavigationRail> {
final List<MenuMeta> deskNavBarMenus = const [
MenuMeta(label: '颜色板', icon: Icons.color_lens_outlined, path: '/color'),
MenuMeta(label: '计数器', icon: Icons.add_chart, path: '/counter'),
MenuMeta(label: '排序', icon: Icons.sort, path: '/sort'),
MenuMeta(label: '我的', icon: Icons.person, path: '/user'),
MenuMeta(label: '设置', icon: Icons.settings, path: '/settings'),
];
@override
Widget build(BuildContext context) {
return DragToMoveWrap(
child: TolyNavigationRail(
items: deskNavBarMenus,
leading: const Padding(
padding: EdgeInsets.symmetric(vertical: 18.0),
child: FlutterLogo(),
),
tail: Padding(
padding: const EdgeInsets.only(bottom: 6.0),
child: Text(
'V0.1.1',
style: TextStyle(color: Colors.white, fontSize: 12),
),
),
backgroundColor: const Color(0xff3975c6),
onDestinationSelected: _onDestinationSelected,
selectedIndex: activeIndex,
),
);
}
final RegExp _segReg = RegExp(r'/\w+');
int? get activeIndex {
final String path = GoRouterState.of(context).uri.toString();
RegExpMatch? match = _segReg.firstMatch(path);
if (match == null) return null;
String? target = match.group(0);
int index = deskNavBarMenus.indexWhere((menu) => menu.path!.contains(target??''));
if (index == -1) return null;
return index;
}
void _onDestinationSelected(int index) {
String path = deskNavBarMenus[index].path!;
if(index==4){
GoRouter.of(context).push(path);
}else{
GoRouter.of(context).go(path);
}
}
}

View File

@@ -0,0 +1,76 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:iroute/components/toly_ui/button/hover_icon_button.dart';
// import '../../router/app_router_delegate.dart';
class AppRouterEditor extends StatefulWidget {
final ValueChanged<String>? onSubmit;
const AppRouterEditor({super.key, this.onSubmit});
@override
State<AppRouterEditor> createState() => _AppRouterEditorState();
}
class _AppRouterEditorState extends State<AppRouterEditor> {
final TextEditingController _controller = TextEditingController();
late GoRouterDelegate _delegate ;
@override
void initState() {
super.initState();
_delegate = GoRouter.of(context).routerDelegate;
_onRouteChange();
_delegate.addListener(_onRouteChange);
}
void _onRouteChange() {
List<RouteMatch> matches = _delegate.currentConfiguration.matches;
if(matches.isEmpty) return;
RouteMatch match = matches.last;
if(match is ImperativeRouteMatch){
_controller.text = match.matches.uri.toString();
}else{
_controller.text = match.matchedLocation;
}
}
@override
void dispose() {
_controller.dispose();
_delegate.removeListener(_onRouteChange);
super.dispose();
}
@override
Widget build(BuildContext context) {
return Stack(
alignment: Alignment.centerRight,
children: [
SizedBox(
child: CupertinoTextField(
controller: _controller,
style: TextStyle(fontSize: 14),
padding: EdgeInsets.only(left:12,top: 6,bottom: 6,right: 32),
placeholder: '输入路由地址导航',
onSubmitted: widget.onSubmit,
decoration: BoxDecoration(color: Color(0xffF1F2F3),borderRadius: BorderRadius.circular(6)),
),
),
Padding(
padding: const EdgeInsets.only(right: 8.0),
child: HoverIconButton(
icon: Icons.directions_outlined,
defaultColor: Color(0xff68696B),
onPressed:()=>widget.onSubmit?.call(_controller.text),
size: 20
),
)
],
);
}
}

View File

@@ -0,0 +1,137 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:iroute/components/components.dart';
import '../../helper/function.dart';
import '../route_back_indicator.dart';
import 'app_router_editor.dart';
import 'route_history_button.dart';
import 'history_view_icon.dart';
class AppTopBar extends StatelessWidget {
const AppTopBar({super.key});
@override
Widget build(BuildContext context) {
return DragToMoveWrap(
child: Container(
// alignment: Alignment.center,
height: 46,
child: Row(
children: [
const SizedBox(width: 16),
const RouteBackIndicator(),
const RouterIndicator(),
// Spacer(),
Expanded(
child: Row(textDirection: TextDirection.rtl, children: [
const Padding(
padding: EdgeInsets.symmetric(vertical: 12.0),
child: VerticalDivider(
width: 32,
),
),
HistoryViewIcon(),
const SizedBox(
width: 12,
),
SizedBox(
width: 250,
child: AppRouterEditor(
onSubmit: (path) {
GoRouter.of(context).go(path);
// => router.changePath(path)
},
)),
const SizedBox(
width: 12,
),
RouteHistoryButton(),
])),
const WindowButtons()
],
),
),
);
}
}
class RouterIndicator extends StatefulWidget {
const RouterIndicator({super.key});
@override
State<RouterIndicator> createState() => _RouterIndicatorState();
}
class _RouterIndicatorState extends State<RouterIndicator> {
late GoRouterDelegate _delegate;
@override
void initState() {
super.initState();
_delegate = GoRouter.of(context).routerDelegate;
_delegate.addListener(_onRouterChange);
}
@override
void dispose() {
_delegate.removeListener(_onRouterChange);
super.dispose();
}
@override
Widget build(BuildContext context) {
List<RouteMatch> matches = _delegate.currentConfiguration.matches;
if(matches.isEmpty) return const SizedBox();
RouteMatch match = _delegate.currentConfiguration.matches.last;
print(
"=========_RouterIndicatorState:build==${match.matchedLocation}========");
return TolyBreadcrumb(
items: pathToBreadcrumbItems(context, match.matchedLocation),
onTapItem: (item) {
if (item.to != null) {
GoRouter.of(context).go(item.to!);
}
},
);
}
void _onRouterChange() {
setState(() {});
}
List<BreadcrumbItem> pathToBreadcrumbItems(
BuildContext context, String path) {
Uri uri = Uri.parse(path);
List<BreadcrumbItem> result = [];
String to = '';
String distPath = '';
for (String segment in uri.pathSegments) {
distPath += '/$segment';
}
for (String segment in uri.pathSegments) {
to += '/$segment';
String label = calcRouteName(context, to);
if (label.isNotEmpty) {
result
.add(BreadcrumbItem(to: to, label: label, active: to == distPath));
}
}
return result;
}
}
Map<String, String> kRouteLabelMap = {
'': '',
'/color': '颜色板',
'/color/add': '添加颜色',
'/color/detail': '颜色详情',
'/counter': '计数器',
'/sort': '排序算法',
'/sort/player': '演示',
'/sort/settings': '排序配置',
'/user': '我的',
'/settings': '系统设置',
};

View File

@@ -0,0 +1,156 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:iroute/components/components.dart';
import 'package:iroute/v11/app/navigation/helper/function.dart';
import '../../helper/router_history.dart';
import 'app_top_bar.dart';
class HistoryViewIcon extends StatelessWidget{
const HistoryViewIcon({super.key});
@override
Widget build(BuildContext context) {
RouterHistory routerHistory = RouterHistoryScope.read(context);
return MouseRegion(
cursor: SystemMouseCursors.click,
child: PopPanel(
offset: const Offset(0, 10),
panel: SizedBox(
height: 350,
child: Column(
children: [
_buildTopBar(routerHistory),
const Expanded(
child:HistoryPanel(),
),
],
),
),
child: const Icon(
Icons.history,
size: 20,
),
),
);
}
Widget _buildTopBar( RouterHistory routerHistory) {
return Container(
decoration: BoxDecoration(
color: const Color(0xffFAFAFC),
borderRadius: BorderRadius.circular(6),
),
padding:
const EdgeInsets.only(top: 10, left: 12, right: 12, bottom: 8),
child: Row(
children: [
const Text(
'浏览历史',
style: TextStyle(fontWeight: FontWeight.bold),
),
const Spacer(),
TextButton(onPressed: routerHistory.clear, child: const Text('清空历史'))
],
));
}
}
class HistoryItem extends StatefulWidget {
final RouteMatchList history;
final VoidCallback onPressed;
final VoidCallback onDelete;
const HistoryItem({super.key, required this.history, required this.onPressed, required this.onDelete});
@override
State<HistoryItem> createState() => _HistoryItemState();
}
class _HistoryItemState extends State<HistoryItem> {
@override
Widget build(BuildContext context) {
String path = widget.history.matches.last.matchedLocation;
return MouseRegion(
cursor: SystemMouseCursors.click,
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: widget.onPressed,
child: Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(path),
const SizedBox(
height: 2,
),
Text(calcRouteName(context, path)),
],
)),
GestureDetector(
onTap: widget.onDelete,
child: const Icon(
Icons.close,
size: 18,
color: Color(0xff8E92A9),
),
),
],
),
),
);
}
}
class HistoryPanel extends StatefulWidget {
const HistoryPanel({super.key});
@override
State<HistoryPanel> createState() => _HistoryPanelState();
}
class _HistoryPanelState extends State<HistoryPanel> {
late RouterHistory _history ;
@override
void didChangeDependencies() {
super.didChangeDependencies();
_history = RouterHistoryScope.of(context);
}
@override
Widget build(BuildContext context) {
List<RouteMatchList> histories = _history.histories.reversed.toList();
if(histories.isEmpty){
return const Center(
child: Text(
'暂无浏览历史记录',
style: TextStyle(fontSize: 14, color: Colors.grey),
),
);
}
return ListView.builder(
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16),
itemExtent: 46,
itemCount: histories.length,
itemBuilder: (_, index) =>
HistoryItem(
onDelete: (){
_history.close(histories[index]);
},
onPressed: ()async {
Navigator.of(context).pop();
_history.select(histories[index]);
// router.changeRoute(histories[index].copyWith(recordHistory: false));
},
history: histories[index]),
);
}
void _onChange() {
setState(() {});
}
}

View File

@@ -0,0 +1,52 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:iroute/components/toly_ui/button/hover_icon_button.dart';
import '../../helper/router_history.dart';
class RouteHistoryButton extends StatefulWidget {
const RouteHistoryButton({super.key});
@override
State<RouteHistoryButton> createState() => _RouteHistoryButtonState();
}
class _RouteHistoryButtonState extends State<RouteHistoryButton> {
late RouterHistory _history ;
@override
void didChangeDependencies() {
super.didChangeDependencies();
_history = RouterHistoryScope.of(context);
}
@override
Widget build(BuildContext context) {
bool hasHistory = _history.hasHistory;
bool hasBackHistory = _history.hasBackHistory;
Color activeColor = const Color(0xff9195AC);
Color inActiveColor = const Color(0xffC7CAD5);
Color historyColor = hasHistory?activeColor:inActiveColor;
Color backHistoryColor = hasBackHistory?activeColor:inActiveColor;
return Wrap(
children: [
HoverIconButton(
size: 20,
hoverColor: historyColor,
defaultColor: historyColor,
icon: CupertinoIcons.arrow_left_circle,
onPressed: hasHistory?_history.back:null,
),
const SizedBox(width: 8,),
HoverIconButton(
size: 20,
hoverColor: backHistoryColor,
defaultColor: backHistoryColor,
icon: CupertinoIcons.arrow_right_circle,
onPressed: hasBackHistory?_history.revocation:null,
),
],
);
}
}

View File

@@ -0,0 +1,25 @@
import 'package:flutter/material.dart';
class NotFindPage extends StatelessWidget {
const NotFindPage({super.key});
@override
Widget build(BuildContext context) {
return const Material(
child: Center(
child: Wrap(
spacing: 16,
crossAxisAlignment: WrapCrossAlignment.center,
direction: Axis.vertical,
children: [
Icon(Icons.nearby_error,size: 64, color: Colors.redAccent),
Text(
'404 Page Not Find',
style: TextStyle(fontSize: 24, color: Colors.grey),
),
],
),
),
);
}
}

View File

@@ -0,0 +1,58 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
class RouteBackIndicator extends StatefulWidget {
const RouteBackIndicator({super.key});
@override
State<RouteBackIndicator> createState() => _RouteBackIndicatorState();
}
class _RouteBackIndicatorState extends State<RouteBackIndicator> {
late GoRouterDelegate _delegate ;
@override
void initState() {
super.initState();
_delegate = GoRouter.of(context).routerDelegate;
_delegate.addListener(_onChange);
}
@override
void dispose() {
_delegate.removeListener(_onChange);
super.dispose();
}
@override
Widget build(BuildContext context) {
bool hasPush = _delegate.currentConfiguration.matches
.whereType<ImperativeRouteMatch>().isNotEmpty;
if(hasPush){
return MouseRegion(
cursor: SystemMouseCursors.click,
child: GestureDetector(
onTap: context.pop,
child: Container(
width: 26,
height: 26,
margin: EdgeInsets.only(right: 8),
alignment: Alignment.center,
decoration: BoxDecoration(
color: Color(0xffE3E5E7),
borderRadius: BorderRadius.circular(6)
),
child: Icon(Icons.arrow_back_ios_new,size: 14,)),
),
);
}
return SizedBox();
}
void _onChange() {
setState(() {
});
}
}