This commit is contained in:
toly
2023-12-27 00:55:04 +08:00
parent 34d8e6dd75
commit 1aeab4fa64
189 changed files with 85 additions and 8676 deletions

View File

@@ -1,4 +1,2 @@
01: 分析 push 方法。
A、B、C 三个界面跳转。
02: replace

4
lib/09/节点介绍.txt Normal file
View File

@@ -0,0 +1,4 @@
01: 分析 pop 方法。
A、B、C 三个界面跳转。
02: 分析 popUntil 方法。

5
lib/10/节点介绍.txt Normal file
View File

@@ -0,0 +1,5 @@
app_info.dart: 弹出对话框界面
cupertino_context_menu_demo.dart: 弹出 CupertinoContextMenu
dropdown_button_color.dart: 弹出 DropdownButton
more_pop_icon.dart: 弹出 PopupMenuButton
search_anchor_demo.dart: 弹出 SearchAnchor

1
lib/11/节点介绍.txt Normal file
View File

@@ -0,0 +1 @@
路由第二动画控制器效果演示

View File

@@ -1,11 +0,0 @@
import 'package:flutter/material.dart';
import 'pages/app/app.dart';
void main() {
runApp(const App());
}

View File

@@ -1,15 +0,0 @@
import 'package:flutter/material.dart';
import 'package:url_strategy/url_strategy.dart';
import 'pages/app.dart';
void main() {
setHashUrlStrategy();
runApp(const App());
}

View File

@@ -1,50 +0,0 @@
import 'package:flutter/material.dart';
import '../route/parser.dart';
import '../route/route_state.dart';
class App extends StatefulWidget {
const App({super.key});
@override
State<App> createState() => _AppState();
}
class _AppState extends State<App> {
late final RootRouterDelegate _delegate;
late final AppRouteParser _parser;
late final RouteState _routeState;
@override
void initState() {
super.initState();
_parser = AppRouteParser(initialRoute: '/color', allowPaths: [
'/color',
'/color/add',
'/color/detail/:colorHex',
]);
_routeState = RouteState(_parser);
_delegate = RootRouterDelegate(_routeState);
}
@override
Widget build(BuildContext context) {
return RouteStateScope(
notifier: _routeState,
child: MaterialApp.router(
routerDelegate: _delegate,
routeInformationParser: _parser,
theme: ThemeData(
useMaterial3: true,
appBarTheme: const AppBarTheme(
elevation: 0,
iconTheme: IconThemeData(color: Colors.black),
titleTextStyle: TextStyle(
color: Colors.black,
fontSize: 18,
fontWeight: FontWeight.bold,
))),
debugShowCheckedModeBanner: false,
),
);
}
}

View File

@@ -1,67 +0,0 @@
import 'dart:math';
import 'package:flutter/material.dart';
class ColorAddPage extends StatefulWidget {
const ColorAddPage({super.key});
@override
State<ColorAddPage> createState() => _ColorAddPageState();
}
class _ColorAddPageState extends State<ColorAddPage> {
late Color _color;
@override
void initState() {
super.initState();
_color = randomColor;
}
@override
Widget build(BuildContext context) {
String text = '# ${_color.value.toRadixString(16)}';
return Scaffold(
appBar: AppBar(
title: Text('添加颜色'),
actions: [IconButton(onPressed: _selectColor, icon: Icon(Icons.check ))],
),
body: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0,vertical: 20),
child: Row(
children: [
Expanded(child: Text(text,style: TextStyle(color: _color,fontSize: 24,letterSpacing: 4),)),
Container(
margin: EdgeInsets.only(left: 10),
width: 40,
height: 40,
child: Icon(
Icons.sell_outlined,
color: Colors.white,
),
decoration: BoxDecoration(
color: _color,
borderRadius: BorderRadius.circular(8),
),
),
],
),
),
);
}
Random _random = Random();
Color get randomColor {
return Color.fromARGB(
255,
_random.nextInt(256),
_random.nextInt(256),
_random.nextInt(256),
);
}
void _selectColor() {
Navigator.of(context).pop(_color);
}
}

View File

@@ -1,46 +0,0 @@
import 'package:flutter/material.dart';
import '../route/route_state.dart';
import 'color_add_page.dart';
import '../../../common/components/colors_panel.dart';
import '../../../common/pages/stl_color_page.dart';
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
final List<Color> _colors = [
Colors.red, Colors.black, Colors.blue, Colors.green, Colors.orange,
Colors.pink, Colors.purple, Colors.indigo, Colors.amber, Colors.cyan,
Colors.redAccent, Colors.grey, Colors.blueAccent, Colors.greenAccent, Colors.orangeAccent,
Colors.pinkAccent, Colors.purpleAccent, Colors.indigoAccent, Colors.amberAccent, Colors.cyanAccent,
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title:const Text('颜色主页')),
floatingActionButton: FloatingActionButton(
onPressed: _toAddPage,
child: const Icon(Icons.add),
),
body: ColorsPanel(
colors: _colors,
onSelect: _selectColor,
),
);
}
void _selectColor(Color color){
String value = '#${color.value.toRadixString(16)}';
RouteStateScope.of(context).go('/color/detail/$value');
}
void _toAddPage() async {
RouteStateScope.of(context).go('/color/add');
}
}

View File

@@ -1,27 +0,0 @@
// 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:collection/collection.dart';
import 'package:equatable/equatable.dart';
import 'package:quiver/core.dart';
/// A route path that has been parsed by [TemplateRouteParser].
class ParsedRoute extends Equatable{
/// The current path location without query parameters. (/book/123)
final String path;
/// The path template (/book/:id)
final String pathTemplate;
/// The path parameters ({id: 123})
final Map<String, String> parameters;
/// The query parameters ({search: abc})
final Map<String, String> queryParameters;
const ParsedRoute(this.path, this.pathTemplate, this.parameters, this.queryParameters);
@override
List<Object?> get props => [path,pathTemplate,parameters,queryParameters];
}

View File

@@ -1,135 +0,0 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:iroute/common/pages/stl_color_page.dart';
import 'package:path_to_regexp/path_to_regexp.dart';
import '../pages/home_page.dart';
import '../pages/color_add_page.dart';
import 'parsed_route.dart';
import 'route_state.dart';
class AppRouteParser extends RouteInformationParser<ParsedRoute> {
final List<String> allowPaths;
final ParsedRoute initialRoute;
AppRouteParser({
required this.allowPaths,
String initialRoute = '/',
}):initialRoute = ParsedRoute(initialRoute, initialRoute, {}, {});
@override
Future<ParsedRoute> parseRouteInformation(
RouteInformation routeInformation) async {
print("=======parseRouteInformation:${routeInformation.uri.path}===================");
final uri = routeInformation.uri;
final path = uri.toString();
final queryParams = uri.queryParameters;
ParsedRoute parsedRoute = initialRoute;
for (var pathTemplate in allowPaths) {
final parameters = <String>[];
var pathRegExp = pathToRegExp(pathTemplate, parameters: parameters);
if (pathRegExp.hasMatch(path)) {
final match = pathRegExp.matchAsPrefix(path);
if (match == null) continue;
final params = extract(parameters, match);
parsedRoute = ParsedRoute(path, pathTemplate, params, queryParams);
}
}
return parsedRoute;
}
@override
RouteInformation? restoreRouteInformation(ParsedRoute configuration) {
print("=======restoreRouteInformation:${configuration}===================");
return RouteInformation(uri: Uri.parse(configuration.path));
}
}
class RootRouterDelegate extends RouterDelegate<ParsedRoute>
with ChangeNotifier, PopNavigatorRouterDelegateMixin {
final RouteState routeState;
RootRouterDelegate(this.routeState) {
routeState.addListener(notifyListeners);
}
@override
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
@override
ParsedRoute get currentConfiguration {
print("=======currentConfiguration:${routeState.route.path}===================");
return routeState.route;
}
@override
void dispose() {
routeState.removeListener(notifyListeners);
routeState.dispose();
super.dispose();
}
final _addColorKey = const ValueKey('addColor');
@override
Widget build(BuildContext context) {
final routeState = RouteStateScope.of(context);
List<Page> pages =[];
final String pathTemplate = routeState.route.pathTemplate;
pages.add(MaterialPage(child: HomePage()));
String? selectedColor;
if (pathTemplate == '/color/detail/:colorHex') {
selectedColor = routeState.route.parameters['colorHex'];
}
if(selectedColor!=null){
pages.add(MaterialPage(child: StlColorPage(
color: Colors.redAccent,
)));
}
bool isAddPage = pathTemplate == '/color/add';
if(isAddPage){
pages.add(MaterialPage(
key: _addColorKey,
child: ColorAddPage()));
}
print("===build====================");
return Navigator(
key: navigatorKey,
pages: pages,
onPopPage: (route, result) {
print(result);
if (route.settings is Page &&
(route.settings as Page).key == _addColorKey) {
routeState.go('/color');
}
// appState.selectedBook = null;
// notifyListeners();
return route.didPop(result);
},
);
}
/// 格式: /a /b
@override
Future<void> setNewRoutePath(ParsedRoute configuration) async {
print("===setNewRoutePath===${configuration}=================");
routeState.route = configuration;
return;
}
// @override
// Future<void> setInitialRoutePath( configuration) async{
// _pages = [_pageMap['/']!];
// notifyListeners();
// }
}

View File

@@ -1,48 +0,0 @@
// 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/widgets.dart';
import 'parsed_route.dart';
import 'parser.dart';
/// The current route state. To change the current route, call obtain the state
/// using `RouteStateScope.of(context)` and call `go()`:
///
/// ```
/// RouteStateScope.of(context).go('/book/2');
/// ```
class RouteState extends ChangeNotifier {
final AppRouteParser _parser;
ParsedRoute _route;
RouteState(this._parser) : _route = _parser.initialRoute;
ParsedRoute get route => _route;
set route(ParsedRoute route) {
// Don't notify listeners if the path hasn't changed.
if (_route == route) return;
_route = route;
notifyListeners();
}
Future<void> go(String route) async {
this.route = await _parser
.parseRouteInformation(RouteInformation(uri: Uri.parse(route)));
}
}
/// Provides the current [RouteState] to descendant widgets in the tree.
class RouteStateScope extends InheritedNotifier<RouteState> {
const RouteStateScope({
required super.notifier,
required super.child,
super.key,
});
static RouteState of(BuildContext context) =>
context.dependOnInheritedWidgetOfExactType<RouteStateScope>()!.notifier!;
}

View File

@@ -1,15 +0,0 @@
import 'package:flutter/material.dart';
import 'package:url_strategy/url_strategy.dart';
import 'pages/app.dart';
void main() {
setHashUrlStrategy();
runApp(const App());
}

View File

@@ -1,46 +0,0 @@
import 'package:flutter/material.dart';
import '../route/parser.dart';
import '../route/route_state.dart';
class App extends StatefulWidget {
const App({super.key});
@override
State<App> createState() => _AppState();
}
class _AppState extends State<App> {
late final RootRouterDelegate _delegate;
late final AppRouteParser _parser;
late final RouteState _routeState;
@override
void initState() {
super.initState();
_parser = AppRouteParser();
_routeState = RouteState(_parser,initial: '/color');
_delegate = RootRouterDelegate(_routeState);
}
@override
Widget build(BuildContext context) {
return RouteStateScope(
notifier: _routeState,
child: MaterialApp.router(
routerDelegate: _delegate,
routeInformationParser: _parser,
theme: ThemeData(
useMaterial3: true,
appBarTheme: const AppBarTheme(
elevation: 0,
iconTheme: IconThemeData(color: Colors.black),
titleTextStyle: TextStyle(
color: Colors.black,
fontSize: 18,
fontWeight: FontWeight.bold,
))),
debugShowCheckedModeBanner: false,
),
);
}
}

View File

@@ -1,67 +0,0 @@
import 'dart:math';
import 'package:flutter/material.dart';
class ColorAddPage extends StatefulWidget {
const ColorAddPage({super.key});
@override
State<ColorAddPage> createState() => _ColorAddPageState();
}
class _ColorAddPageState extends State<ColorAddPage> {
late Color _color;
@override
void initState() {
super.initState();
_color = randomColor;
}
@override
Widget build(BuildContext context) {
String text = '# ${_color.value.toRadixString(16)}';
return Scaffold(
appBar: AppBar(
title: Text('添加颜色'),
actions: [IconButton(onPressed: _selectColor, icon: Icon(Icons.check ))],
),
body: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0,vertical: 20),
child: Row(
children: [
Expanded(child: Text(text,style: TextStyle(color: _color,fontSize: 24,letterSpacing: 4),)),
Container(
margin: EdgeInsets.only(left: 10),
width: 40,
height: 40,
child: Icon(
Icons.sell_outlined,
color: Colors.white,
),
decoration: BoxDecoration(
color: _color,
borderRadius: BorderRadius.circular(8),
),
),
],
),
),
);
}
Random _random = Random();
Color get randomColor {
return Color.fromARGB(
255,
_random.nextInt(256),
_random.nextInt(256),
_random.nextInt(256),
);
}
void _selectColor() {
Navigator.of(context).pop(_color);
}
}

View File

@@ -1,46 +0,0 @@
import 'package:flutter/material.dart';
import '../route/route_state.dart';
import 'color_add_page.dart';
import '../../../common/components/colors_panel.dart';
import '../../../common/pages/stl_color_page.dart';
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
final List<Color> _colors = [
Colors.red, Colors.black, Colors.blue, Colors.green, Colors.orange,
Colors.pink, Colors.purple, Colors.indigo, Colors.amber, Colors.cyan,
Colors.redAccent, Colors.grey, Colors.blueAccent, Colors.greenAccent, Colors.orangeAccent,
Colors.pinkAccent, Colors.purpleAccent, Colors.indigoAccent, Colors.amberAccent, Colors.cyanAccent,
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title:const Text('颜色主页')),
floatingActionButton: FloatingActionButton(
onPressed: _toAddPage,
child: const Icon(Icons.add),
),
body: ColorsPanel(
colors: _colors,
onSelect: _selectColor,
),
);
}
void _selectColor(Color color){
String value = color.value.toRadixString(16);
RouteStateScope.of(context).go('/color/detail?color=$value');
}
void _toAddPage() async {
RouteStateScope.of(context).go('/color/add');
}
}

View File

@@ -1,21 +0,0 @@
// 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:collection/collection.dart';
import 'package:equatable/equatable.dart';
import 'package:quiver/core.dart';
/// A route path that has been parsed by [TemplateRouteParser].
class ParsedRoute extends Equatable{
/// The current path location without query parameters. (/book/123)
final String path;
/// The query parameters ({search: abc})
final Map<String, String> queryParameters;
const ParsedRoute(this.path, this.queryParameters);
@override
List<Object?> get props => [path,queryParameters];
}

View File

@@ -1,119 +0,0 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:iroute/common/pages/stl_color_page.dart';
import 'package:path_to_regexp/path_to_regexp.dart';
import '../pages/home_page.dart';
import '../pages/color_add_page.dart';
import 'parsed_route.dart';
import 'route_state.dart';
class AppRouteParser extends RouteInformationParser<ParsedRoute> {
@override
Future<ParsedRoute> parseRouteInformation(
RouteInformation routeInformation) async {
print("=======parseRouteInformation:${routeInformation.uri.path}===================");
final uri = routeInformation.uri;
final path = uri.toString();
final queryParams = uri.queryParameters;
return ParsedRoute(path, queryParams);
}
@override
RouteInformation? restoreRouteInformation(ParsedRoute configuration) {
print("=======restoreRouteInformation:${configuration}===================");
return RouteInformation(uri: Uri.parse(configuration.path));
}
}
class RootRouterDelegate extends RouterDelegate<ParsedRoute>
with ChangeNotifier, PopNavigatorRouterDelegateMixin {
final RouteState routeState;
RootRouterDelegate(this.routeState) {
routeState.addListener(notifyListeners);
}
@override
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
@override
ParsedRoute get currentConfiguration {
print("=======currentConfiguration:${routeState.route.path}===================");
return routeState.route;
}
@override
void dispose() {
routeState.removeListener(notifyListeners);
routeState.dispose();
super.dispose();
}
final _addColorKey = const ValueKey('addColor');
@override
Widget build(BuildContext context) {
final routeState = RouteStateScope.of(context);
List<Page> pages =[];
final String path = routeState.route.path;
pages.add(MaterialPage(child: HomePage()));
String? selectedColor;
if (path.startsWith('/color/detail') ) {
selectedColor = routeState.route.queryParameters['color'];
}
if(selectedColor!=null){
pages.add(MaterialPage(child: StlColorPage(
color: Color(int.parse(selectedColor,radix: 16)),
)));
}
bool isAddPage = path == '/color/add';
if(isAddPage){
pages.add(MaterialPage(
key: _addColorKey,
child: ColorAddPage()));
}
return Navigator(
key: navigatorKey,
pages: pages,
onPopPage: (route, result) {
if (route.settings is Page && (route.settings as Page).key == _addColorKey) {
routeState.go('/color');
}
if(selectedColor!=null){
selectedColor = null;
routeState.go('/color');
}
return route.didPop(result);
},
);
}
/// 格式: /a /b
@override
Future<void> setNewRoutePath(ParsedRoute configuration) async {
print("===setNewRoutePath===${configuration}=================");
routeState.route = configuration;
return;
}
// @override
// Future<void> setInitialRoutePath( configuration) async{
// _pages = [_pageMap['/']!];
// notifyListeners();
// }
}

View File

@@ -1,48 +0,0 @@
// 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/widgets.dart';
import 'parsed_route.dart';
import 'parser.dart';
/// The current route state. To change the current route, call obtain the state
/// using `RouteStateScope.of(context)` and call `go()`:
///
/// ```
/// RouteStateScope.of(context).go('/book/2');
/// ```
class RouteState extends ChangeNotifier {
final AppRouteParser _parser;
ParsedRoute _route;
RouteState(this._parser,{String initial=''}) : _route = ParsedRoute(initial,{});
ParsedRoute get route => _route;
set route(ParsedRoute route) {
// Don't notify listeners if the path hasn't changed.
if (_route == route) return;
_route = route;
notifyListeners();
}
Future<void> go(String route) async {
this.route = await _parser
.parseRouteInformation(RouteInformation(uri: Uri.parse(route)));
}
}
/// Provides the current [RouteState] to descendant widgets in the tree.
class RouteStateScope extends InheritedNotifier<RouteState> {
const RouteStateScope({
required super.notifier,
required super.child,
super.key,
});
static RouteState of(BuildContext context) =>
context.dependOnInheritedWidgetOfExactType<RouteStateScope>()!.notifier!;
}

View File

@@ -1,15 +0,0 @@
import 'package:flutter/material.dart';
import 'package:url_strategy/url_strategy.dart';
import 'pages/app.dart';
void main() {
setHashUrlStrategy();
runApp(const App());
}

View File

@@ -1,36 +0,0 @@
import 'package:flutter/material.dart';
import '../route/parser.dart';
import '../route/route_state.dart';
class App extends StatefulWidget {
const App({super.key});
@override
State<App> createState() => _AppState();
}
AppRouteParser parser = AppRouteParser();
AppRouterDelegate routerDelegate = AppRouterDelegate();
class _AppState extends State<App> {
@override
Widget build(BuildContext context) {
return MaterialApp.router(
routerDelegate: routerDelegate,
routeInformationParser: parser,
// backButtonDispatcher: RootBackButtonDispatcher(),
theme: ThemeData(
useMaterial3: true,
appBarTheme: const AppBarTheme(
elevation: 0,
iconTheme: IconThemeData(color: Colors.black),
titleTextStyle: TextStyle(
color: Colors.black,
fontSize: 18,
fontWeight: FontWeight.bold,
))),
debugShowCheckedModeBanner: false,
);
}
}

View File

@@ -1,67 +0,0 @@
import 'dart:math';
import 'package:flutter/material.dart';
class ColorAddPage extends StatefulWidget {
const ColorAddPage({super.key});
@override
State<ColorAddPage> createState() => _ColorAddPageState();
}
class _ColorAddPageState extends State<ColorAddPage> {
late Color _color;
@override
void initState() {
super.initState();
_color = randomColor;
}
@override
Widget build(BuildContext context) {
String text = '# ${_color.value.toRadixString(16)}';
return Scaffold(
appBar: AppBar(
title: Text('添加颜色'),
actions: [IconButton(onPressed: _selectColor, icon: Icon(Icons.check ))],
),
body: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0,vertical: 20),
child: Row(
children: [
Expanded(child: Text(text,style: TextStyle(color: _color,fontSize: 24,letterSpacing: 4),)),
Container(
margin: EdgeInsets.only(left: 10),
width: 40,
height: 40,
child: Icon(
Icons.sell_outlined,
color: Colors.white,
),
decoration: BoxDecoration(
color: _color,
borderRadius: BorderRadius.circular(8),
),
),
],
),
),
);
}
Random _random = Random();
Color get randomColor {
return Color.fromARGB(
255,
_random.nextInt(256),
_random.nextInt(256),
_random.nextInt(256),
);
}
void _selectColor() {
Navigator.of(context).pop(_color);
}
}

View File

@@ -1,47 +0,0 @@
import 'package:flutter/material.dart';
import '../route/route_state.dart';
import 'app.dart';
import 'color_add_page.dart';
import '../../../common/components/colors_panel.dart';
import '../../../common/pages/stl_color_page.dart';
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
final List<Color> _colors = [
Colors.red, Colors.black, Colors.blue, Colors.green, Colors.orange,
Colors.pink, Colors.purple, Colors.indigo, Colors.amber, Colors.cyan,
Colors.redAccent, Colors.grey, Colors.blueAccent, Colors.greenAccent, Colors.orangeAccent,
Colors.pinkAccent, Colors.purpleAccent, Colors.indigoAccent, Colors.amberAccent, Colors.cyanAccent,
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title:const Text('颜色主页')),
floatingActionButton: FloatingActionButton(
onPressed: _toAddPage,
child: const Icon(Icons.add),
),
body: ColorsPanel(
colors: _colors,
onSelect: _selectColor,
),
);
}
void _selectColor(Color color){
String value = color.value.toRadixString(16);
routerDelegate.go('/color/detail?color=$value');
}
void _toAddPage() async {
routerDelegate.go('/color/add');
}
}

View File

@@ -1,21 +0,0 @@
// 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:collection/collection.dart';
import 'package:equatable/equatable.dart';
import 'package:quiver/core.dart';
/// A route path that has been parsed by [TemplateRouteParser].
class ParsedRoute extends Equatable{
/// The current path location without query parameters. (/book/123)
final String path;
/// The query parameters ({search: abc})
final Map<String, String> queryParameters;
const ParsedRoute(this.path, this.queryParameters);
@override
List<Object?> get props => [path,queryParameters];
}

View File

@@ -1,122 +0,0 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:iroute/common/pages/stl_color_page.dart';
import 'package:path_to_regexp/path_to_regexp.dart';
import '../pages/app.dart';
import '../pages/home_page.dart';
import '../pages/color_add_page.dart';
import 'parsed_route.dart';
import 'route_state.dart';
class AppRouteParser extends RouteInformationParser<ParsedRoute> {
@override
Future<ParsedRoute> parseRouteInformation(
RouteInformation routeInformation) async {
print("=======parseRouteInformation:${routeInformation.uri.path}===================");
final uri = routeInformation.uri;
final path = uri.toString();
final queryParams = uri.queryParameters;
return ParsedRoute(path, queryParams);
}
@override
RouteInformation? restoreRouteInformation(ParsedRoute configuration) {
print("=======restoreRouteInformation:${configuration}===================");
return RouteInformation(uri: Uri.parse(configuration.path));
}
}
class AppRouterDelegate extends RouterDelegate<ParsedRoute>
with ChangeNotifier, PopNavigatorRouterDelegateMixin {
AppRouterDelegate({String initial = '/'}) {
_routes.add(ParsedRoute(initial, {}));
}
final List<ParsedRoute> _routes = [];
@override
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
@override
ParsedRoute get currentConfiguration {
return _routes.last;
}
Future<void> go(String route) async {
ParsedRoute _route = await parser.parseRouteInformation(RouteInformation(uri: Uri.parse(route)));
if(_route!=_routes.last){
_routes.add(_route);
}
notifyListeners();
}
final _addColorKey = const ValueKey('addColor');
final _colorDetailKey = const ValueKey('ColorDetail');
@override
Widget build(BuildContext context) {
List<Page> pages = [];
for (ParsedRoute route in _routes) {
Page? page = _buildPageByPath(route);
if(page!=null){
pages.add(page);
}
}
return Navigator(
key: navigatorKey,
pages: pages,
onPopPage: _onPagePop,
);
}
Page? _buildPageByPath(ParsedRoute route) {
if(route.path == '/'){
return MaterialPage(child: HomePage());
}
if(route.path.startsWith('/color/detail')){
String? selectedColor = route.queryParameters['color'];
if (selectedColor != null) {
Color color = Color(int.parse(selectedColor, radix: 16));
return MaterialPage(key: _colorDetailKey, child: StlColorPage(color: color));
}
}
if (route.path == '/color/add') {
return MaterialPage(key: _addColorKey, child: ColorAddPage());
}
return null;
}
@override
Future<void> setNewRoutePath(ParsedRoute configuration) async {
print("===setNewRoutePath===${configuration}=================");
if(configuration!=_routes.last){
_routes.add(configuration);
}
}
bool _onPagePop(Route route, result) {
RouteSettings settings = route.settings;
if(settings is Page){
if(settings.key==_addColorKey){
_routes.removeLast();
notifyListeners();
}
if(settings.key==_colorDetailKey){
_routes.removeLast();
notifyListeners();
}
}
return route.didPop(result);
}
}

View File

@@ -1,48 +0,0 @@
// 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/widgets.dart';
import 'parsed_route.dart';
import 'parser.dart';
/// The current route state. To change the current route, call obtain the state
/// using `RouteStateScope.of(context)` and call `go()`:
///
/// ```
/// RouteStateScope.of(context).go('/book/2');
/// ```
class RouteState extends ChangeNotifier {
final AppRouteParser _parser;
ParsedRoute _route;
RouteState(this._parser,{String initial=''}) : _route = ParsedRoute(initial,{});
ParsedRoute get route => _route;
set route(ParsedRoute route) {
// Don't notify listeners if the path hasn't changed.
if (_route == route) return;
_route = route;
notifyListeners();
}
Future<void> go(String route) async {
this.route = await _parser
.parseRouteInformation(RouteInformation(uri: Uri.parse(route)));
}
}
// /// Provides the current [RouteState] to descendant widgets in the tree.
// class RouteStateScope extends InheritedNotifier<RouteState> {
// const RouteStateScope({
// required super.notifier,
// required super.child,
// super.key,
// });
//
// static RouteState of(BuildContext context) =>
// context.dependOnInheritedWidgetOfExactType<RouteStateScope>()!.notifier!;
// }

View File

@@ -1,14 +0,0 @@
import 'package:flutter/material.dart';
import 'pages/app/app.dart';
import 'pages/app/app_router_delegate.dart';
AppRouterDelegate router = AppRouterDelegate();
void main() {
runApp(const App());
}

View File

@@ -1,29 +0,0 @@
import 'package:flutter/material.dart';
import '../../main.dart';
import 'app_tool_bar.dart';
class App extends StatelessWidget {
const App({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
appBarTheme: const AppBarTheme(
elevation: 0,
iconTheme: IconThemeData(color: Colors.black),
titleTextStyle: TextStyle(
color: Colors.black,
fontSize: 18,
fontWeight: FontWeight.bold,
))),
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppToolBar(),
body: Router(routerDelegate: router),
));
}
}

View File

@@ -1,73 +0,0 @@
import 'package:flutter/material.dart';
import '../page_a.dart';
import '../page_b.dart';
import '../page_c.dart';
import '../home_page.dart';
class AppRouterDelegate extends RouterDelegate<String> with ChangeNotifier, PopNavigatorRouterDelegateMixin {
AppRouterDelegate({String initial = '/'}):_path=initial;
String _path;
String get path=> _path;
void go(String path){
_path = path;
notifyListeners();
}
@override
Widget build(BuildContext context) {
return Navigator(
onPopPage: _onPopPage,
pages: parserConfig(_path).map((e) => _pageMap[e]!).toList(),
);
}
final Map<String, Page> _pageMap = const {
'/': MaterialPage(child: HomePage()),
'a': MaterialPage(child: PageA()),
'b': MaterialPage(child: PageB()),
'c': MaterialPage(child: PageC()),
};
Widget buildNavigatorByConfig(String path) {
return Navigator(
onPopPage: _onPopPage,
pages: parserConfig(path).map((e) => _pageMap[e]!).toList(),
);
}
bool _onPopPage(Route route, result) {
if(path.length>1){
int last = path.lastIndexOf('/');
_path = path.substring(0,last);
if(_path.isEmpty) _path = '/';
notifyListeners();
}
return route.didPop(result);
}
@override
GlobalKey<NavigatorState>? navigatorKey = GlobalKey<NavigatorState>();
@override
Future<void> setNewRoutePath(String configuration) async{
_path = configuration;
}
List<String> parserConfig(String path){
/// 例: /a/b/c 进栈 /,a,b,c 界面
List<String> result = ['/'];
if(path.startsWith('/')){
path = path.substring(1);
if(path.isNotEmpty){
List<String> parts = path.split('/');
result.addAll(parts);
}
}
return result;
}
}

View File

@@ -1,64 +0,0 @@
import 'package:flutter/material.dart';
import '../../main.dart';
class AppToolBar extends StatefulWidget implements PreferredSizeWidget{
const AppToolBar({super.key});
@override
State<AppToolBar> createState() => _AppToolBarState();
@override
Size get preferredSize => const Size.fromHeight(kToolbarHeight);
}
class _AppToolBarState extends State<AppToolBar> {
TextEditingController _ctrl = TextEditingController();
@override
void initState() {
super.initState();
_changRoute();
router.addListener(_changRoute);
}
@override
void dispose() {
router.removeListener(_changRoute);
_ctrl.dispose();
super.dispose();
}
void _changRoute() {
_ctrl.text=router.path;
}
@override
Widget build(BuildContext context) {
return AppBar(
backgroundColor: Colors.white,
elevation: 0,
title : TextField(
controller: _ctrl,
onSubmitted: _onSubmitted,
decoration: InputDecoration( //装饰
filled: true, //填充
fillColor: Color(0xffF3F6F9), //填充颜色
constraints: BoxConstraints(maxHeight: 34), //约束信息
contentPadding: EdgeInsets.only(top: -14,left: 10),
border: UnderlineInputBorder( //边线信息
borderSide: BorderSide.none,
borderRadius: BorderRadius.all(Radius.circular(6)),
),
hintText: "请输入路由", //提示字
hintStyle: TextStyle(fontSize: 14) //提示字样式
),
),
);
}
void _onSubmitted(String value) {
router.go(value);
}
}

View File

@@ -1,30 +0,0 @@
import 'package:flutter/material.dart';
import '../main.dart';
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
const Color bgColor = Color(0xffCCFFCC);
return Scaffold(
backgroundColor: bgColor,
appBar: AppBar(
title: const Text('主页起点'),
backgroundColor: bgColor,
),
body: Center(child: ElevatedButton(
onPressed: () => toPageA(context),
child: const Text('Push A'),
),
));
}
void toPageA(BuildContext context) {
router.go('/a');
}
}

View File

@@ -1,30 +0,0 @@
import 'package:flutter/material.dart';
import '../main.dart';
class PageA extends StatelessWidget {
const PageA({super.key});
@override
Widget build(BuildContext context) {
const Color bgColor = Color(0xffCCFFFF);
return Scaffold(
backgroundColor: bgColor,
appBar: AppBar(
title: const Text('A 界面'),
backgroundColor: bgColor,
),
body: Center(
child: ElevatedButton(
onPressed: () => toPageB(context),
child: const Text('Push B'),
),
));
}
void toPageB(BuildContext context) {
// router.value = ['/', 'a', 'b'];
router.go('/a/b');
}
}

View File

@@ -1,32 +0,0 @@
import 'package:flutter/material.dart';
import '../main.dart';
class PageB extends StatelessWidget {
const PageB({super.key});
@override
Widget build(BuildContext context) {
const Color bgColor = Color(0xffCCE5FF);
return Scaffold(
backgroundColor: bgColor,
appBar: AppBar(
title: const Text('B 界面'),
backgroundColor: bgColor,
),
body: Center(
child: ElevatedButton(
onPressed: () => toPageC(context),
child: const Text('Push C'),
),
));
}
void toPageC(BuildContext context){
router.go('/a/b/c');
}
}

View File

@@ -1,24 +0,0 @@
import 'package:flutter/material.dart';
import '../main.dart';
class PageC extends StatelessWidget {
const PageC({super.key});
@override
Widget build(BuildContext context) {
const Color bgColor = Color(0xffFFE6CC);
return Scaffold(
backgroundColor: bgColor,
appBar: AppBar(
title: const Text('C 界面'),
backgroundColor: bgColor,
),
body: Center(
child: Text('到达终点'),
));
}
}

View File

@@ -1,13 +0,0 @@
import 'package:flutter/material.dart';
import 'pages/app/app.dart';
void main() {
runApp(const App());
}

View File

@@ -1,83 +0,0 @@
import 'package:toly_menu/toly_menu.dart';
List<MenuData> menus = [
MenuData(path: '/dashboard', label: '总览面板', children: [
MenuData(path: '/dashboard/data_analyse', label: '数据分析', deep: 1),
MenuData(path: '/dashboard/work_board', label: '工作台', deep: 1, children: [
MenuData(path: '/dashboard/work_board/a', label: '第一工作区', deep: 2),
MenuData(path: '/dashboard/work_board/b', label: '第二工作区', deep: 2),
MenuData(path: '/dashboard/work_board/c', label: '第三工作区', deep: 2),
]),
]),
MenuData(path: '/cases', label: '案例演示', children: [
MenuData(path: '/cases/counter', label: '计数器项目', deep: 1),
MenuData(path: '/cases/guess', label: '猜数字项目', deep: 1),
MenuData(path: '/cases/muyu', label: '电子木鱼项目', deep: 1),
MenuData(path: '/cases/canvas', label: '白板绘制项目', deep: 1),
MenuData(path: '/cases/timer', label: '计时器项目', deep: 1),
]),
MenuData(path: '/manager', label: '系统管理', children: [
MenuData(path: '/manager/account', label: '账号管理', deep: 1),
MenuData(path: '/manager/role', label: '角色管理', deep: 1),
MenuData(path: '/manager/menu', label: '菜单管理', deep: 1),
]),
MenuData(path: '/knowledge', label: '知识库管理', children: [
MenuData(path: '/knowledge/a', label: '语文知识', deep: 1, children: [
MenuData(
path: '/knowledge/a/1',
label: '诗词歌赋',
deep: 2,
),
MenuData(
path: '/knowledge/a/2',
label: '人物故事',
deep: 2,
),
MenuData(
path: '/knowledge/a/3',
label: '名著推荐',
deep: 2,
)
]),
MenuData(
path: '/knowledge/b',
label: '数学知识',
children: [
MenuData(
path: '/knowledge/b/1',
label: '人物故事',
deep: 2,
),
MenuData(
path: '/knowledge/b/2',
label: '数学定理',
deep: 2,
),
MenuData(
path: '/knowledge/b/3',
label: '几何知识',
deep: 2,
),
MenuData(
path: '/knowledge/b/4',
label: '代数知识',
deep: 2,
)
],
deep: 1),
MenuData(
path: '/knowledge/c',
label: '英语知识',
deep: 1,
),
]),
MenuData(path: '/widgets', label: '组件集录', children: [
MenuData(path: '/widgets/stateless', label: '无状态组件', deep: 1),
MenuData(path: '/widgets/stateful', label: '有状态组件', deep: 1),
MenuData(path: '/widgets/single_child', label: '单子渲染组件', deep: 1),
MenuData(path: '/widgets/mutli_child', label: '多子渲染组件', deep: 1),
MenuData(path: '/widgets/sliver', label: '滑片组件', deep: 1),
MenuData(path: '/widgets/proxy', label: '代理组件', deep: 1),
MenuData(path: '/widgets/other', label: '其他组件', deep: 1),
])
];

View File

@@ -1,107 +0,0 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:toly_menu/toly_menu.dart';
import '../../menus.dart';
import '../../transition/fade_transition.dart';
import 'root_content.dart';
class App extends StatelessWidget {
const App({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
pageTransitionsTheme: PageTransitionsTheme(
builders: {
TargetPlatform.android: FadeUpwardsPageTransitionsBuilder(),
TargetPlatform.iOS: CupertinoPageTransitionsBuilder(),
TargetPlatform.macOS: FadeUpwardsPageTransitionsBuilder(),
TargetPlatform.windows: FadeTransitionsBuilder(),
}
),
appBarTheme: const AppBarTheme(
elevation: 0,
iconTheme: IconThemeData(color: Colors.black),
backgroundColor: Colors.white,
titleTextStyle: TextStyle(
color: Colors.black,
fontSize: 18,
fontWeight: FontWeight.bold,
))),
debugShowCheckedModeBanner: false,
home: AppLayout());
}
}
class AppLayout extends StatelessWidget {
const AppLayout({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: Row(
children: [
SizedBox(
width: 210,
child: MenuPanel(),
),
// Container()
Expanded(child: RootContent())
],
),
// appBar: AppToolBar(),
// body: AppNavigation(),
);
}
}
class MenuPanel extends StatefulWidget {
const MenuPanel({super.key});
@override
State<MenuPanel> createState() => _MenuPanelState();
}
class _MenuPanelState extends State<MenuPanel> {
MenuState state = MenuState(expandMenus: ['/dashboard'], activeMenu: '/dashboard/data_analyse', items: menus);
@override
Widget build(BuildContext context) {
return TolyMenu(state: state, onSelect: _onSelect);
}
void _onSelect(MenuData menu) {
if(menu.isLeaf){
state = state.copyWith(activeMenu: menu.path);
print("menu.path${menu.path}");
goRouter.go(menu.path);
}else{
List<String> menus = [];
String path = menu.path.substring(1);
List<String> parts = path.split('/');
if(parts.isNotEmpty){
String path = '';
for (String part in parts) {
path+='/$part';
menus.add(path);
}
}
if(state.expandMenus.contains(menu.path)){
menus.remove(menu.path);
}
state = state.copyWith(expandMenus: menus);
}
setState(() {
});
}
}

View File

@@ -1,140 +0,0 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:iroute/cases/cases.dart';
import '../color_page.dart';
// GoRouter configuration
final goRouter = GoRouter(
initialLocation: '/manager',
routes: [
GoRoute(
path: '/dashboard',
builder: (_,__)=>SizedBox(),
routes: [
GoRoute(
path: 'data_analyse',
// builder: (context, state) => ColorPage(title: 'data_analyse',),
pageBuilder: (context, state) {
return CustomTransitionPage(
key: state.pageKey,
child: ColorPage(title: 'data_analyse',),
transitionsBuilder: (context, animation, secondaryAnimation, child) {
// Change the opacity of the screen using a Curve based on the the animation's
// value
return FadeTransition(
opacity:
CurveTween(curve: Curves.easeInOutCirc).animate(animation),
child: child,
);
},
);
},
),
GoRoute(
path: 'work_board',
builder: (_,__)=>SizedBox(),
routes: [
GoRoute(
path: 'a',
builder: (context, state) => ColorPage(title: '第一工作区',),
),
GoRoute(
path: 'b',
builder: (context, state) => ColorPage(title: '第二工作区',),
),
GoRoute(
path: 'c',
builder: (context, state) => ColorPage(title: '第三工作区',),
),
]
),
]
),
GoRoute(
path: '/cases',
builder: (_,__)=>SizedBox(),
routes: [
GoRoute(
path: 'counter',
builder: (context, state) => CounterPage(),
),
GoRoute(
path: 'guess',
builder: (context, state) => GuessPage(),
),
GoRoute(
path: 'muyu',
builder: (context, state) => ColorPage(title: '第三工作区',),
), GoRoute(
path: 'canvas',
builder: (context, state) => Paper(),
), GoRoute(
path: 'muyu',
builder: (context, state) => ColorPage(title: '第三工作区',),
),
]
),
GoRoute(
path: '/manager', builder: (_,__)=>SizedBox(),
routes: [
GoRoute(
path: 'account',
builder: (context, state) => ColorPage(title: 'account',),
),
GoRoute(
path: 'role',
builder: (context, state) => ColorPage(title: 'role',),
),
]
),
],
);
class RootContent extends StatelessWidget {
const RootContent({super.key});
@override
Widget build(BuildContext context) {
return Router.withConfig(config: goRouter);
}
}
class RootContentDelegate extends RouterDelegate with ChangeNotifier,PopNavigatorRouterDelegateMixin{
@override
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
@override
Widget build(BuildContext context) {
return Navigator(
key: navigatorKey,
pages: [
],
onPopPage: (route, result) {
// appState.selectedBook = null;
// notifyListeners();
return route.didPop(result);
},
);
}
@override
Future<void> setNewRoutePath(configuration) {
// TODO: implement setNewRoutePath
throw UnimplementedError();
}
}

View File

@@ -1,11 +0,0 @@
import 'package:flutter/material.dart';
class ColorPage extends StatelessWidget {
final String title;
const ColorPage({super.key, required this.title});
@override
Widget build(BuildContext context) {
return Scaffold(body: Center(child: Text(title)));
}
}

View File

@@ -1,58 +0,0 @@
import 'package:flutter/material.dart';
class FadeTransitionsBuilder extends PageTransitionsBuilder {
/// Constructs a page transition animation that slides the page up.
const FadeTransitionsBuilder();
@override
Widget buildTransitions<T>(
PageRoute<T>? route,
BuildContext? context,
Animation<double> animation,
Animation<double>? secondaryAnimation,
Widget child,
) {
return _FadeUpwardsPageTransition(routeAnimation: animation, child: child);
}
}
class _FadeUpwardsPageTransition extends StatelessWidget {
_FadeUpwardsPageTransition({
required Animation<double> routeAnimation, // The route's linear 0.0 - 1.0 animation.
required this.child,
}) : _positionAnimation = routeAnimation.drive(_bottomUpTween.chain(_fastOutSlowInTween)),
_opacityAnimation = routeAnimation.drive(_easeInTween);
// Fractional offset from 1/4 screen below the top to fully on screen.
static final Tween<Offset> _bottomUpTween = Tween<Offset>(
begin: const Offset(0.25,0),
end: Offset.zero,
);
static final Animatable<double> _fastOutSlowInTween = CurveTween(curve: Curves.fastOutSlowIn);
static final Animatable<double> _easeInTween = CurveTween(curve: Curves.easeIn);
final Animation<Offset> _positionAnimation;
final Animation<double> _opacityAnimation;
final Widget child;
@override
Widget build(BuildContext context) {
// return FadeTransition(
// opacity: _opacityAnimation,
// child: child,
// );
return SlideTransition(
position: _positionAnimation,
child: FadeTransition(
opacity: _opacityAnimation,
child: child,
),
);
}
}

View File

@@ -1,15 +0,0 @@
import 'package:flutter/material.dart';
import 'package:url_strategy/url_strategy.dart';
import 'pages/app.dart';
void main() {
setHashUrlStrategy();
runApp(const App());
}

View File

@@ -1,56 +0,0 @@
import 'package:flutter/material.dart';
import '../store/app_state.dart';
import '../route/parser.dart';
import '../route/route_state.dart';
class App extends StatefulWidget {
const App({super.key});
@override
State<App> createState() => _AppState();
}
class _AppState extends State<App> {
late final RootRouterDelegate _delegate;
late final AppRouteParser _parser;
late final AppState _appState;
late final RouteState _routeState;
@override
void initState() {
super.initState();
_parser = AppRouteParser(initialRoute: '/color', allowPaths: [
'/color',
'/color/add',
'/color/detail/:colorHex',
]);
_appState = AppState.initial();
_routeState = RouteState(_parser);
_delegate = RootRouterDelegate(_routeState);
}
@override
Widget build(BuildContext context) {
return AppStateScope(
notifier: _appState,
child: RouteStateScope(
notifier: _routeState,
child: MaterialApp.router(
routerDelegate: _delegate,
routeInformationParser: _parser,
theme: ThemeData(
useMaterial3: true,
appBarTheme: const AppBarTheme(
elevation: 0,
iconTheme: IconThemeData(color: Colors.black),
titleTextStyle: TextStyle(
color: Colors.black,
fontSize: 18,
fontWeight: FontWeight.bold,
))),
debugShowCheckedModeBanner: false,
),
),
);
}
}

View File

@@ -1,67 +0,0 @@
import 'dart:math';
import 'package:flutter/material.dart';
class ColorAddPage extends StatefulWidget {
const ColorAddPage({super.key});
@override
State<ColorAddPage> createState() => _ColorAddPageState();
}
class _ColorAddPageState extends State<ColorAddPage> {
late Color _color;
@override
void initState() {
super.initState();
_color = randomColor;
}
@override
Widget build(BuildContext context) {
String text = '# ${_color.value.toRadixString(16)}';
return Scaffold(
appBar: AppBar(
title: Text('添加颜色'),
actions: [IconButton(onPressed: _selectColor, icon: Icon(Icons.check ))],
),
body: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0,vertical: 20),
child: Row(
children: [
Expanded(child: Text(text,style: TextStyle(color: _color,fontSize: 24,letterSpacing: 4),)),
Container(
margin: EdgeInsets.only(left: 10),
width: 40,
height: 40,
child: Icon(
Icons.sell_outlined,
color: Colors.white,
),
decoration: BoxDecoration(
color: _color,
borderRadius: BorderRadius.circular(8),
),
),
],
),
),
);
}
Random _random = Random();
Color get randomColor {
return Color.fromARGB(
255,
_random.nextInt(256),
_random.nextInt(256),
_random.nextInt(256),
);
}
void _selectColor() {
Navigator.of(context).pop(_color);
}
}

View File

@@ -1,43 +0,0 @@
import 'package:flutter/material.dart';
import '../store/app_state.dart';
import '../route/route_state.dart';
import 'color_add_page.dart';
import '../../../common/components/colors_panel.dart';
import '../../../common/pages/stl_color_page.dart';
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
AppState state = AppStateScope.of(context);
return Scaffold(
appBar: AppBar(title:const Text('颜色主页')),
floatingActionButton: FloatingActionButton(
onPressed: _toAddPage,
child: const Icon(Icons.add),
),
body: ColorsPanel(
colors: state.colors,
onSelect: _selectColor,
),
);
}
void _selectColor(Color color){
String value = '#${color.value.toRadixString(16)}';
RouteStateScope.of(context).update('/color/detail/$value');
}
void _toAddPage() async {
RouteStateScope.of(context).update('/color/add');
}
}

View File

@@ -1,49 +0,0 @@
// 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:collection/collection.dart';
import 'package:quiver/core.dart';
/// A route path that has been parsed by [TemplateRouteParser].
class ParsedRoute {
/// The current path location without query parameters. (/book/123)
final String path;
/// The path template (/book/:id)
final String pathTemplate;
/// The path parameters ({id: 123})
final Map<String, String> parameters;
/// The query parameters ({search: abc})
final Map<String, String> queryParameters;
static const _mapEquality = MapEquality<String, String>();
ParsedRoute(
this.path, this.pathTemplate, this.parameters, this.queryParameters);
@override
bool operator ==(Object other) =>
other is ParsedRoute &&
other.pathTemplate == pathTemplate &&
other.path == path &&
_mapEquality.equals(parameters, other.parameters) &&
_mapEquality.equals(queryParameters, other.queryParameters);
@override
int get hashCode => hash4(
path,
pathTemplate,
_mapEquality.hash(parameters),
_mapEquality.hash(queryParameters),
);
@override
String toString() => '<ParsedRoute '
'template: $pathTemplate '
'path: $path '
'parameters: $parameters '
'query parameters: $queryParameters>';
}

View File

@@ -1,153 +0,0 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:iroute/common/pages/stl_color_page.dart';
import 'package:path_to_regexp/path_to_regexp.dart';
import '../pages/home_page.dart';
import '../pages/color_add_page.dart';
import '../store/app_state.dart';
import 'parsed_route.dart';
import 'route_state.dart';
class AppRouteParser extends RouteInformationParser<ParsedRoute> {
final List<String> allowPaths;
final ParsedRoute initialRoute;
AppRouteParser({
required this.allowPaths,
String initialRoute = '/',
}) : initialRoute = ParsedRoute(initialRoute, initialRoute, {}, {});
@override
Future<ParsedRoute> parseRouteInformation(
RouteInformation routeInformation) async {
print(
"=======parseRouteInformation:${routeInformation.uri.path}===================");
final uri = routeInformation.uri;
final path = uri.toString();
final queryParams = uri.queryParameters;
ParsedRoute parsedRoute = initialRoute;
for (var pathTemplate in allowPaths) {
final parameters = <String>[];
var pathRegExp = pathToRegExp(pathTemplate, parameters: parameters);
if (pathRegExp.hasMatch(path)) {
final match = pathRegExp.matchAsPrefix(path);
if (match == null) continue;
final params = extract(parameters, match);
parsedRoute = ParsedRoute(path, pathTemplate, params, queryParams);
}
}
return parsedRoute;
}
@override
RouteInformation? restoreRouteInformation(ParsedRoute configuration) {
print("=======restoreRouteInformation:${configuration}===================");
return RouteInformation(uri: Uri.parse(configuration.path));
}
}
class RootRouterDelegate extends RouterDelegate<ParsedRoute>
with ChangeNotifier, PopNavigatorRouterDelegateMixin {
final RouteState routeState;
RootRouterDelegate(this.routeState) {
routeState.addListener(notifyListeners);
}
@override
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
@override
ParsedRoute get currentConfiguration {
print("=======currentConfiguration:${routeState.route.path}===================");
return routeState.route;
}
@override
void dispose() {
routeState.removeListener(notifyListeners);
routeState.dispose();
super.dispose();
}
final _addColorKey = const ValueKey('addColor');
final _detailColorKey = const ValueKey('detailColor');
@override
Widget build(BuildContext context) {
final routeState = RouteStateScope.of(context);
List<Page> pages = [];
final String pathTemplate = routeState.route.pathTemplate;
pages.add(MaterialPage(child: HomePage()));
String? selectedColor;
if (pathTemplate == '/color/detail/:colorHex') {
selectedColor = routeState.route.parameters['colorHex'];
}
if (selectedColor != null) {
int value = int.parse(
selectedColor.substring(
1,
),
radix: 16);
pages.add(MaterialPage(
key: _detailColorKey,
child: StlColorPage(
color: Color(value),
)));
}
bool isAddPage = pathTemplate == '/color/add';
if (isAddPage) {
pages.add(
MaterialPage(key: _addColorKey, child: ColorAddPage()),
);
}
print("===build====================");
return Navigator(
key: navigatorKey,
pages: pages,
onPopPage: (route, result) {
print(result);
if (route.settings is Page &&
(route.settings as Page).key == _addColorKey) {
if(result is Color){
AppStateScope.of(context).addColor(result);
}
routeState.update('/color');
}
if (route.settings is Page &&
(route.settings as Page).key == _detailColorKey) {
routeState.update('/color');
}
// appState.selectedBook = null;
// notifyListeners();
return route.didPop(result);
},
);
}
/// 格式: /a /b
@override
Future<void> setNewRoutePath(ParsedRoute configuration) async {
print("===setNewRoutePath===${configuration}=================");
routeState.route = configuration;
return;
}
// @override
// Future<void> setInitialRoutePath( configuration) async{
// _pages = [_pageMap['/']!];
// notifyListeners();
// }
}

View File

@@ -1,48 +0,0 @@
// 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/widgets.dart';
import 'parsed_route.dart';
import 'parser.dart';
/// The current route state. To change the current route, call obtain the state
/// using `RouteStateScope.of(context)` and call `go()`:
///
/// ```
/// RouteStateScope.of(context).go('/book/2');
/// ```
class RouteState extends ChangeNotifier {
final AppRouteParser _parser;
ParsedRoute _route;
RouteState(this._parser) : _route = _parser.initialRoute;
ParsedRoute get route => _route;
set route(ParsedRoute route) {
// Don't notify listeners if the path hasn't changed.
if (_route == route) return;
_route = route;
notifyListeners();
}
Future<void> update(String route) async {
this.route = await _parser
.parseRouteInformation(RouteInformation(uri: Uri.parse(route)));
}
}
/// Provides the current [RouteState] to descendant widgets in the tree.
class RouteStateScope extends InheritedNotifier<RouteState> {
const RouteStateScope({
required super.notifier,
required super.child,
super.key,
});
static RouteState of(BuildContext context) =>
context.dependOnInheritedWidgetOfExactType<RouteStateScope>()!.notifier!;
}

View File

@@ -1,32 +0,0 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class AppState extends ChangeNotifier{
final List<Color> colors;
AppState({required this.colors,});
AppState.initial():colors=[
Colors.red, Colors.black, Colors.blue, Colors.green, Colors.orange,
Colors.pink, Colors.purple, Colors.indigo, Colors.amber, Colors.cyan,
Colors.redAccent, Colors.grey, Colors.blueAccent, Colors.greenAccent, Colors.orangeAccent,
Colors.pinkAccent, Colors.purpleAccent, Colors.indigoAccent, Colors.amberAccent, Colors.cyanAccent,
];
void addColor(Color color){
colors.add(color);
notifyListeners();
}
}
/// Provides the current [RouteState] to descendant widgets in the tree.
class AppStateScope extends InheritedNotifier<AppState> {
const AppStateScope({super.key, required super.child, required super.notifier,});
static AppState of(BuildContext context) =>
context.dependOnInheritedWidgetOfExactType<AppStateScope>()!.notifier!;
}

View File

@@ -1,13 +0,0 @@
import 'package:flutter/material.dart';
import 'pages/app/app.dart';
void main() {
runApp(const App());
}

View File

@@ -1,76 +0,0 @@
import 'package:toly_menu/toly_menu.dart';
List<MenuData> menus = [
MenuData(path: '/dashboard', label: '总览面板', children: [
MenuData(path: '/dashboard/data_analyse', label: '数据分析', deep: 1),
MenuData(path: '/dashboard/work_board', label: '工作台', deep: 1, children: [
MenuData(path: '/dashboard/work_board/a', label: '第一工作区', deep: 2),
MenuData(path: '/dashboard/work_board/b', label: '第二工作区', deep: 2),
MenuData(path: '/dashboard/work_board/c', label: '第三工作区', deep: 2),
]),
]),
MenuData(path: '/manager', label: '系统管理', children: [
MenuData(path: '/manager/account', label: '账号管理', deep: 1),
MenuData(path: '/manager/role', label: '角色管理', deep: 1),
MenuData(path: '/manager/menu', label: '菜单管理', deep: 1),
]),
MenuData(path: '/knowledge', label: '知识库管理', children: [
MenuData(path: '/knowledge/a', label: '语文知识', deep: 1, children: [
MenuData(
path: '/knowledge/a/1',
label: '诗词歌赋',
deep: 2,
),
MenuData(
path: '/knowledge/a/2',
label: '人物故事',
deep: 2,
),
MenuData(
path: '/knowledge/a/3',
label: '名著推荐',
deep: 2,
)
]),
MenuData(
path: '/knowledge/b',
label: '数学知识',
children: [
MenuData(
path: '/knowledge/b/1',
label: '人物故事',
deep: 2,
),
MenuData(
path: '/knowledge/b/2',
label: '数学定理',
deep: 2,
),
MenuData(
path: '/knowledge/b/3',
label: '几何知识',
deep: 2,
),
MenuData(
path: '/knowledge/b/4',
label: '代数知识',
deep: 2,
)
],
deep: 1),
MenuData(
path: '/knowledge/c',
label: '英语知识',
deep: 1,
),
]),
MenuData(path: '/widgets', label: '组件集录', children: [
MenuData(path: '/widgets/stateless', label: '无状态组件', deep: 1),
MenuData(path: '/widgets/stateful', label: '有状态组件', deep: 1),
MenuData(path: '/widgets/single_child', label: '单子渲染组件', deep: 1),
MenuData(path: '/widgets/mutli_child', label: '多子渲染组件', deep: 1),
MenuData(path: '/widgets/sliver', label: '滑片组件', deep: 1),
MenuData(path: '/widgets/proxy', label: '代理组件', deep: 1),
MenuData(path: '/widgets/other', label: '其他组件', deep: 1),
])
];

Some files were not shown because too many files have changed in this diff Show More