9
This commit is contained in:
@@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
|
|||||||
|
|
||||||
import 'pages/page_a.dart';
|
import 'pages/page_a.dart';
|
||||||
import 'pages/page_b.dart';
|
import 'pages/page_b.dart';
|
||||||
import 'pages/page_c.dart';
|
import 'pages/home_page.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
runApp(const MyApp());
|
runApp(const MyApp());
|
||||||
@@ -23,25 +23,26 @@ class MyApp extends StatelessWidget {
|
|||||||
titleTextStyle: TextStyle(color: Colors.black,fontSize: 18,fontWeight: FontWeight.bold)
|
titleTextStyle: TextStyle(color: Colors.black,fontSize: 18,fontWeight: FontWeight.bold)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
home: const PageA(),
|
initialRoute: '/a/b',
|
||||||
onUnknownRoute: _onUnknownRoute,
|
onGenerateRoute: _onGenerateRoute,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Route? _onUnknownRoute(RouteSettings settings) {
|
Route? _onGenerateRoute(RouteSettings settings) {
|
||||||
String? name = settings.name;
|
String? name = settings.name;
|
||||||
Widget? page ;
|
Widget? page ;
|
||||||
|
if(name=='/'){
|
||||||
|
page = const HomePage();
|
||||||
|
}
|
||||||
if(name=='/a'){
|
if(name=='/a'){
|
||||||
page = const PageA();
|
page = const PageA();
|
||||||
}
|
}
|
||||||
if(name=='/b'){
|
if(name=='/a/b'){
|
||||||
page = const PageB();
|
page = const PageB();
|
||||||
}
|
}
|
||||||
if(name=='/c'){
|
|
||||||
page = const PageC();
|
|
||||||
}
|
|
||||||
if(page!=null){
|
if(page!=null){
|
||||||
return MaterialPageRoute(builder: (_)=> const PageB());
|
return MaterialPageRoute(builder: (_)=> page!,settings: settings);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
28
lib/06/02/pages/home_page.dart
Normal file
28
lib/06/02/pages/home_page.dart
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class HomePage extends StatelessWidget {
|
||||||
|
const HomePage({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
const Color bgColor = Color(0xffFFE6CD);
|
||||||
|
|
||||||
|
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){
|
||||||
|
Navigator.of(context).pushNamed('/a');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'page_c.dart';
|
import 'home_page.dart';
|
||||||
|
|
||||||
class PageB extends StatelessWidget {
|
class PageB extends StatelessWidget {
|
||||||
const PageB({super.key});
|
const PageB({super.key});
|
||||||
@@ -17,13 +17,13 @@ class PageB extends StatelessWidget {
|
|||||||
body: Center(
|
body: Center(
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
onPressed: ()=>toPageC(context),
|
onPressed: ()=>toPageC(context),
|
||||||
child: const Text('Push C'),
|
child: const Text('回到主界面'),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void toPageC(BuildContext context){
|
void toPageC(BuildContext context){
|
||||||
Navigator.of(context).push(MaterialPageRoute(builder: (_)=> const PageC()));
|
Navigator.of(context).popUntil(ModalRoute.withName('/'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -23,6 +23,6 @@ class PageA extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void toPageB(BuildContext context){
|
void toPageB(BuildContext context){
|
||||||
Navigator.of(context).pushNamed('/a');
|
Navigator.of(context).pushNamed('/b');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
5
lib/08/节点介绍.txt
Normal file
5
lib/08/节点介绍.txt
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
01: 分析 pushReplacement 方法。
|
||||||
|
A、B、C 三个界面跳转。
|
||||||
|
|
||||||
|
02: 分析 pushAndRemoveUntil 方法。
|
||||||
|
A、B、C、D 四个界面跳转。
|
||||||
27
lib/09/01/main.dart
Normal file
27
lib/09/01/main.dart
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'pages/page_a.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
runApp(const MyApp());
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyApp extends StatelessWidget {
|
||||||
|
const MyApp({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return MaterialApp(
|
||||||
|
title: 'Flutter Demo',
|
||||||
|
debugShowCheckedModeBanner: false,
|
||||||
|
theme: ThemeData(
|
||||||
|
appBarTheme: AppBarTheme(
|
||||||
|
elevation: 0,
|
||||||
|
iconTheme: IconThemeData(color: Colors.black),
|
||||||
|
titleTextStyle: TextStyle(color: Colors.black,fontSize: 18,fontWeight: FontWeight.bold)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
home: const PageA(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
28
lib/09/01/pages/page_a.dart
Normal file
28
lib/09/01/pages/page_a.dart
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'page_b.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){
|
||||||
|
Navigator.of(context).push(MaterialPageRoute(builder: (_)=> const PageB()));
|
||||||
|
}
|
||||||
|
}
|
||||||
29
lib/09/01/pages/page_b.dart
Normal file
29
lib/09/01/pages/page_b.dart
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'page_c.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){
|
||||||
|
Navigator.of(context).push(MaterialPageRoute(builder: (_)=> const PageC()));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,6 +12,11 @@ class PageC extends StatelessWidget {
|
|||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text('C'),
|
title: const Text('C'),
|
||||||
backgroundColor: bgColor,
|
backgroundColor: bgColor,
|
||||||
|
leading: BackButton(
|
||||||
|
onPressed: (){
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
body: const Center(
|
body: const Center(
|
||||||
child: Text('到达终点'),
|
child: Text('到达终点'),
|
||||||
50
lib/09/02/main.dart
Normal file
50
lib/09/02/main.dart
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'pages/page_a.dart';
|
||||||
|
import 'pages/page_b.dart';
|
||||||
|
import 'pages/page_c.dart';
|
||||||
|
import 'pages/home_page.dart';
|
||||||
|
void main() {
|
||||||
|
runApp(const MyApp());
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyApp extends StatelessWidget {
|
||||||
|
const MyApp({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return MaterialApp(
|
||||||
|
title: 'Flutter Demo',
|
||||||
|
debugShowCheckedModeBanner: false,
|
||||||
|
theme: ThemeData(
|
||||||
|
appBarTheme: AppBarTheme(
|
||||||
|
elevation: 0,
|
||||||
|
iconTheme: IconThemeData(color: Colors.black),
|
||||||
|
titleTextStyle: TextStyle(color: Colors.black,fontSize: 18,fontWeight: FontWeight.bold)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
onUnknownRoute: _onUnknownRoute,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Route? _onUnknownRoute(RouteSettings settings) {
|
||||||
|
String? name = settings.name;
|
||||||
|
Widget? page ;
|
||||||
|
if(name=='/'){
|
||||||
|
page = const HomePage();
|
||||||
|
}
|
||||||
|
if(name=='/a'){
|
||||||
|
page = const PageA();
|
||||||
|
}
|
||||||
|
if(name=='/b'){
|
||||||
|
page = const PageB();
|
||||||
|
}
|
||||||
|
if(name=='/c'){
|
||||||
|
page = const PageC();
|
||||||
|
}
|
||||||
|
if(page!=null){
|
||||||
|
return MaterialPageRoute(builder: (_)=> page!,settings: settings);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
29
lib/09/02/pages/home_page.dart
Normal file
29
lib/09/02/pages/home_page.dart
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:iroute/06/02/pages/page_a.dart';
|
||||||
|
|
||||||
|
class HomePage extends StatelessWidget {
|
||||||
|
const HomePage({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
const Color bgColor = Color(0xffFFCCFF);
|
||||||
|
|
||||||
|
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){
|
||||||
|
Navigator.of(context).pushNamed('/a');
|
||||||
|
}
|
||||||
|
}
|
||||||
28
lib/09/02/pages/page_a.dart
Normal file
28
lib/09/02/pages/page_a.dart
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'page_b.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){
|
||||||
|
Navigator.of(context).pushNamed('/b');
|
||||||
|
}
|
||||||
|
}
|
||||||
29
lib/09/02/pages/page_b.dart
Normal file
29
lib/09/02/pages/page_b.dart
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'page_c.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){
|
||||||
|
Navigator.of(context).pushNamed('/c');
|
||||||
|
}
|
||||||
|
}
|
||||||
34
lib/09/02/pages/page_c.dart
Normal file
34
lib/09/02/pages/page_c.dart
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
|
||||||
|
class PageC extends StatelessWidget {
|
||||||
|
const PageC({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
const Color bgColor = Color(0xffFFE6CD);
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: bgColor,
|
||||||
|
appBar: AppBar(
|
||||||
|
title: const Text('C'),
|
||||||
|
backgroundColor: bgColor,
|
||||||
|
),
|
||||||
|
body: Center(
|
||||||
|
child: ElevatedButton(
|
||||||
|
onPressed: ()=>toPageD(context),
|
||||||
|
child: const Text('pop Until A'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void toPageD(BuildContext context){
|
||||||
|
Navigator.of(context).popUntil(
|
||||||
|
ModalRoute.withName('/a')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
11
lib/12/01/main.dart
Normal file
11
lib/12/01/main.dart
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'pages/app/app.dart';
|
||||||
|
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
runApp(const App());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
28
lib/12/01/pages/app/app.dart
Normal file
28
lib/12/01/pages/app/app.dart
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'app_navigation.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: const Scaffold(
|
||||||
|
appBar: AppToolBar(),
|
||||||
|
body: AppNavigation(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
50
lib/12/01/pages/app/app_navigation.dart
Normal file
50
lib/12/01/pages/app/app_navigation.dart
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import '../page_a.dart';
|
||||||
|
import '../page_b.dart';
|
||||||
|
import '../page_c.dart';
|
||||||
|
import '../home_page.dart';
|
||||||
|
|
||||||
|
ValueNotifier<List<String>> router = ValueNotifier(['/']);
|
||||||
|
|
||||||
|
class AppNavigation extends StatefulWidget {
|
||||||
|
const AppNavigation({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<AppNavigation> createState() => _AppNavigationState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _AppNavigationState extends State<AppNavigation> {
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
router.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ValueListenableBuilder(
|
||||||
|
valueListenable: router,
|
||||||
|
builder: (_, List<String> value, __) => buildNavigatorByConfig(value),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Map<String, Page> _pageMap = const {
|
||||||
|
'/': MaterialPage(child: HomePage()),
|
||||||
|
'a': MaterialPage(child: PageA()),
|
||||||
|
'b': MaterialPage(child: PageB()),
|
||||||
|
'c': MaterialPage(child: PageC()),
|
||||||
|
};
|
||||||
|
|
||||||
|
Widget buildNavigatorByConfig(List<String> value) {
|
||||||
|
return Navigator(
|
||||||
|
onPopPage: _onPopPage,
|
||||||
|
pages: router.value.map((e) => _pageMap[e]!).toList(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _onPopPage(Route route, result) {
|
||||||
|
return route.didPop(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
64
lib/12/01/pages/app/app_tool_bar.dart
Normal file
64
lib/12/01/pages/app/app_tool_bar.dart
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'app_navigation.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(',');
|
||||||
|
}
|
||||||
|
}
|
||||||
29
lib/12/01/pages/home_page.dart
Normal file
29
lib/12/01/pages/home_page.dart
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'app/app_navigation.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.value = ['/', 'a'];
|
||||||
|
}
|
||||||
|
}
|
||||||
29
lib/12/01/pages/page_a.dart
Normal file
29
lib/12/01/pages/page_a.dart
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'app/app_navigation.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'];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
39
lib/12/01/pages/page_b.dart
Normal file
39
lib/12/01/pages/page_b.dart
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'app/app_navigation.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,
|
||||||
|
leading: BackButton(
|
||||||
|
onPressed: _pop,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
body: Center(
|
||||||
|
child: ElevatedButton(
|
||||||
|
onPressed: () => toPageC(context),
|
||||||
|
child: const Text('Push C'),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void toPageC(BuildContext context){
|
||||||
|
router.value = ['/','a','b','c'];
|
||||||
|
}
|
||||||
|
|
||||||
|
void _pop() {
|
||||||
|
router.value = List.of(router.value)..removeLast();
|
||||||
|
}
|
||||||
|
}
|
||||||
29
lib/12/01/pages/page_c.dart
Normal file
29
lib/12/01/pages/page_c.dart
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'app/app_navigation.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,
|
||||||
|
leading: BackButton(
|
||||||
|
onPressed: _pop,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
body: Center(
|
||||||
|
child: Text('到达终点'),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
void _pop() {
|
||||||
|
router.value = List.of(router.value)..removeLast();
|
||||||
|
}
|
||||||
|
}
|
||||||
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
50
lib/13/01/pages/app.dart
Normal file
50
lib/13/01/pages/app.dart
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
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,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
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');
|
||||||
|
}
|
||||||
|
}
|
||||||
27
lib/13/01/route/parsed_route.dart
Normal file
27
lib/13/01/route/parsed_route.dart
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
// 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];
|
||||||
|
}
|
||||||
135
lib/13/01/route/parser.dart
Normal file
135
lib/13/01/route/parser.dart
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
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();
|
||||||
|
// }
|
||||||
|
}
|
||||||
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) : _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!;
|
||||||
|
}
|
||||||
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
56
lib/13/02/pages/app.dart
Normal file
56
lib/13/02/pages/app.dart
Normal 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,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
43
lib/13/02/pages/home_page.dart
Normal file
43
lib/13/02/pages/home_page.dart
Normal 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');
|
||||||
|
}
|
||||||
|
}
|
||||||
49
lib/13/02/route/parsed_route.dart
Normal file
49
lib/13/02/route/parsed_route.dart
Normal 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
153
lib/13/02/route/parser.dart
Normal 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();
|
||||||
|
// }
|
||||||
|
}
|
||||||
48
lib/13/02/route/route_state.dart
Normal file
48
lib/13/02/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) : _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!;
|
||||||
|
}
|
||||||
32
lib/13/02/store/app_state.dart
Normal file
32
lib/13/02/store/app_state.dart
Normal 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!;
|
||||||
|
}
|
||||||
13
lib/13/02_/main.dart
Normal file
13
lib/13/02_/main.dart
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'pages/app/app.dart';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
runApp(const App());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
83
lib/13/02_/menus.dart
Normal file
83
lib/13/02_/menus.dart
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
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),
|
||||||
|
])
|
||||||
|
];
|
||||||
107
lib/13/02_/pages/app/app.dart
Normal file
107
lib/13/02_/pages/app/app.dart
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
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(() {
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
140
lib/13/02_/pages/app/root_content.dart
Normal file
140
lib/13/02_/pages/app/root_content.dart
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
11
lib/13/02_/pages/color_page.dart
Normal file
11
lib/13/02_/pages/color_page.dart
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
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)));
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user