This commit is contained in:
toly
2023-09-22 09:15:11 +08:00
parent d456e3c523
commit e95c34018e
132 changed files with 8527 additions and 17 deletions

15
lib/13/02/main.dart Normal file
View File

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

56
lib/13/02/pages/app.dart Normal file
View File

@@ -0,0 +1,56 @@
import 'package:flutter/material.dart';
import 'package:iroute/13/02/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

@@ -0,0 +1,67 @@
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

@@ -0,0 +1,43 @@
import 'package:flutter/material.dart';
import 'package:iroute/13/02/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

@@ -0,0 +1,49 @@
// 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>';
}

153
lib/13/02/route/parser.dart Normal file
View File

@@ -0,0 +1,153 @@
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

@@ -0,0 +1,48 @@
// 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

@@ -0,0 +1,32 @@
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!;
}