。
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
import 'pages/app/app.dart';
|
||||
import 'pages/app/app_router_delegate.dart';
|
||||
|
||||
|
||||
@@ -1,210 +0,0 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:iroute/13/04/app/navigation/router/iroute.dart';
|
||||
import 'package:iroute/common/pages/stl_color_page.dart';
|
||||
|
||||
import '../../../pages/color/color_detail_page.dart';
|
||||
import '../../../pages/color/color_page.dart';
|
||||
import '../../../pages/empty/empty_page.dart';
|
||||
import '../../../pages/settings/settings_page.dart';
|
||||
import '../../../pages/counter/counter_page.dart';
|
||||
import '../../../pages/sort/sort_page.dart';
|
||||
import '../../../pages/user/user_page.dart';
|
||||
import '../../../transition/fade_transition_page.dart';
|
||||
import '../../../pages/color/color_add_page.dart';
|
||||
|
||||
const List<String> kDestinationsPaths = [
|
||||
'/color',
|
||||
'/counter',
|
||||
'/user',
|
||||
'/settings',
|
||||
];
|
||||
|
||||
AppRouterDelegate router = AppRouterDelegate();
|
||||
|
||||
class AppRouterDelegate extends RouterDelegate<Object> with ChangeNotifier {
|
||||
String _path = '/color';
|
||||
|
||||
String get path => _path;
|
||||
|
||||
int? get activeIndex {
|
||||
if(path.startsWith('/color')) return 0;
|
||||
if(path.startsWith('/counter')) return 1;
|
||||
if(path.startsWith('/user')) return 2;
|
||||
if(path.startsWith('/settings')) return 3;
|
||||
return null;
|
||||
}
|
||||
|
||||
final Map<String,Completer<dynamic>> _completerMap = {};
|
||||
|
||||
Completer<dynamic>? completer;
|
||||
|
||||
Future<dynamic> changePathForResult(String value) async{
|
||||
Completer<dynamic> completer = Completer();
|
||||
_completerMap[value] = completer;
|
||||
path = value;
|
||||
return completer.future;
|
||||
}
|
||||
|
||||
set path(String value) {
|
||||
if (_path == value) return;
|
||||
_path = value;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
// IRoute? parserPath(String path){
|
||||
//
|
||||
// List<String> parts = path.split('/');
|
||||
// String lever1 = '/${parts[1]}';
|
||||
// List<IRoute> iRoutes = kDestinationsIRoutes.where((e) => e.path == lever1).toList();
|
||||
//
|
||||
// int counter = 2;
|
||||
//
|
||||
// IRoute? result;
|
||||
// String check = lever1;
|
||||
// for(int i = 0;i<iRoutes.length;i++){
|
||||
// check = check +"/" + parts[counter];
|
||||
// String path = iRoutes[i].path;
|
||||
// if(path == check){
|
||||
// result = iRoutes[i];
|
||||
// break;
|
||||
// }
|
||||
// // String path =
|
||||
// // result.children.add(IRoute(path: parts[i]);
|
||||
// }
|
||||
// }
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Navigator(
|
||||
onPopPage: _onPopPage,
|
||||
pages: _buildPageByPath(path),
|
||||
);
|
||||
}
|
||||
|
||||
List<Page> _buildPageByPath(String path) {
|
||||
if(path.startsWith('/color')){
|
||||
return buildColorPages(path);
|
||||
}
|
||||
|
||||
Widget? child;
|
||||
if (path == kDestinationsPaths[1]) {
|
||||
child = const CounterPage();
|
||||
}
|
||||
if (path == kDestinationsPaths[2]) {
|
||||
child = const SortPage();
|
||||
}
|
||||
if (path == kDestinationsPaths[3]) {
|
||||
child = const SettingPage();
|
||||
}
|
||||
return [
|
||||
FadeTransitionPage(
|
||||
key: ValueKey(path),
|
||||
child: child ?? const EmptyPage(),
|
||||
)
|
||||
];
|
||||
}
|
||||
|
||||
List<Page> buildColorPages(String path){
|
||||
List<Page> result = [];
|
||||
Uri uri = Uri.parse(path);
|
||||
for (String segment in uri.pathSegments) {
|
||||
if(segment == 'color'){
|
||||
result.add( const FadeTransitionPage(
|
||||
key: ValueKey('/color'),
|
||||
child:ColorPage(),
|
||||
));
|
||||
}
|
||||
if(segment =='detail'){
|
||||
final Map<String, String> queryParams = uri.queryParameters;
|
||||
String? selectedColor = queryParams['color'];
|
||||
if (selectedColor != null) {
|
||||
Color color = Color(int.parse(selectedColor, radix: 16));
|
||||
result.add( FadeTransitionPage(
|
||||
key: const ValueKey('/color/detail'),
|
||||
child:ColorDetailPage(color: color),
|
||||
));
|
||||
}
|
||||
}
|
||||
if(segment == 'add'){
|
||||
result.add( const FadeTransitionPage(
|
||||
key: ValueKey('/color/add'),
|
||||
child:ColorAddPage(),
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> popRoute() async {
|
||||
print('=======popRoute=========');
|
||||
return true;
|
||||
}
|
||||
|
||||
bool _onPopPage(Route route, result) {
|
||||
if(_completerMap.containsKey(path)){
|
||||
_completerMap[path]?.complete(result);
|
||||
_completerMap.remove(path);
|
||||
}
|
||||
|
||||
path = backPath(path);
|
||||
return route.didPop(result);
|
||||
}
|
||||
|
||||
String backPath(String path){
|
||||
Uri uri = Uri.parse(path);
|
||||
if(uri.pathSegments.length==1) return path;
|
||||
List<String> parts = List.of(uri.pathSegments)..removeLast();
|
||||
return '/${parts.join('/')}';
|
||||
}
|
||||
|
||||
@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{
|
||||
// }
|
||||
// }
|
||||
@@ -1,37 +0,0 @@
|
||||
class IRoute {
|
||||
final String path;
|
||||
final List<IRoute> children;
|
||||
|
||||
const IRoute({required this.path, this.children = const []});
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'IRoute{path: $path, children: $children}';
|
||||
}
|
||||
|
||||
List<String> list(){
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
const List<IRoute> kDestinationsIRoutes = [
|
||||
IRoute(
|
||||
path: '/color',
|
||||
children: [
|
||||
IRoute(path: '/color/add'),
|
||||
IRoute(path: '/color/detail'),
|
||||
],
|
||||
),
|
||||
IRoute(
|
||||
path: '/counter',
|
||||
),
|
||||
IRoute(
|
||||
path: '/user',
|
||||
),
|
||||
IRoute(
|
||||
path: '/settings',
|
||||
),
|
||||
];
|
||||
@@ -1,39 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../router/app_router_delegate.dart';
|
||||
import 'app_navigation_rail.dart';
|
||||
import 'background.dart';
|
||||
import 'top_bar.dart';
|
||||
|
||||
class AppNavigation extends StatelessWidget {
|
||||
const AppNavigation({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: Stack(
|
||||
children: [
|
||||
// const Background(),
|
||||
Row(
|
||||
children: [
|
||||
const AppNavigationRail(),
|
||||
Expanded(
|
||||
child: Column(
|
||||
children: [
|
||||
TopBar(),
|
||||
Divider(height: 1,),
|
||||
Expanded(
|
||||
child: Router(
|
||||
routerDelegate: router,
|
||||
backButtonDispatcher: RootBackButtonDispatcher(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../../components/tolyui/navigation/toly_navigation_rail.dart';
|
||||
import '../router/app_router_delegate.dart';
|
||||
|
||||
class AppNavigationRail extends StatefulWidget {
|
||||
const AppNavigationRail({super.key});
|
||||
|
||||
@override
|
||||
State<AppNavigationRail> createState() => _AppNavigationRailState();
|
||||
}
|
||||
|
||||
class _AppNavigationRailState extends State<AppNavigationRail> {
|
||||
final List<NavigationRailDestination> destinations = const [
|
||||
NavigationRailDestination(icon: Icon(Icons.color_lens_outlined), label: Text("颜色板")),
|
||||
NavigationRailDestination(icon: Icon(Icons.add_chart), label: Text("计数器")),
|
||||
NavigationRailDestination(icon: Icon(Icons.person), label: Text("我的")),
|
||||
NavigationRailDestination(icon: Icon(Icons.settings), label: Text("设置")),
|
||||
];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
router.addListener(_onRouterChange);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
router.removeListener(_onRouterChange);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return TolyNavigationRail(
|
||||
leading: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 18.0),
|
||||
child: FlutterLogo(),
|
||||
),
|
||||
backgroundColor: const Color(0xff3975c6),
|
||||
onDestinationSelected: _onDestinationSelected,
|
||||
selectedIndex: router.activeIndex,
|
||||
);
|
||||
|
||||
// return NavigationRail(
|
||||
// backgroundColor: Colors.transparent,
|
||||
// labelType: NavigationRailLabelType.all,
|
||||
// onDestinationSelected: _onDestinationSelected,
|
||||
// destinations: destinations,
|
||||
// selectedIndex: router.activeIndex,
|
||||
// );
|
||||
}
|
||||
|
||||
void _onDestinationSelected(int index) {
|
||||
router.path = kDestinationsPaths[index];
|
||||
}
|
||||
|
||||
void _onRouterChange() {
|
||||
setState(() {});
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class Background extends StatelessWidget {
|
||||
const Background({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
decoration: const BoxDecoration(
|
||||
gradient:
|
||||
LinearGradient(transform: GradientRotation(pi / 2), colors: [
|
||||
Color(0xffF1EFF1),
|
||||
Color(0xffFFFFFF),
|
||||
])),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../router/app_router_delegate.dart';
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
|
||||
import '../../../components/tolyui/navigation/toly_breadcrumb.dart';
|
||||
import '../../../components/windows/window_buttons.dart';
|
||||
|
||||
class TopBar extends StatelessWidget {
|
||||
const TopBar({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DragToMoveAreaNoDouble(
|
||||
child: Container(
|
||||
alignment: Alignment.center,
|
||||
height: 46,
|
||||
child: Row(
|
||||
children: [
|
||||
const SizedBox(
|
||||
width: 16,
|
||||
),
|
||||
RouterIndicator(),
|
||||
Spacer(),
|
||||
WindowButtons()
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class RouterIndicator extends StatefulWidget {
|
||||
const RouterIndicator({super.key});
|
||||
|
||||
@override
|
||||
State<RouterIndicator> createState() => _RouterIndicatorState();
|
||||
}
|
||||
|
||||
class _RouterIndicatorState extends State<RouterIndicator> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
router.addListener(_onRouterChange);
|
||||
}
|
||||
|
||||
Map<String, String> routeLabelMap = {
|
||||
'/color': '颜色板',
|
||||
'/color/add': '添加颜色',
|
||||
'/color/detail': '颜色详情',
|
||||
'/counter': '计数器',
|
||||
'/user': '我的',
|
||||
'/settings': '系统设置',
|
||||
};
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return TolyBreadcrumb(
|
||||
items: pathToBreadcrumbItems(router.path),
|
||||
onTapItem: (item){
|
||||
if(item.to!=null){
|
||||
router.path = item.to!;
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void _onRouterChange() {
|
||||
print('_onRouterChange');
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
List<BreadcrumbItem> pathToBreadcrumbItems(String path) {
|
||||
Uri uri = Uri.parse(path);
|
||||
List<BreadcrumbItem> result = [];
|
||||
String to = '';
|
||||
|
||||
String distPath = '';
|
||||
for (String segment in uri.pathSegments) {
|
||||
distPath += '/$segment';
|
||||
}
|
||||
|
||||
for (String segment in uri.pathSegments) {
|
||||
to += '/$segment';
|
||||
result.add(BreadcrumbItem(to: to, label: routeLabelMap[to] ?? '未知路由',active: to==distPath));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
class DragToMoveAreaNoDouble extends StatelessWidget {
|
||||
final Widget child;
|
||||
|
||||
const DragToMoveAreaNoDouble({
|
||||
Key? key,
|
||||
required this.child,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
behavior: HitTestBehavior.translucent,
|
||||
onPanStart: (details) {
|
||||
windowManager.startDragging();
|
||||
},
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'navigation/router/app_router_delegate.dart';
|
||||
import 'navigation/views/app_navigation.dart';
|
||||
import 'navigation/views/app_navigation_rail.dart';
|
||||
|
||||
class UnitApp extends StatelessWidget {
|
||||
const UnitApp({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
return MaterialApp(
|
||||
theme: ThemeData(
|
||||
fontFamily: "宋体",
|
||||
appBarTheme: const AppBarTheme(
|
||||
elevation: 0,
|
||||
iconTheme: IconThemeData(color: Colors.black),
|
||||
titleTextStyle: TextStyle(
|
||||
color: Colors.black,
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
))),
|
||||
debugShowCheckedModeBanner: false,
|
||||
home: AppNavigation());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
|
||||
class MenuMeta {
|
||||
// 标签
|
||||
final String label;
|
||||
|
||||
// 图标数据
|
||||
final IconData icon;
|
||||
|
||||
// 图标颜色
|
||||
final Color? color;
|
||||
|
||||
const MenuMeta({
|
||||
required this.label,
|
||||
required this.icon,
|
||||
this.color,
|
||||
});
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/src/gestures/events.dart';
|
||||
|
||||
class TolyBreadcrumb extends StatelessWidget {
|
||||
final List<BreadcrumbItem> items;
|
||||
final ValueChanged<BreadcrumbItem>? onTapItem;
|
||||
|
||||
const TolyBreadcrumb({super.key, required this.items, this.onTapItem});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
List<Widget> children = [];
|
||||
|
||||
for (int i = 0; i < items.length; i++) {
|
||||
children.add(TolyBreadcrumbItem(
|
||||
item: items[i], onTapItem: onTapItem,
|
||||
));
|
||||
if (i != items.length - 1) {
|
||||
children.add(Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 4.0),
|
||||
child: Text(
|
||||
'/',
|
||||
style: TextStyle(color: Colors.grey),
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
return Wrap(
|
||||
children: children,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class TolyBreadcrumbItem extends StatefulWidget {
|
||||
final BreadcrumbItem item;
|
||||
final ValueChanged<BreadcrumbItem>? onTapItem;
|
||||
const TolyBreadcrumbItem({super.key, required this.item, required this.onTapItem});
|
||||
|
||||
@override
|
||||
State<TolyBreadcrumbItem> createState() => _TolyBreadcrumbItemState();
|
||||
}
|
||||
|
||||
class _TolyBreadcrumbItemState extends State<TolyBreadcrumbItem> {
|
||||
|
||||
bool _hover = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
bool hasTarget = (widget.item.to != null);
|
||||
Color? color = (_hover&&hasTarget)?Colors.blue:null;
|
||||
MouseCursor cursor = hasTarget?SystemMouseCursors.click:SystemMouseCursors.basic;
|
||||
|
||||
if(widget.item.active) {
|
||||
color = null;
|
||||
cursor = SystemMouseCursors.basic;
|
||||
}
|
||||
|
||||
TextStyle style = TextStyle(
|
||||
fontWeight: hasTarget ? FontWeight.bold : null,
|
||||
color: color
|
||||
);
|
||||
|
||||
return MouseRegion(
|
||||
cursor: cursor,
|
||||
onEnter: _onEnter,
|
||||
onExit: _onExit,
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
if(!widget.item.active){
|
||||
widget.onTapItem?.call(widget.item);
|
||||
}
|
||||
},
|
||||
child: Text(widget.item.label, style: style)),
|
||||
);
|
||||
}
|
||||
|
||||
void _onEnter(PointerEnterEvent event) {
|
||||
setState(() {
|
||||
_hover = true;
|
||||
});
|
||||
}
|
||||
|
||||
void _onExit(PointerExitEvent event) {
|
||||
setState(() {
|
||||
_hover = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class BreadcrumbItem {
|
||||
final String? to;
|
||||
final String label;
|
||||
final bool active;
|
||||
|
||||
BreadcrumbItem( {this.to, required this.label,this.active=false,});
|
||||
}
|
||||
|
||||
//<el-breadcrumb separator="/">
|
||||
// <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
|
||||
// <el-breadcrumb-item><a href="/">活动管理</a></el-breadcrumb-item>
|
||||
// <el-breadcrumb-item>活动列表</el-breadcrumb-item>
|
||||
// <el-breadcrumb-item>活动详情</el-breadcrumb-item>
|
||||
// </el-breadcrumb>
|
||||
@@ -1,163 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'menu_meta.dart';
|
||||
|
||||
// final List<NavigationRailDestination> destinations = const [
|
||||
// NavigationRailDestination(icon: Icon(Icons.color_lens_outlined), label: Text("颜色板")),
|
||||
// NavigationRailDestination(icon: Icon(Icons.add_chart), label: Text("计数器")),
|
||||
// NavigationRailDestination(icon: Icon(Icons.person), label: Text("我的")),
|
||||
// NavigationRailDestination(icon: Icon(Icons.settings), label: Text("设置")),
|
||||
// ];
|
||||
|
||||
const List<MenuMeta> kDeskNavBarMenus = [
|
||||
MenuMeta(label: '颜色板', icon: Icons.color_lens_outlined),
|
||||
MenuMeta(
|
||||
label: '计数器',
|
||||
icon: Icons.add_chart,
|
||||
),
|
||||
MenuMeta(
|
||||
label: '我的',
|
||||
icon: Icons.person,
|
||||
),
|
||||
MenuMeta(label: '设置', icon: Icons.settings),
|
||||
];
|
||||
|
||||
class TolyNavigationRail extends StatelessWidget {
|
||||
final ValueChanged<int> onDestinationSelected;
|
||||
final Color backgroundColor;
|
||||
final int? selectedIndex;
|
||||
final Widget? leading;
|
||||
|
||||
const TolyNavigationRail({
|
||||
Key? key,
|
||||
required this.onDestinationSelected,
|
||||
required this.selectedIndex,
|
||||
this.leading,
|
||||
required this.backgroundColor,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
width: 64,
|
||||
color: backgroundColor,
|
||||
child: Column(
|
||||
children: [
|
||||
if(leading!=null) leading!,
|
||||
Expanded(
|
||||
child: LeftNavigationMenu(
|
||||
items: kDeskNavBarMenus,
|
||||
selectedIndex: selectedIndex,
|
||||
onTapItem: onDestinationSelected,
|
||||
)),
|
||||
// if (selectedIndex == 0) HelpButton()
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class LeftNavigationMenu extends StatelessWidget {
|
||||
final List<MenuMeta> items;
|
||||
final ValueChanged<int> onTapItem;
|
||||
|
||||
final int? selectedIndex;
|
||||
|
||||
const LeftNavigationMenu(
|
||||
{Key? key,
|
||||
required this.items,
|
||||
required this.selectedIndex,
|
||||
required this.onTapItem})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
children: items.asMap().keys.map((int index) {
|
||||
return LeftNavigationBarItemWidget(
|
||||
item: items[index],
|
||||
selected: index == selectedIndex,
|
||||
onTap: () {
|
||||
onTapItem.call(index);
|
||||
},
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class LeftNavigationBarItemWidget extends StatefulWidget {
|
||||
final MenuMeta item;
|
||||
final bool selected;
|
||||
final VoidCallback onTap;
|
||||
|
||||
const LeftNavigationBarItemWidget(
|
||||
{Key? key,
|
||||
required this.item,
|
||||
required this.selected,
|
||||
required this.onTap})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
State<LeftNavigationBarItemWidget> createState() =>
|
||||
_LeftNavigationBarItemWidgetState();
|
||||
}
|
||||
|
||||
class _LeftNavigationBarItemWidgetState
|
||||
extends State<LeftNavigationBarItemWidget> {
|
||||
bool _hover = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Color? bgColor;
|
||||
Color iconColor;
|
||||
if (widget.selected) {
|
||||
bgColor = Colors.white.withOpacity(0.2);
|
||||
iconColor = Colors.white;
|
||||
} else {
|
||||
bgColor = _hover ? Colors.white.withOpacity(0.1) : null;
|
||||
iconColor = Colors.white.withOpacity(0.8);
|
||||
}
|
||||
|
||||
return InkWell(
|
||||
onTap: widget.selected
|
||||
? null
|
||||
: () {
|
||||
widget.onTap();
|
||||
setState(() {
|
||||
_hover = false;
|
||||
});
|
||||
},
|
||||
onHover: widget.selected
|
||||
? null
|
||||
: (v) {
|
||||
setState(() {
|
||||
_hover = v;
|
||||
});
|
||||
},
|
||||
child: Container(
|
||||
alignment: Alignment.center,
|
||||
margin: EdgeInsets.only(bottom: 10),
|
||||
width: 50,
|
||||
height: 50,
|
||||
decoration: BoxDecoration(
|
||||
color: bgColor, borderRadius: BorderRadius.circular(8)),
|
||||
child: Wrap(
|
||||
direction: Axis.vertical,
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
spacing: 2,
|
||||
children: [
|
||||
Icon(
|
||||
widget.item.icon,
|
||||
color: iconColor,
|
||||
),
|
||||
Text(
|
||||
widget.item.label,
|
||||
style: TextStyle(color: iconColor, fontSize: 12),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
|
||||
class WindowButtons extends StatefulWidget {
|
||||
final List<Widget>? actions;
|
||||
const WindowButtons({Key? key, this.actions}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<WindowButtons> createState() => _WindowButtonsState();
|
||||
}
|
||||
|
||||
class _WindowButtonsState extends State<WindowButtons> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Brightness brightness = Theme.of(context).brightness;
|
||||
return Align(
|
||||
alignment:Alignment.topRight,child: Wrap(
|
||||
spacing: 5,
|
||||
children: [
|
||||
if(widget.actions!=null)
|
||||
...widget.actions!,
|
||||
SizedBox(
|
||||
width: 30,
|
||||
height: 30,
|
||||
child: WindowCaptionButton.minimize(
|
||||
brightness:brightness,
|
||||
onPressed: () async {
|
||||
bool isMinimized = await windowManager.isMinimized();
|
||||
if (isMinimized) {
|
||||
windowManager.restore();
|
||||
} else {
|
||||
windowManager.minimize();
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 30,
|
||||
height: 30,
|
||||
child: FutureBuilder<bool>(
|
||||
future: windowManager.isMaximized(),
|
||||
builder: (BuildContext context, AsyncSnapshot<bool> snapshot) {
|
||||
if (snapshot.data == true) {
|
||||
return WindowCaptionButton.unmaximize(
|
||||
brightness: brightness,
|
||||
onPressed: () async{
|
||||
await windowManager.unmaximize();
|
||||
setState(() {
|
||||
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
return WindowCaptionButton.maximize(
|
||||
brightness: brightness,
|
||||
onPressed: () async{
|
||||
await windowManager.maximize();
|
||||
setState(() {
|
||||
|
||||
});
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 30,
|
||||
width: 30,
|
||||
child: WindowCaptionButton.close(
|
||||
brightness: brightness,
|
||||
onPressed: () {
|
||||
windowManager.close();
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
|
||||
import 'app/unit_app.dart';
|
||||
import 'app/navigation/router/app_router_delegate.dart';
|
||||
|
||||
|
||||
void main() {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
setSize();
|
||||
runApp(const UnitApp());
|
||||
}
|
||||
|
||||
|
||||
void setSize() async{
|
||||
await windowManager.ensureInitialized();
|
||||
WindowOptions windowOptions = const WindowOptions(
|
||||
size: Size(800, 540),
|
||||
center: true,
|
||||
backgroundColor: Colors.transparent,
|
||||
skipTaskbar: false,
|
||||
titleBarStyle: TitleBarStyle.hidden,
|
||||
);
|
||||
windowManager.waitUntilReadyToShow(windowOptions, () async {
|
||||
await windowManager.show();
|
||||
await windowManager.focus();
|
||||
});
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_colorpicker/flutter_colorpicker.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(
|
||||
bottomNavigationBar: Container(
|
||||
margin: EdgeInsets.only(right:20,bottom: 20),
|
||||
// color: Colors.redAccent,
|
||||
child: Row(
|
||||
textDirection:TextDirection.rtl,
|
||||
children: [
|
||||
ElevatedButton(onPressed: (){
|
||||
Navigator.of(context).pop(_color);
|
||||
|
||||
}, child: Text('添加')),
|
||||
SizedBox(width: 12,),
|
||||
OutlinedButton(onPressed: (){
|
||||
Navigator.of(context).pop();
|
||||
}, child: Text('取消')),
|
||||
],
|
||||
),
|
||||
),
|
||||
body: Column(
|
||||
// mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0,vertical: 16),
|
||||
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),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
ColorPicker(
|
||||
colorPickerWidth:200,
|
||||
// enableAlpha: false,
|
||||
displayThumbColor:true,
|
||||
pickerColor: _color,
|
||||
paletteType: PaletteType.hueWheel,
|
||||
onColorChanged: changeColor,
|
||||
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void changeColor(Color value) {
|
||||
_color = value;
|
||||
setState(() {
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
class ColorDetailPage extends StatelessWidget {
|
||||
final Color color;
|
||||
const ColorDetailPage({super.key, required this.color});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
const TextStyle style = TextStyle(
|
||||
fontSize: 32,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.white
|
||||
);
|
||||
String text = '# ${color.value.toRadixString(16)}';
|
||||
return Scaffold(
|
||||
// appBar: AppBar(
|
||||
// systemOverlayStyle: SystemUiOverlayStyle(
|
||||
// statusBarColor: Colors.transparent,
|
||||
// statusBarIconBrightness: Brightness.light
|
||||
// ),
|
||||
// iconTheme: IconThemeData(color: Colors.white),
|
||||
// titleTextStyle:TextStyle(color: Colors.white,fontSize: 18) ,
|
||||
// backgroundColor: color,
|
||||
// title: Text('颜色界面',),),
|
||||
body: Container(
|
||||
alignment: Alignment.center,
|
||||
color: color,
|
||||
child: Text(text ,style: style,),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:iroute/common/components/colors_panel.dart';
|
||||
import '../../app/navigation/router/app_router_delegate.dart';
|
||||
|
||||
class ColorPage extends StatefulWidget {
|
||||
const ColorPage({super.key});
|
||||
|
||||
@override
|
||||
State<ColorPage> createState() => _ColorPageState();
|
||||
}
|
||||
|
||||
class _ColorPageState extends State<ColorPage> {
|
||||
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: Align(
|
||||
alignment: Alignment.topCenter,
|
||||
child: ColorsPanel(
|
||||
colors: _colors,
|
||||
onSelect: _selectColor,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _selectColor(Color color){
|
||||
String value = color.value.toRadixString(16);
|
||||
router.path = '/color/detail?color=$value';
|
||||
}
|
||||
|
||||
void _toAddPage() async {
|
||||
Color? color = await router.changePathForResult('/color/add');
|
||||
if (color != null) {
|
||||
setState(() {
|
||||
_colors.add(color);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class CounterPage extends StatefulWidget {
|
||||
const CounterPage({super.key});
|
||||
|
||||
@override
|
||||
State<CounterPage> createState() => _CounterPageState();
|
||||
}
|
||||
|
||||
class _CounterPageState extends State<CounterPage> {
|
||||
int _counter = 0;
|
||||
|
||||
void _incrementCounter() {
|
||||
setState(() {
|
||||
_counter++;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
const Text(
|
||||
'You have pushed the button this many times:',
|
||||
),
|
||||
Text(
|
||||
'$_counter',
|
||||
style: Theme.of(context).textTheme.headlineMedium,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: _incrementCounter,
|
||||
tooltip: 'Increment',
|
||||
child: const Icon(Icons.add),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class EmptyPage extends StatelessWidget {
|
||||
const EmptyPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('界面走丢了'),
|
||||
),
|
||||
body: Scaffold(
|
||||
body: Center(
|
||||
child: Wrap(
|
||||
spacing: 16,
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
direction: Axis.vertical,
|
||||
children: [
|
||||
Icon(Icons.nearby_error,size: 64, color: Colors.grey),
|
||||
Text(
|
||||
'404 界面丢失',
|
||||
style: TextStyle(fontSize: 24, color: Colors.grey),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class SettingPage extends StatelessWidget {
|
||||
const SettingPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body:Center(child: Text('SettingPage')));
|
||||
}
|
||||
}
|
||||
@@ -1,859 +0,0 @@
|
||||
import 'dart:async';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class SortPage extends StatefulWidget {
|
||||
const SortPage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<SortPage> createState() => _SortPageState();
|
||||
}
|
||||
|
||||
class _SortPageState extends State<SortPage> {
|
||||
//存放随机数组
|
||||
List<int> numbers = [];
|
||||
|
||||
//订阅流
|
||||
StreamController<List<int>> streamController = StreamController();
|
||||
String currentSort = 'bubble';
|
||||
|
||||
//柱子的数量 -> 生成排序数组的长度
|
||||
double sampleSize = 0;
|
||||
|
||||
//是否排序
|
||||
bool isSorted = false;
|
||||
|
||||
//是否在排序中
|
||||
bool isSorting = false;
|
||||
|
||||
//排序动画更新的速度
|
||||
int speed = 0;
|
||||
|
||||
static int duration = 1500;
|
||||
|
||||
String getTitle() {
|
||||
switch (currentSort) {
|
||||
case "bubble":
|
||||
return "Bubble Sort";
|
||||
case "coctail":
|
||||
return "Coctail Sort";
|
||||
case "comb":
|
||||
return "Comb Sort";
|
||||
case "pigeonhole":
|
||||
return "Pigeonhole Sort";
|
||||
case "shell":
|
||||
return "Shell Sort";
|
||||
case "selection":
|
||||
return "Selection Sort";
|
||||
case "cycle":
|
||||
return "Cycle Sort";
|
||||
case "heap":
|
||||
return "Heap Sort";
|
||||
case "insertion":
|
||||
return "Insertion Sort";
|
||||
case "gnome":
|
||||
return "Gnome Sort";
|
||||
case "oddeven":
|
||||
return "OddEven Sort";
|
||||
case "quick":
|
||||
return "Quick Sort";
|
||||
case "merge":
|
||||
return "Merge Sort";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
reset() {
|
||||
isSorted = false;
|
||||
numbers = [];
|
||||
for (int i = 0; i < sampleSize; ++i) {
|
||||
numbers.add(Random().nextInt(500));
|
||||
}
|
||||
streamController.add(numbers);
|
||||
}
|
||||
|
||||
Duration getDuration() {
|
||||
return Duration(microseconds: duration);
|
||||
}
|
||||
|
||||
///动画时间
|
||||
changeSpeed() {
|
||||
if (speed >= 3) {
|
||||
speed = 0;
|
||||
duration = 1500;
|
||||
} else {
|
||||
speed++;
|
||||
duration = duration ~/ 2;
|
||||
}
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
///冒泡排序
|
||||
bubbleSort() async {
|
||||
//控制需要进行排序的次数。每一轮循环都会确定一个数字的最终位置。
|
||||
for (int i = 0; i < numbers.length; ++i) {
|
||||
//遍历当前未排序的元素,通过相邻的元素比较并交换位置来完成排序。
|
||||
for (int j = 0; j < numbers.length - i - 1; ++j) {
|
||||
//如果 _numbers[j] 大于 _numbers[j + 1],则交换它们的位置,确保较大的元素移到右边。
|
||||
if (numbers[j] > numbers[j + 1]) {
|
||||
int temp = numbers[j];
|
||||
numbers[j] = numbers[j + 1];
|
||||
numbers[j + 1] = temp;
|
||||
}
|
||||
//实现一个延迟,以便在ui上展示排序的动画效果
|
||||
await Future.delayed(getDuration(), () {});
|
||||
streamController.add(numbers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///鸡尾酒排序(双向冒泡排序)
|
||||
cocktailSort() async {
|
||||
bool swapped = true; // 表示是否进行了交换
|
||||
int start = 0; // 当前未排序部分的起始位置
|
||||
int end = numbers.length; // 当前未排序部分的结束位置
|
||||
|
||||
// 开始排序循环,只有当没有进行交换时才会退出循环
|
||||
while (swapped == true) {
|
||||
swapped = false;
|
||||
|
||||
// 从左往右遍历需要排序的部分
|
||||
for (int i = start; i < end - 1; ++i) {
|
||||
// 对每两个相邻元素进行比较
|
||||
if (numbers[i] > numbers[i + 1]) {
|
||||
// 如果前面的元素大于后面的元素,则交换它们的位置
|
||||
int temp = numbers[i];
|
||||
numbers[i] = numbers[i + 1];
|
||||
numbers[i + 1] = temp;
|
||||
swapped = true; // 进行了交换
|
||||
}
|
||||
|
||||
// 实现动画效果,延迟一段时间后更新数组状态
|
||||
await Future.delayed(getDuration());
|
||||
streamController.add(numbers);
|
||||
}
|
||||
|
||||
// 如果没有进行交换,则说明已经排好序,退出循环
|
||||
if (swapped == false) break;
|
||||
// 重设为false,准备进行下一轮排序
|
||||
swapped = false;
|
||||
// 将end设置为上一轮排序的最后一个元素的位置
|
||||
end = end - 1;
|
||||
|
||||
// 从右往左遍历需要排序的部分
|
||||
for (int i = end - 1; i >= start; i--) {
|
||||
// 对每两个相邻元素进行比较
|
||||
if (numbers[i] > numbers[i + 1]) {
|
||||
// 如果前面的元素大于后面的元素,则交换它们的位置
|
||||
int temp = numbers[i];
|
||||
numbers[i] = numbers[i + 1];
|
||||
numbers[i + 1] = temp;
|
||||
swapped = true; // 进行了交换
|
||||
}
|
||||
|
||||
// 实现动画效果,延迟一段时间后更新数组状态
|
||||
await Future.delayed(getDuration());
|
||||
streamController.add(numbers);
|
||||
}
|
||||
// 将start向右移一位,准备下一轮排序
|
||||
start = start + 1;
|
||||
}
|
||||
}
|
||||
|
||||
///梳排序(Comb Sort)
|
||||
combSort() async {
|
||||
int gap = numbers.length;
|
||||
|
||||
bool swapped = true;
|
||||
|
||||
// 当间隔不为1或存在交换时执行循环
|
||||
while (gap != 1 || swapped == true) {
|
||||
// 通过缩小间隔来逐步将元素归位
|
||||
gap = getNextGap(gap);
|
||||
swapped = false;
|
||||
for (int i = 0; i < numbers.length - gap; i++) {
|
||||
// 如果当前元素大于间隔位置上的元素,则交换它们的位置
|
||||
if (numbers[i] > numbers[i + gap]) {
|
||||
int temp = numbers[i];
|
||||
numbers[i] = numbers[i + gap];
|
||||
numbers[i + gap] = temp;
|
||||
swapped = true;
|
||||
}
|
||||
|
||||
// 实现一个延迟,以便在 UI 上展示排序的动画效果。
|
||||
await Future.delayed(getDuration());
|
||||
streamController.add(numbers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int getNextGap(int gap) {
|
||||
// 根据当前间隔值计算下一个间隔值
|
||||
gap = (gap * 10) ~/ 13;
|
||||
if (gap < 1) return 1;
|
||||
return gap;
|
||||
}
|
||||
|
||||
///鸽巢排序
|
||||
pigeonHole() async {
|
||||
int min = numbers[0];
|
||||
int max = numbers[0];
|
||||
int range, i, j, index;
|
||||
|
||||
// 找到数组中的最大值和最小值
|
||||
for (int a = 0; a < numbers.length; a++) {
|
||||
if (numbers[a] > max) max = numbers[a];
|
||||
if (numbers[a] < min) min = numbers[a];
|
||||
}
|
||||
|
||||
// 计算鸽巢的个数
|
||||
range = max - min + 1;
|
||||
List<int> p = List.generate(range, (i) => 0);
|
||||
|
||||
// 将数字分配到各个鸽巢中
|
||||
for (i = 0; i < numbers.length; i++) {
|
||||
p[numbers[i] - min]++;
|
||||
}
|
||||
|
||||
index = 0;
|
||||
|
||||
// 将鸽巢中的数字取出,重新放回到数组中
|
||||
for (j = 0; j < range; j++) {
|
||||
while (p[j]-- > 0) {
|
||||
numbers[index++] = j + min;
|
||||
await Future.delayed(getDuration());
|
||||
streamController.add(numbers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///希尔排序
|
||||
shellSort() async {
|
||||
//定义变量 gap 并初始化为数组长度的一半。每次循环完成后将 gap 减半直到等于 0。
|
||||
for (int gap = numbers.length ~/ 2; gap > 0; gap ~/= 2) {
|
||||
//遍历每个子序列并进行插入排序。初始时从第一个子序列的第二个元素开始,即 i = gap,以 gap 为步长逐个遍历每个子序列。
|
||||
for (int i = gap; i < numbers.length; i += 1) {
|
||||
//将当前遍历到的元素赋值给它
|
||||
int temp = numbers[i];
|
||||
//内部使用一个 for 循环来实现插入排序。
|
||||
//循环开始时定义变量 j 并将其初始化为当前遍历到的元素的下标。通过不断比较前后相隔 gap 的元素大小并交换位置,将当前元素插入到正确的位置。
|
||||
int j;
|
||||
for (j = i; j >= gap && numbers[j - gap] > temp; j -= gap) {
|
||||
numbers[j] = numbers[j - gap];
|
||||
}
|
||||
numbers[j] = temp;
|
||||
await Future.delayed(getDuration());
|
||||
streamController.add(numbers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///选择排序
|
||||
selectionSort() async {
|
||||
for (int i = 0; i < numbers.length; i++) {
|
||||
for (int j = i + 1; j < numbers.length; j++) {
|
||||
// 遍历未排序部分,内层循环控制变量 j
|
||||
if (numbers[i] > numbers[j]) {
|
||||
// 判断当前元素是否比后续元素小
|
||||
int temp = numbers[j];
|
||||
// 交换当前元素和后续较小的元素
|
||||
numbers[j] = numbers[i];
|
||||
numbers[i] = temp;
|
||||
}
|
||||
|
||||
await Future.delayed(getDuration(), () {});
|
||||
|
||||
streamController.add(numbers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///循环排序
|
||||
cycleSort() async {
|
||||
int writes = 0;
|
||||
for (int cycleStart = 0; cycleStart <= numbers.length - 2; cycleStart++) {
|
||||
int item = numbers[cycleStart];
|
||||
int pos = cycleStart;
|
||||
|
||||
// 在未排序部分中寻找比当前元素小的元素个数
|
||||
for (int i = cycleStart + 1; i < numbers.length; i++) {
|
||||
if (numbers[i] < item) pos++;
|
||||
}
|
||||
|
||||
// 如果当前元素已经在正确位置上,则跳过此次迭代
|
||||
if (pos == cycleStart) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 将当前元素放置到正确的位置上,并记录写操作次数
|
||||
while (item == numbers[pos]) {
|
||||
pos += 1;
|
||||
}
|
||||
if (pos != cycleStart) {
|
||||
int temp = item;
|
||||
item = numbers[pos];
|
||||
numbers[pos] = temp;
|
||||
writes++;
|
||||
}
|
||||
|
||||
// 循环将位于当前位置的元素放置到正确的位置上
|
||||
while (pos != cycleStart) {
|
||||
pos = cycleStart;
|
||||
// 继续在未排序部分中寻找比当前元素小的元素个数
|
||||
for (int i = cycleStart + 1; i < numbers.length; i++) {
|
||||
if (numbers[i] < item) pos += 1;
|
||||
}
|
||||
|
||||
// 将当前元素放置到正确的位置上,并记录写操作次数
|
||||
while (item == numbers[pos]) {
|
||||
pos += 1;
|
||||
}
|
||||
if (item != numbers[pos]) {
|
||||
int temp = item;
|
||||
item = numbers[pos];
|
||||
numbers[pos] = temp;
|
||||
writes++;
|
||||
}
|
||||
|
||||
// 添加延迟操作以展示排序过程
|
||||
await Future.delayed(getDuration());
|
||||
streamController.add(numbers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///堆排序
|
||||
heapSort() async {
|
||||
// 从最后一个非叶子节点开始,构建最大堆
|
||||
for (int i = numbers.length ~/ 2; i >= 0; i--) {
|
||||
await heapify(numbers, numbers.length, i);
|
||||
streamController.add(numbers);
|
||||
}
|
||||
|
||||
// 依次取出最大堆的根节点(最大值),并进行堆化
|
||||
for (int i = numbers.length - 1; i >= 0; i--) {
|
||||
int temp = numbers[0];
|
||||
numbers[0] = numbers[i];
|
||||
numbers[i] = temp;
|
||||
await heapify(numbers, i, 0);
|
||||
streamController.add(numbers);
|
||||
}
|
||||
}
|
||||
|
||||
heapify(List<int> arr, int n, int i) async {
|
||||
int largest = i;
|
||||
int l = 2 * i + 1; // 左子节点索引
|
||||
int r = 2 * i + 2; // 右子节点索引
|
||||
|
||||
// 如果左子节点存在并且大于父节点,则更新最大值索引
|
||||
if (l < n && arr[l] > arr[largest]) largest = l;
|
||||
|
||||
// 如果右子节点存在并且大于父节点或左子节点,则更新最大值索引
|
||||
if (r < n && arr[r] > arr[largest]) largest = r;
|
||||
|
||||
// 如果最大值索引不等于当前节点索引,则交换节点值,并递归进行堆化
|
||||
if (largest != i) {
|
||||
int temp = numbers[i];
|
||||
numbers[i] = numbers[largest];
|
||||
numbers[largest] = temp;
|
||||
heapify(arr, n, largest);
|
||||
}
|
||||
|
||||
await Future.delayed(getDuration()); // 延迟操作,用于可视化排序过程
|
||||
}
|
||||
|
||||
///插入排序
|
||||
insertionSort() async {
|
||||
for (int i = 1; i < numbers.length; i++) {
|
||||
int temp = numbers[i]; // 将当前元素存储到临时变量 temp 中
|
||||
int j = i - 1; // j 表示已排序部分的最后一个元素的索引
|
||||
|
||||
// 在已排序部分从后往前查找,找到合适位置插入当前元素
|
||||
while (j >= 0 && temp < numbers[j]) {
|
||||
numbers[j + 1] = numbers[j]; // 当前元素比已排序部分的元素小,将元素后移一位
|
||||
--j; // 向前遍历
|
||||
await Future.delayed(getDuration());
|
||||
streamController.add(numbers); // 更新排序结果
|
||||
}
|
||||
|
||||
numbers[j + 1] = temp; // 插入当前元素到已排序部分的正确位置
|
||||
await Future.delayed(getDuration(), () {});
|
||||
streamController.add(numbers); // 更新排序结果
|
||||
}
|
||||
}
|
||||
|
||||
///地精排序 (侏儒排序)
|
||||
gnomeSort() async {
|
||||
int index = 0;
|
||||
|
||||
while (index < numbers.length) {
|
||||
// 当 index 小于数组长度时执行循环
|
||||
if (index == 0) index++;
|
||||
if (numbers[index] >= numbers[index - 1]) {
|
||||
// 如果当前元素大于等于前面的元素,则将 index 加1
|
||||
index++;
|
||||
} else {
|
||||
// 否则,交换这两个元素,并将 index 减1(使得元素可以沉到正确位置)
|
||||
int temp = numbers[index];
|
||||
numbers[index] = numbers[index - 1];
|
||||
numbers[index - 1] = temp;
|
||||
index--;
|
||||
}
|
||||
await Future.delayed(getDuration());
|
||||
streamController.add(numbers);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
///奇偶排序(Odd-Even Sort)
|
||||
oddEvenSort() async {
|
||||
bool isSorted = false;
|
||||
|
||||
while (!isSorted) {
|
||||
// 当 isSorted 为 false 时执行循环
|
||||
isSorted = true; // 先假设数组已经排好序
|
||||
|
||||
for (int i = 1; i <= numbers.length - 2; i = i + 2) {
|
||||
// 对奇数索引位置进行比较
|
||||
if (numbers[i] > numbers[i + 1]) {
|
||||
// 如果当前元素大于后面的元素,则交换它们的值
|
||||
int temp = numbers[i];
|
||||
numbers[i] = numbers[i + 1];
|
||||
numbers[i + 1] = temp;
|
||||
isSorted = false; // 若发生了交换,则说明数组仍未完全排序,将 isSorted 设为 false
|
||||
await Future.delayed(getDuration());
|
||||
streamController.add(numbers);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i <= numbers.length - 2; i = i + 2) {
|
||||
// 对偶数索引位置进行比较
|
||||
if (numbers[i] > numbers[i + 1]) {
|
||||
// 如果当前元素大于后面的元素,则交换它们的值
|
||||
int temp = numbers[i];
|
||||
numbers[i] = numbers[i + 1];
|
||||
numbers[i + 1] = temp;
|
||||
isSorted = false;
|
||||
await Future.delayed(getDuration());
|
||||
streamController.add(numbers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
///快速排序
|
||||
quickSort(int leftIndex, int rightIndex) async {
|
||||
// 定义一个名为 _partition 的异步函数,用于划分数组,并返回划分后的基准元素的索引位置
|
||||
Future<int> _partition(int left, int right) async {
|
||||
// 选择中间位置的元素作为基准元素
|
||||
int p = (left + (right - left) / 2).toInt();
|
||||
|
||||
// 交换基准元素和最右边的元素
|
||||
var temp = numbers[p];
|
||||
numbers[p] = numbers[right];
|
||||
numbers[right] = temp;
|
||||
await Future.delayed(getDuration());
|
||||
streamController.add(numbers);
|
||||
|
||||
// 初始化游标 cursor
|
||||
int cursor = left;
|
||||
|
||||
// 遍历数组并根据基准元素将元素交换到左侧或右侧
|
||||
for (int i = left; i < right; i++) {
|
||||
if (cf(numbers[i], numbers[right]) <= 0) {
|
||||
// 如果当前元素小于等于基准元素,则交换它和游标位置的元素
|
||||
var temp = numbers[i];
|
||||
numbers[i] = numbers[cursor];
|
||||
numbers[cursor] = temp;
|
||||
cursor++;
|
||||
|
||||
await Future.delayed(getDuration());
|
||||
streamController.add(numbers);
|
||||
}
|
||||
}
|
||||
|
||||
// 将基准元素放置在游标位置
|
||||
temp = numbers[right];
|
||||
numbers[right] = numbers[cursor];
|
||||
numbers[cursor] = temp;
|
||||
|
||||
await Future.delayed(getDuration());
|
||||
streamController.add(numbers);
|
||||
|
||||
return cursor; // 返回基准元素的索引位置
|
||||
}
|
||||
|
||||
// 如果左索引小于右索引,则递归地对数组进行快速排序
|
||||
if (leftIndex < rightIndex) {
|
||||
int p = await _partition(leftIndex, rightIndex);
|
||||
|
||||
await quickSort(leftIndex, p - 1); // 对基准元素左侧的子数组进行快速排序
|
||||
|
||||
await quickSort(p + 1, rightIndex); // 对基准元素右侧的子数组进行快速排序
|
||||
}
|
||||
}
|
||||
|
||||
// 比较函数,用于判断两个元素的大小关系
|
||||
cf(int a, int b) {
|
||||
if (a < b) {
|
||||
return -1; // 若 a 小于 b,则返回 -1
|
||||
} else if (a > b) {
|
||||
return 1; // 若 a 大于 b,则返回 1
|
||||
} else {
|
||||
return 0; // 若 a 等于 b,则返回 0
|
||||
}
|
||||
}
|
||||
|
||||
///归并排序
|
||||
mergeSort(int leftIndex, int rightIndex) async {
|
||||
// 定义一个名为 merge 的异步函数,用于合并两个有序子数组
|
||||
Future<void> merge(int leftIndex, int middleIndex, int rightIndex) async {
|
||||
// 计算左侧子数组和右侧子数组的大小
|
||||
int leftSize = middleIndex - leftIndex + 1;
|
||||
int rightSize = rightIndex - middleIndex;
|
||||
|
||||
// 创建左侧子数组和右侧子数组
|
||||
List leftList = List.generate(leftSize, (index) => 0);
|
||||
List rightList = List.generate(rightSize, (index) => 0);
|
||||
|
||||
// 将原始数组中的元素分别复制到左侧子数组和右侧子数组中
|
||||
for (int i = 0; i < leftSize; i++) {
|
||||
leftList[i] = numbers[leftIndex + i];
|
||||
}
|
||||
for (int j = 0; j < rightSize; j++) {
|
||||
rightList[j] = numbers[middleIndex + j + 1];
|
||||
}
|
||||
|
||||
// 初始化游标和索引
|
||||
int i = 0, j = 0;
|
||||
int k = leftIndex;
|
||||
|
||||
// 比较左侧子数组和右侧子数组的元素,并按顺序将较小的元素放入原始数组中
|
||||
while (i < leftSize && j < rightSize) {
|
||||
if (leftList[i] <= rightList[j]) {
|
||||
numbers[k] = leftList[i];
|
||||
i++;
|
||||
} else {
|
||||
numbers[k] = rightList[j];
|
||||
j++;
|
||||
}
|
||||
|
||||
await Future.delayed(getDuration());
|
||||
streamController.add(numbers);
|
||||
|
||||
k++;
|
||||
}
|
||||
|
||||
// 将左侧子数组或右侧子数组中剩余的元素放入原始数组中
|
||||
while (i < leftSize) {
|
||||
numbers[k] = leftList[i];
|
||||
i++;
|
||||
k++;
|
||||
|
||||
await Future.delayed(getDuration());
|
||||
streamController.add(numbers);
|
||||
}
|
||||
|
||||
while (j < rightSize) {
|
||||
numbers[k] = rightList[j];
|
||||
j++;
|
||||
k++;
|
||||
|
||||
await Future.delayed(getDuration());
|
||||
streamController.add(numbers);
|
||||
}
|
||||
}
|
||||
|
||||
// 如果左索引小于右索引,则递归地对数组进行归并排序
|
||||
if (leftIndex < rightIndex) {
|
||||
// 计算中间索引位置
|
||||
int middleIndex = (rightIndex + leftIndex) ~/ 2;
|
||||
|
||||
// 分别对左侧子数组和右侧子数组进行归并排序
|
||||
await mergeSort(leftIndex, middleIndex);
|
||||
await mergeSort(middleIndex + 1, rightIndex);
|
||||
|
||||
await Future.delayed(getDuration());
|
||||
streamController.add(numbers);
|
||||
|
||||
// 合并两个有序子数组
|
||||
await merge(leftIndex, middleIndex, rightIndex);
|
||||
}
|
||||
}
|
||||
|
||||
checkAndResetIfSorted() async {
|
||||
if (isSorted) {
|
||||
reset();
|
||||
await Future.delayed(const Duration(milliseconds: 200));
|
||||
}
|
||||
}
|
||||
|
||||
sort() async {
|
||||
setState(() {
|
||||
isSorting = true;
|
||||
});
|
||||
|
||||
await checkAndResetIfSorted();
|
||||
|
||||
Stopwatch stopwatch = Stopwatch()..start();
|
||||
|
||||
switch (currentSort) {
|
||||
case "bubble":
|
||||
await bubbleSort();
|
||||
break;
|
||||
case "coctail":
|
||||
await cocktailSort();
|
||||
break;
|
||||
case "comb":
|
||||
await combSort();
|
||||
break;
|
||||
case "pigeonhole":
|
||||
await pigeonHole();
|
||||
break;
|
||||
case "shell":
|
||||
await shellSort();
|
||||
break;
|
||||
case "selection":
|
||||
await selectionSort();
|
||||
break;
|
||||
case "cycle":
|
||||
await cycleSort();
|
||||
break;
|
||||
case "heap":
|
||||
await heapSort();
|
||||
break;
|
||||
case "insertion":
|
||||
await insertionSort();
|
||||
break;
|
||||
case "gnome":
|
||||
await gnomeSort();
|
||||
break;
|
||||
case "oddeven":
|
||||
await oddEvenSort();
|
||||
break;
|
||||
case "quick":
|
||||
await quickSort(0, sampleSize.toInt() - 1);
|
||||
break;
|
||||
case "merge":
|
||||
await mergeSort(0, sampleSize.toInt() - 1);
|
||||
break;
|
||||
}
|
||||
|
||||
stopwatch.stop();
|
||||
|
||||
print("Sorting completed in ${stopwatch.elapsed.inMilliseconds} ms.");
|
||||
setState(() {
|
||||
isSorting = false;
|
||||
isSorted = true;
|
||||
});
|
||||
}
|
||||
|
||||
setSort(String type) {
|
||||
setState(() {
|
||||
currentSort = type;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
// reset();
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
sampleSize = MediaQuery.of(context).size.width / 2;
|
||||
for (int i = 0; i < sampleSize; ++i) {
|
||||
//随机往数组中填值
|
||||
numbers.add(Random().nextInt(500));
|
||||
}
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
streamController.close();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(
|
||||
"当前选择的是:${getTitle()}",
|
||||
style: const TextStyle(fontSize: 14),
|
||||
),
|
||||
actions: <Widget>[
|
||||
PopupMenuButton(
|
||||
initialValue: currentSort,
|
||||
itemBuilder: (ctx) {
|
||||
return const [
|
||||
PopupMenuItem(
|
||||
value: 'bubble',
|
||||
child: Text("Bubble Sort — 冒泡排序"),
|
||||
),
|
||||
PopupMenuItem(
|
||||
value: 'coctail',
|
||||
child: Text("Coctail Sort — 鸡尾酒排序(双向冒泡排序)"),
|
||||
),
|
||||
PopupMenuItem(
|
||||
value: 'comb',
|
||||
child: Text("Comb Sort — 梳排序"),
|
||||
),
|
||||
PopupMenuItem(
|
||||
value: 'pigeonhole',
|
||||
child: Text("pigeonhole Sort — 鸽巢排序"),
|
||||
),
|
||||
PopupMenuItem(
|
||||
value: 'shell',
|
||||
child: Text("shell Sort — 希尔排序"),
|
||||
),
|
||||
PopupMenuItem(
|
||||
value: 'selection',
|
||||
child: Text("Selection Sort — 选择排序"),
|
||||
),
|
||||
PopupMenuItem(
|
||||
value: 'cycle',
|
||||
child: Text("CycleSort — 循环排序"),
|
||||
),
|
||||
PopupMenuItem(
|
||||
value: 'heap',
|
||||
child: Text("HeapSort — 堆排序"),
|
||||
),
|
||||
PopupMenuItem(
|
||||
value: 'insertion',
|
||||
child: Text("InsertionSort — 插入排序"),
|
||||
),
|
||||
PopupMenuItem(
|
||||
value: 'gnome',
|
||||
child: Text("GnomeSort — 地精排序 (侏儒排序)"),
|
||||
),
|
||||
PopupMenuItem(
|
||||
value: 'oddeven',
|
||||
child: Text("OddEvenSort — 奇偶排序"),
|
||||
),
|
||||
PopupMenuItem(
|
||||
value: 'quick',
|
||||
child: Text("QuickSort — 快速排序"),
|
||||
),
|
||||
PopupMenuItem(
|
||||
value: 'merge',
|
||||
child: Text("MergeSort — 归并排序"),
|
||||
),
|
||||
];
|
||||
},
|
||||
onSelected: (String value) {
|
||||
reset();
|
||||
setSort(value);
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
body: StreamBuilder<Object>(
|
||||
initialData: numbers,
|
||||
stream: streamController.stream,
|
||||
builder: (context, snapshot) {
|
||||
List<int> numbers = snapshot.data as List<int>;
|
||||
int counter = 0;
|
||||
return Row(
|
||||
children: numbers.map((int num) {
|
||||
counter++;
|
||||
return CustomPaint(
|
||||
painter: BarPainter(
|
||||
width: MediaQuery.of(context).size.width / sampleSize,
|
||||
value: num,
|
||||
index: counter,
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
},
|
||||
),
|
||||
bottomNavigationBar: BottomAppBar(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: <Widget>[
|
||||
ElevatedButton(
|
||||
onPressed: isSorting
|
||||
? null
|
||||
: () {
|
||||
reset();
|
||||
setSort(currentSort);
|
||||
},
|
||||
child: const Text("重置")),
|
||||
ElevatedButton(
|
||||
onPressed: isSorting ? null : sort, child: const Text("开始排序")),
|
||||
ElevatedButton(
|
||||
onPressed: isSorting ? null : changeSpeed,
|
||||
child: Text(
|
||||
"${speed + 1}x",
|
||||
style: const TextStyle(fontSize: 20),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class BarPainter extends CustomPainter {
|
||||
//宽度
|
||||
final double width;
|
||||
|
||||
//高度(数组中对应的值)
|
||||
final int value;
|
||||
|
||||
//位置索引
|
||||
final int index;
|
||||
|
||||
BarPainter({required this.width, required this.value, required this.index});
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
Paint paint = Paint();
|
||||
if (value < 500 * .10) {
|
||||
paint.color = Colors.blue.shade100;
|
||||
} else if (value < 500 * .20) {
|
||||
paint.color = Colors.blue.shade200;
|
||||
} else if (value < 500 * .30) {
|
||||
paint.color = Colors.blue.shade300;
|
||||
} else if (value < 500 * .40) {
|
||||
paint.color = Colors.blue.shade400;
|
||||
} else if (value < 500 * .50) {
|
||||
paint.color = Colors.blue.shade500;
|
||||
} else if (value < 500 * .60) {
|
||||
paint.color = Colors.blue.shade600;
|
||||
} else if (value < 500 * .70) {
|
||||
paint.color = Colors.blue.shade700;
|
||||
} else if (value < 500 * .80) {
|
||||
paint.color = Colors.blue.shade800;
|
||||
} else if (value < 500 * .90) {
|
||||
paint.color = Colors.blue.shade900;
|
||||
} else {
|
||||
paint.color = const Color(0xFF011E51);
|
||||
}
|
||||
|
||||
paint.strokeWidth = width;
|
||||
paint.strokeCap = StrokeCap.round;
|
||||
|
||||
canvas.drawLine(
|
||||
Offset(index * width, 0),
|
||||
Offset(
|
||||
index * width,
|
||||
value.ceilToDouble(),
|
||||
),
|
||||
paint);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(covariant CustomPainter oldDelegate) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class UserPage extends StatelessWidget {
|
||||
const UserPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body:Center(child: Text('UserPage')));
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
// Copyright 2021, the Flutter project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class FadeTransitionPage<T> extends Page<T> {
|
||||
final Widget child;
|
||||
final Duration duration;
|
||||
|
||||
const FadeTransitionPage({
|
||||
super.key,
|
||||
required this.child,
|
||||
this.duration = const Duration(milliseconds: 300),
|
||||
});
|
||||
|
||||
@override
|
||||
Route<T> createRoute(BuildContext context) =>
|
||||
PageBasedFadeTransitionRoute<T>(this);
|
||||
}
|
||||
|
||||
class PageBasedFadeTransitionRoute<T> extends PageRoute<T> {
|
||||
final FadeTransitionPage<T> _page;
|
||||
|
||||
PageBasedFadeTransitionRoute(this._page) : super(settings: _page);
|
||||
|
||||
@override
|
||||
Color? get barrierColor => null;
|
||||
|
||||
@override
|
||||
String? get barrierLabel => null;
|
||||
|
||||
@override
|
||||
Duration get transitionDuration => _page.duration;
|
||||
|
||||
@override
|
||||
bool get maintainState => true;
|
||||
|
||||
@override
|
||||
Widget buildPage(BuildContext context, Animation<double> animation,
|
||||
Animation<double> secondaryAnimation) {
|
||||
var curveTween = CurveTween(curve: Curves.easeIn);
|
||||
return FadeTransition(
|
||||
opacity: animation.drive(curveTween),
|
||||
child: (settings as FadeTransitionPage).child,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget buildTransitions(BuildContext context, Animation<double> animation,
|
||||
Animation<double> secondaryAnimation, Widget child) =>
|
||||
child;
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
// Copyright 2021, the Flutter project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class NoTransitionPage<T> extends Page<T> {
|
||||
final Widget child;
|
||||
|
||||
const NoTransitionPage({
|
||||
super.key,
|
||||
required this.child,
|
||||
});
|
||||
|
||||
@override
|
||||
Route<T> createRoute(BuildContext context) => NoTransitionRoute<T>(this);
|
||||
}
|
||||
|
||||
class NoTransitionRoute<T> extends PageRoute<T> {
|
||||
|
||||
final NoTransitionPage<T> _page;
|
||||
|
||||
NoTransitionRoute(this._page) : super(settings: _page);
|
||||
|
||||
@override
|
||||
Color? get barrierColor => null;
|
||||
|
||||
@override
|
||||
String? get barrierLabel => null;
|
||||
|
||||
@override
|
||||
Duration get transitionDuration => const Duration(milliseconds: 0);
|
||||
|
||||
@override
|
||||
bool get maintainState => true;
|
||||
|
||||
@override
|
||||
Widget buildPage(BuildContext context, Animation<double> animation,
|
||||
Animation<double> secondaryAnimation) {
|
||||
return (settings as NoTransitionPage).child;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget buildTransitions(BuildContext context, Animation<double> animation,
|
||||
Animation<double> secondaryAnimation, Widget child) =>
|
||||
child;
|
||||
}
|
||||
@@ -6,18 +6,10 @@
|
||||
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <screen_retriever/screen_retriever_plugin.h>
|
||||
#include <url_launcher_linux/url_launcher_plugin.h>
|
||||
#include <window_manager/window_manager_plugin.h>
|
||||
|
||||
void fl_register_plugins(FlPluginRegistry* registry) {
|
||||
g_autoptr(FlPluginRegistrar) screen_retriever_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "ScreenRetrieverPlugin");
|
||||
screen_retriever_plugin_register_with_registrar(screen_retriever_registrar);
|
||||
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
|
||||
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
|
||||
g_autoptr(FlPluginRegistrar) window_manager_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "WindowManagerPlugin");
|
||||
window_manager_plugin_register_with_registrar(window_manager_registrar);
|
||||
}
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
#
|
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
screen_retriever
|
||||
url_launcher_linux
|
||||
window_manager
|
||||
)
|
||||
|
||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||
|
||||
@@ -5,12 +5,8 @@
|
||||
import FlutterMacOS
|
||||
import Foundation
|
||||
|
||||
import screen_retriever
|
||||
import url_launcher_macos
|
||||
import window_manager
|
||||
|
||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
ScreenRetrieverPlugin.register(with: registry.registrar(forPlugin: "ScreenRetrieverPlugin"))
|
||||
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
|
||||
WindowManagerPlugin.register(with: registry.registrar(forPlugin: "WindowManagerPlugin"))
|
||||
}
|
||||
|
||||
16
pubspec.lock
16
pubspec.lock
@@ -208,14 +208,6 @@ packages:
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.2.1"
|
||||
screen_retriever:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: screen_retriever
|
||||
sha256: "6ee02c8a1158e6dae7ca430da79436e3b1c9563c8cf02f524af997c201ac2b90"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.1.9"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
@@ -364,14 +356,6 @@ packages:
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.1.4-beta"
|
||||
window_manager:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: window_manager
|
||||
sha256: dcc865277f26a7dad263a47d0e405d77e21f12cb71f30333a52710a408690bd7
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.3.7"
|
||||
sdks:
|
||||
dart: ">=3.1.1 <4.0.0"
|
||||
flutter: ">=3.13.0"
|
||||
|
||||
@@ -31,7 +31,7 @@ dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
flutter_colorpicker: ^1.0.3
|
||||
window_manager: ^0.3.7
|
||||
# window_manager: ^0.3.7
|
||||
adaptive_navigation: ^0.0.4
|
||||
go_router: ^10.1.0
|
||||
provider: 6.0.5
|
||||
|
||||
@@ -6,15 +6,9 @@
|
||||
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <screen_retriever/screen_retriever_plugin.h>
|
||||
#include <url_launcher_windows/url_launcher_windows.h>
|
||||
#include <window_manager/window_manager_plugin.h>
|
||||
|
||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||
ScreenRetrieverPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("ScreenRetrieverPlugin"));
|
||||
UrlLauncherWindowsRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("UrlLauncherWindows"));
|
||||
WindowManagerPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("WindowManagerPlugin"));
|
||||
}
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
#
|
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
screen_retriever
|
||||
url_launcher_windows
|
||||
window_manager
|
||||
)
|
||||
|
||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||
|
||||
@@ -28,7 +28,7 @@ bool FlutterWindow::OnCreate() {
|
||||
SetChildContent(flutter_controller_->view()->GetNativeWindow());
|
||||
|
||||
flutter_controller_->engine()->SetNextFrameCallback([&]() {
|
||||
// this->Show();
|
||||
this->Show();
|
||||
//delete this->Show()
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user