10
This commit is contained in:
@@ -1,12 +1,11 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:url_strategy/url_strategy.dart';
|
||||
|
||||
import 'pages/app.dart';
|
||||
import 'pages/app/app.dart';
|
||||
import 'pages/app/app_router_delegate.dart';
|
||||
|
||||
|
||||
AppRouterDelegate router = AppRouterDelegate();
|
||||
|
||||
void main() {
|
||||
setHashUrlStrategy();
|
||||
runApp(const App());
|
||||
}
|
||||
|
||||
|
||||
29
lib/13/01/pages/app/app.dart
Normal file
29
lib/13/01/pages/app/app.dart
Normal file
@@ -0,0 +1,29 @@
|
||||
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: const AppToolBar(),
|
||||
body: Router(routerDelegate: router),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
94
lib/13/01/pages/app/app_router_delegate.dart
Normal file
94
lib/13/01/pages/app/app_router_delegate.dart
Normal file
@@ -0,0 +1,94 @@
|
||||
import 'dart:ffi';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
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 with ChangeNotifier{
|
||||
|
||||
List<String> _value = ['/'];
|
||||
|
||||
List<String> get value => _value;
|
||||
|
||||
set value(List<String> value){
|
||||
_value = value;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Navigator(
|
||||
onPopPage: _onPopPage,
|
||||
pages: _value.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()),
|
||||
};
|
||||
|
||||
@override
|
||||
Future<bool> popRoute() async{
|
||||
print('================');
|
||||
return true;
|
||||
}
|
||||
|
||||
bool _onPopPage(Route route, result) {
|
||||
_value = List.of(_value)..removeLast();
|
||||
notifyListeners();
|
||||
return route.didPop(result);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> setNewRoutePath(configuration) async{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// class AppRouterDelegate extends RouterDelegate<String> with ChangeNotifier, PopNavigatorRouterDelegateMixin {
|
||||
//
|
||||
// List<String> _value = ['/'];
|
||||
//
|
||||
//
|
||||
// List<String> get value => _value;
|
||||
//
|
||||
// set value(List<String> value){
|
||||
// _value = value;
|
||||
// notifyListeners();
|
||||
// }
|
||||
//
|
||||
// @override
|
||||
// Widget build(BuildContext context) {
|
||||
// return Navigator(
|
||||
// onPopPage: _onPopPage,
|
||||
// pages: _value.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()),
|
||||
// };
|
||||
//
|
||||
// bool _onPopPage(Route route, result) {
|
||||
// _value = List.of(_value)..removeLast();
|
||||
// notifyListeners();
|
||||
// return route.didPop(result);
|
||||
// }
|
||||
//
|
||||
// @override
|
||||
// GlobalKey<NavigatorState>? navigatorKey = GlobalKey<NavigatorState>();
|
||||
//
|
||||
// @override
|
||||
// Future<void> setNewRoutePath(String configuration) async{
|
||||
// }
|
||||
// }
|
||||
64
lib/13/01/pages/app/app_tool_bar.dart
Normal file
64
lib/13/01/pages/app/app_tool_bar.dart
Normal file
@@ -0,0 +1,64 @@
|
||||
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.value.join(',');
|
||||
}
|
||||
|
||||
@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.value = value.split(',');
|
||||
}
|
||||
}
|
||||
@@ -1,46 +1,30 @@
|
||||
|
||||
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';
|
||||
import '../main.dart';
|
||||
|
||||
class HomePage extends StatefulWidget {
|
||||
|
||||
class HomePage extends StatelessWidget {
|
||||
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) {
|
||||
const Color bgColor = Color(0xffCCFFCC);
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(title:const Text('颜色主页')),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: _toAddPage,
|
||||
child: const Icon(Icons.add),
|
||||
backgroundColor: bgColor,
|
||||
appBar: AppBar(
|
||||
title: const Text('主页起点'),
|
||||
backgroundColor: bgColor,
|
||||
),
|
||||
body: Center(child: ElevatedButton(
|
||||
onPressed: () => toPageA(context),
|
||||
child: const Text('Push A'),
|
||||
),
|
||||
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');
|
||||
void toPageA(BuildContext context) {
|
||||
router.value = ['/', 'a'];
|
||||
}
|
||||
}
|
||||
|
||||
29
lib/13/01/pages/page_a.dart
Normal file
29
lib/13/01/pages/page_a.dart
Normal file
@@ -0,0 +1,29 @@
|
||||
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'];
|
||||
}
|
||||
|
||||
}
|
||||
32
lib/13/01/pages/page_b.dart
Normal file
32
lib/13/01/pages/page_b.dart
Normal file
@@ -0,0 +1,32 @@
|
||||
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.value = ['/','a','b','c'];
|
||||
}
|
||||
|
||||
}
|
||||
22
lib/13/01/pages/page_c.dart
Normal file
22
lib/13/01/pages/page_c.dart
Normal file
@@ -0,0 +1,22 @@
|
||||
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('到达终点'),
|
||||
));
|
||||
}
|
||||
}
|
||||
46
lib/13/01_/pages/home_page.dart
Normal file
46
lib/13/01_/pages/home_page.dart
Normal file
@@ -0,0 +1,46 @@
|
||||
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');
|
||||
}
|
||||
}
|
||||
15
lib/13/01__/main.dart
Normal file
15
lib/13/01__/main.dart
Normal 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());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
46
lib/13/01__/pages/app.dart
Normal file
46
lib/13/01__/pages/app.dart
Normal file
@@ -0,0 +1,46 @@
|
||||
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,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
46
lib/13/01__/pages/home_page.dart
Normal file
46
lib/13/01__/pages/home_page.dart
Normal file
@@ -0,0 +1,46 @@
|
||||
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');
|
||||
}
|
||||
}
|
||||
21
lib/13/01__/route/parsed_route.dart
Normal file
21
lib/13/01__/route/parsed_route.dart
Normal file
@@ -0,0 +1,21 @@
|
||||
// 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];
|
||||
}
|
||||
119
lib/13/01__/route/parser.dart
Normal file
119
lib/13/01__/route/parser.dart
Normal file
@@ -0,0 +1,119 @@
|
||||
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();
|
||||
// }
|
||||
}
|
||||
48
lib/13/01__/route/route_state.dart
Normal file
48
lib/13/01__/route/route_state.dart
Normal 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,{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!;
|
||||
}
|
||||
15
lib/13/01___/main.dart
Normal file
15
lib/13/01___/main.dart
Normal 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());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
36
lib/13/01___/pages/app.dart
Normal file
36
lib/13/01___/pages/app.dart
Normal file
@@ -0,0 +1,36 @@
|
||||
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,
|
||||
);
|
||||
}
|
||||
}
|
||||
67
lib/13/01___/pages/color_add_page.dart
Normal file
67
lib/13/01___/pages/color_add_page.dart
Normal 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);
|
||||
}
|
||||
}
|
||||
47
lib/13/01___/pages/home_page.dart
Normal file
47
lib/13/01___/pages/home_page.dart
Normal file
@@ -0,0 +1,47 @@
|
||||
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');
|
||||
}
|
||||
}
|
||||
21
lib/13/01___/route/parsed_route.dart
Normal file
21
lib/13/01___/route/parsed_route.dart
Normal file
@@ -0,0 +1,21 @@
|
||||
// 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];
|
||||
}
|
||||
122
lib/13/01___/route/parser.dart
Normal file
122
lib/13/01___/route/parser.dart
Normal file
@@ -0,0 +1,122 @@
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
48
lib/13/01___/route/route_state.dart
Normal file
48
lib/13/01___/route/route_state.dart
Normal 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,{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!;
|
||||
// }
|
||||
14
lib/13/01____/main.dart
Normal file
14
lib/13/01____/main.dart
Normal file
@@ -0,0 +1,14 @@
|
||||
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());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
29
lib/13/01____/pages/app/app.dart
Normal file
29
lib/13/01____/pages/app/app.dart
Normal file
@@ -0,0 +1,29 @@
|
||||
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),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
73
lib/13/01____/pages/app/app_router_delegate.dart
Normal file
73
lib/13/01____/pages/app/app_router_delegate.dart
Normal file
@@ -0,0 +1,73 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
64
lib/13/01____/pages/app/app_tool_bar.dart
Normal file
64
lib/13/01____/pages/app/app_tool_bar.dart
Normal file
@@ -0,0 +1,64 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
30
lib/13/01____/pages/home_page.dart
Normal file
30
lib/13/01____/pages/home_page.dart
Normal file
@@ -0,0 +1,30 @@
|
||||
|
||||
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');
|
||||
}
|
||||
}
|
||||
30
lib/13/01____/pages/page_a.dart
Normal file
30
lib/13/01____/pages/page_a.dart
Normal file
@@ -0,0 +1,30 @@
|
||||
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');
|
||||
}
|
||||
|
||||
}
|
||||
32
lib/13/01____/pages/page_b.dart
Normal file
32
lib/13/01____/pages/page_b.dart
Normal file
@@ -0,0 +1,32 @@
|
||||
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');
|
||||
}
|
||||
|
||||
}
|
||||
24
lib/13/01____/pages/page_c.dart
Normal file
24
lib/13/01____/pages/page_c.dart
Normal file
@@ -0,0 +1,24 @@
|
||||
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('到达终点'),
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
15
lib/13/02__/main.dart
Normal file
15
lib/13/02__/main.dart
Normal 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());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:iroute/13/02/store/app_state.dart';
|
||||
import '../store/app_state.dart';
|
||||
import '../route/parser.dart';
|
||||
import '../route/route_state.dart';
|
||||
|
||||
67
lib/13/02__/pages/color_add_page.dart
Normal file
67
lib/13/02__/pages/color_add_page.dart
Normal 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);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:iroute/13/02/store/app_state.dart';
|
||||
import '../store/app_state.dart';
|
||||
import '../route/route_state.dart';
|
||||
import 'color_add_page.dart';
|
||||
|
||||
13
lib/13/go_color/main.dart
Normal file
13
lib/13/go_color/main.dart
Normal file
@@ -0,0 +1,13 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:url_strategy/url_strategy.dart';
|
||||
|
||||
import 'pages/app.dart';
|
||||
|
||||
void main() {
|
||||
setHashUrlStrategy();
|
||||
runApp(const App());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
50
lib/13/go_color/pages/app.dart
Normal file
50
lib/13/go_color/pages/app.dart
Normal file
@@ -0,0 +1,50 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:iroute/common/pages/stl_color_page.dart';
|
||||
import '../route/parser.dart';
|
||||
import 'home_page.dart';
|
||||
import 'color_add_page.dart';
|
||||
|
||||
class App extends StatefulWidget {
|
||||
const App({super.key});
|
||||
|
||||
@override
|
||||
State<App> createState() => _AppState();
|
||||
}
|
||||
|
||||
class _AppState extends State<App> {
|
||||
|
||||
GoRouter router = GoRouter(
|
||||
initialLocation: '/color',
|
||||
routes: <GoRoute>[
|
||||
GoRoute(path: '/color',builder: (ctx,state)=>HomePage()),
|
||||
GoRoute(path: '/color/detail',builder: (ctx,state) {
|
||||
String selectedColor = state.uri.queryParameters['color']??'';
|
||||
return StlColorPage(
|
||||
color: Color(int.parse(selectedColor,radix: 16)),
|
||||
);
|
||||
}),
|
||||
GoRoute(path: '/color/add',builder: (ctx,state)=>ColorAddPage()),
|
||||
]
|
||||
|
||||
);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp.router(
|
||||
routerConfig: router,
|
||||
// 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,
|
||||
);
|
||||
}
|
||||
}
|
||||
67
lib/13/go_color/pages/color_add_page.dart
Normal file
67
lib/13/go_color/pages/color_add_page.dart
Normal 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);
|
||||
}
|
||||
}
|
||||
61
lib/13/go_color/pages/home_page.dart
Normal file
61
lib/13/go_color/pages/home_page.dart
Normal file
@@ -0,0 +1,61 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.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
|
||||
void dispose() {
|
||||
print('_HomePageState#dispose');
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@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);
|
||||
context.push('/color/detail?color=$value');
|
||||
context.go('/color/detail?color=$value');
|
||||
// routerDelegate.go('/color/detail?color=$value');
|
||||
}
|
||||
|
||||
void _toAddPage() async {
|
||||
Color? color = await context.push<Color?>('/color/add');
|
||||
if (color != null) {
|
||||
setState(() {
|
||||
_colors.add(color);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
21
lib/13/go_color/route/parsed_route.dart
Normal file
21
lib/13/go_color/route/parsed_route.dart
Normal file
@@ -0,0 +1,21 @@
|
||||
// // 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];
|
||||
// }
|
||||
112
lib/13/go_color/route/parser.dart
Normal file
112
lib/13/go_color/route/parser.dart
Normal file
@@ -0,0 +1,112 @@
|
||||
// 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));
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// ValueNotifier<List<String>> router = ValueNotifier(['/']);
|
||||
//
|
||||
// class AppRouterDelegate extends RouterDelegate<ParsedRoute>
|
||||
// with ChangeNotifier, PopNavigatorRouterDelegateMixin {
|
||||
//
|
||||
//
|
||||
// AppRouterDelegate({String initial='/'}) : _route = ParsedRoute(initial,{});
|
||||
//
|
||||
// late ParsedRoute _route;
|
||||
//
|
||||
// @override
|
||||
// final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
|
||||
//
|
||||
// @override
|
||||
// ParsedRoute get currentConfiguration {
|
||||
// return _route;
|
||||
// }
|
||||
//
|
||||
// Future<void> go(String route) async {
|
||||
// _route = await parser.parseRouteInformation(RouteInformation(uri: Uri.parse(route)));
|
||||
// notifyListeners();
|
||||
// }
|
||||
//
|
||||
// @override
|
||||
// void dispose() {
|
||||
// super.dispose();
|
||||
// }
|
||||
//
|
||||
// final _addColorKey = const ValueKey('addColor');
|
||||
//
|
||||
// @override
|
||||
// Widget build(BuildContext context) {
|
||||
//
|
||||
// List<Page> pages =[];
|
||||
// final String path = _route.path;
|
||||
//
|
||||
// pages.add(MaterialPage(child: HomePage()));
|
||||
//
|
||||
// String? selectedColor;
|
||||
// if (path.startsWith('/color/detail') ) {
|
||||
// selectedColor = _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) {
|
||||
// go('/');
|
||||
// }
|
||||
//
|
||||
// if(selectedColor!=null){
|
||||
// selectedColor = null;
|
||||
// go('/');
|
||||
// }
|
||||
// return route.didPop(result);
|
||||
// },
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// @override
|
||||
// Future<void> setNewRoutePath(ParsedRoute configuration) async {
|
||||
// print("===setNewRoutePath===${configuration}=================");
|
||||
// _route = configuration;
|
||||
// }
|
||||
//
|
||||
// }
|
||||
48
lib/13/go_color/route/route_state.dart
Normal file
48
lib/13/go_color/route/route_state.dart
Normal 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,{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!;
|
||||
// // }
|
||||
Reference in New Issue
Block a user