diff --git a/lib/10/app_info.dart b/lib/10/app_info.dart new file mode 100644 index 0000000..3d990c8 --- /dev/null +++ b/lib/10/app_info.dart @@ -0,0 +1,46 @@ +import 'package:flutter/material.dart'; + +class AppInfo extends StatelessWidget { + const AppInfo({super.key}); + + @override + Widget build(BuildContext context) { + const String msg = 'FlutterUnit 是一个辅助开发者,了解 Flutter 组件和编程技术的开源项目。 '; + const String msg2 = '由张风捷特烈维护,开源地址:\n https://github.com/toly1994328/FlutterUnit '; + + double height = MediaQuery.of(context).size.height; + return SizedBox( + height: height*(1-0.618), + child: Column( + children: [ + AppBar( + backgroundColor: Colors.transparent, + automaticallyImplyLeading: false, + centerTitle: true, + leading: Align(child: FlutterLogo()), + actions: [ + CloseButton() + ], + title: Column( + children: [ + Text('FlutterUnit',style: TextStyle(fontSize: 16,fontWeight: FontWeight.bold)), + Text('v2.9.3',style: TextStyle(fontSize: 12,),), + ], + ),), + const Padding( + padding: EdgeInsets.symmetric(horizontal: 20.0,vertical: 10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + // direction: Axis.vertical, + children: [ + Text(msg,style: TextStyle(color: Colors.grey),), + const SizedBox(height: 8,), + Text(msg2,style: TextStyle(color: Colors.grey),), + ], + ), + ), + ], + ), + ); + } +} diff --git a/lib/10/cupertino_context_menu_demo.dart b/lib/10/cupertino_context_menu_demo.dart new file mode 100644 index 0000000..d478745 --- /dev/null +++ b/lib/10/cupertino_context_menu_demo.dart @@ -0,0 +1,107 @@ +// Copyright 2014 The Flutter Authors. 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/cupertino.dart'; +import 'package:flutter/material.dart'; + +/// Flutter code sample for [CupertinoContextMenu]. + +final DecorationTween _tween = DecorationTween( + begin: BoxDecoration( + color: CupertinoColors.systemPurple, + boxShadow: const [], + borderRadius: BorderRadius.circular(20.0), + ), + end: BoxDecoration( + color: CupertinoColors.systemPurple, + boxShadow: CupertinoContextMenu.kEndBoxShadow, + borderRadius: BorderRadius.circular(20.0), + ), +); + +class CupertinoContextMenuDemo extends StatelessWidget { + const CupertinoContextMenuDemo({super.key}); + + // Or just do this inline in the builder below? + static Animation _boxDecorationAnimation( + Animation animation) { + return _tween.animate( + CurvedAnimation( + parent: animation, + curve: Interval( + 0.0, + CupertinoContextMenu.animationOpensAt, + ), + ), + ); + } + + @override + Widget build(BuildContext context) { + return CupertinoPageScaffold( + navigationBar: const CupertinoNavigationBar( + middle: Text('CupertinoContextMenu 案例'), + ), + child: Center( + child: SizedBox( + width: 100, + height: 100, + child: CupertinoContextMenu.builder( + actions: [ + CupertinoContextMenuAction( + onPressed: () { + Navigator.pop(context); + }, + isDefaultAction: true, + trailingIcon: CupertinoIcons.doc_on_clipboard_fill, + child: const Text('Copy'), + ), + CupertinoContextMenuAction( + onPressed: () { + Navigator.pop(context); + }, + trailingIcon: CupertinoIcons.share, + child: const Text('Share'), + ), + CupertinoContextMenuAction( + onPressed: () { + Navigator.pop(context); + }, + trailingIcon: CupertinoIcons.heart, + child: const Text('Favorite'), + ), + CupertinoContextMenuAction( + onPressed: () { + Navigator.pop(context); + }, + isDestructiveAction: true, + trailingIcon: CupertinoIcons.delete, + child: const Text('Delete'), + ), + ], + builder: (BuildContext context, Animation animation) { + final Animation boxDecorationAnimation = + _boxDecorationAnimation(animation); + + return Container( + decoration: + animation.value < CupertinoContextMenu.animationOpensAt + ? boxDecorationAnimation.value + : null, + child: Container( + padding: EdgeInsets.all(20), + decoration: BoxDecoration( + color: CupertinoColors.systemPurple, + borderRadius: BorderRadius.circular(20.0), + ), + child: const FlutterLogo(size: 250.0), + ), + ); + }, + ), + ), + ), + ); + } +} diff --git a/lib/10/dropdown_button_color.dart b/lib/10/dropdown_button_color.dart new file mode 100644 index 0000000..557c027 --- /dev/null +++ b/lib/10/dropdown_button_color.dart @@ -0,0 +1,83 @@ +// Copyright 2014 The Flutter Authors. 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'; + +/// Flutter code sample for [DropdownButton.selectedItemBuilder]. + +const Map kColors = { + '红色': Colors.red, + '黄色': Colors.yellowAccent, + '蓝色': Colors.blue, + '绿色': Colors.greenAccent, + '橙色': Colors.orange, + '紫色': Colors.purple, +}; + +class DropdownButtonColor extends StatefulWidget { + const DropdownButtonColor({super.key}); + + @override + State createState() => _DropdownButtonColorState(); +} + +class _DropdownButtonColorState extends State { + String selectedItem = kColors.keys.first; + + @override + Widget build(BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text('选择颜色:', style: Theme.of(context).textTheme.bodyLarge), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 8.0), + child: DropdownButton( + value: selectedItem, + onChanged: (String? value) { + setState(() => selectedItem = value!); + }, + selectedItemBuilder: _buildSelectItem, + items: _buildItems(), + ), + ), + ], + ); + } + + List> _buildItems(){ + return kColors.keys.map>((String key) { + return DropdownMenuItem( + value: key, + child: Wrap( + spacing: 4, + crossAxisAlignment: WrapCrossAlignment.center, + children: [ + Container( + width: 14, + height: 14, + decoration: BoxDecoration( + color: kColors[key], + borderRadius: BorderRadius.circular(2)), + ), + Text(key), + ], + ), + ); + }).toList(); + } + + List _buildSelectItem(BuildContext context) { + return kColors.values.map((Color color) { + return Align( + child: Container( + decoration: BoxDecoration( + color: color, + borderRadius: BorderRadius.circular(2)), + constraints: const BoxConstraints(minWidth: 24,maxHeight: 24), + ), + ); + }).toList(); + } +} diff --git a/lib/10/main.dart b/lib/10/main.dart new file mode 100644 index 0000000..b601355 --- /dev/null +++ b/lib/10/main.dart @@ -0,0 +1,137 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_localizations/flutter_localizations.dart'; + +import 'app_info.dart'; +import 'cupertino_context_menu_demo.dart'; +import 'dropdown_button_color.dart'; +import 'more_pop_icon.dart'; +import 'search_anchor_demo.dart'; + +void main() { + runApp(const MyApp()); +} + +class MyApp extends StatelessWidget { + const MyApp({super.key}); + + @override + Widget build(BuildContext context) { + return MaterialApp( + title: 'Flutter Demo', + localizationsDelegates: GlobalMaterialLocalizations.delegates, + supportedLocales: const [ + Locale('zh', 'CN'), + ], + locale: const Locale('zh', 'CN'), + debugShowCheckedModeBanner: false, + theme: ThemeData( + colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), + useMaterial3: true, + ), + home: const HomePage(), + ); + } +} + + +class HomePage extends StatefulWidget { + const HomePage({super.key}); + + @override + State createState() => _HomePageState(); +} + +class _HomePageState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text("弹出层测试"), + actions: [ + MorePopIcon(onTapItem: _onTapItem,) + ], + ), + body: Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + ElevatedButton( + onPressed: showConformDialog, + child: Text('关于应用'), + ), + DropdownButtonColor(), + ElevatedButton( + onPressed: _showModalBottomSheet, + child: Text('showModalBottomSheet'), + ), + ElevatedButton( + onPressed: _showCupertinoModalPopup, + child: Text('showCupertinoModalPopup'), + ), + ElevatedButton( + onPressed: _toSearchAnchor, + child: Text('SearchAnchor 案例'), + ), ElevatedButton( + onPressed: _toCupertinoContextMenu, + child: Text('CupertinoContextMenu 案例'), + ), + ], + ), + ), + ); + } + + void showConformDialog(){ + showDialog(context: context, builder: _buildAbout); + // showCupertinoModalPopup(context: context, builder: builder) + // showCupertinoDialog(context: context, builder: _buildAbout); + } + + void _showModalBottomSheet(){ + showModalBottomSheet( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8) + ), + context: context, builder: (_)=>AppInfo()); + } + + void _showCupertinoModalPopup(){ + showCupertinoModalPopup( + context: context, builder: (_)=>Material(child: const AppInfo())); + } + + Widget _buildAbout(BuildContext context){ + const String msg = 'FlutterUnit 是一个辅助开发者,了解 Flutter 组件和编程技术的开源项目。'; + return const AboutDialog( + applicationName: "FlutterUnit", + applicationVersion: "v2.9.3", + applicationIcon: FlutterLogo(), + children: [ + Text(msg,style: TextStyle(color: Colors.grey),) + ], + ); + } + + void _onTapItem(MenuAction value) { + print(value.label); + switch(value){ + case MenuAction.setting: + break; + case MenuAction.about: + showConformDialog(); + break; + case MenuAction.help: + break; + } + } + + void _toSearchAnchor() { + Navigator.of(context).push(MaterialPageRoute(builder: (_)=>SearchAnchorDemo())); + + } + + void _toCupertinoContextMenu() { + Navigator.of(context).push(MaterialPageRoute(builder: (_)=>CupertinoContextMenuDemo())); + } +} diff --git a/lib/10/more_pop_icon.dart b/lib/10/more_pop_icon.dart new file mode 100644 index 0000000..1417ffb --- /dev/null +++ b/lib/10/more_pop_icon.dart @@ -0,0 +1,58 @@ +import 'package:flutter/material.dart'; + +enum MenuAction implements Comparable { + setting(label: '应用设置', iconData: Icons.settings), + about(label: '关于应用', iconData: Icons.info), + help(label: '帮助中心', iconData: Icons.help); + + final String label; + final IconData iconData; + + const MenuAction({ + required this.label, + required this.iconData, + }); + + @override + int compareTo(MenuAction other) => label.compareTo(other.label); + + bool operator >(MenuAction other) { + return compareTo(other) > 0; + } +} + +class MorePopIcon extends StatelessWidget { + final ValueChanged onTapItem; + const MorePopIcon({super.key, required this.onTapItem}); + + @override + Widget build(BuildContext context) { + return PopupMenuButton( + itemBuilder: _buildItem, + onSelected: onTapItem, + icon: const Icon(Icons.more_vert_outlined), + position: PopupMenuPosition.under, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(10)), + ), + ); + } + + List> _buildItem(BuildContext context) { + return MenuAction.values + .map((MenuAction action) => PopupMenuItem( + height: 35, + value: action, + child: Center( + child: Wrap( + crossAxisAlignment: WrapCrossAlignment.center, + spacing: 6, + children: [ + Text(action.label), + Icon(action.iconData, size: 18), + ], + )), + )) + .toList(); + } +} diff --git a/lib/10/search_anchor_demo.dart b/lib/10/search_anchor_demo.dart new file mode 100644 index 0000000..1fda44b --- /dev/null +++ b/lib/10/search_anchor_demo.dart @@ -0,0 +1,162 @@ +// Copyright 2014 The Flutter Authors. 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 SearchAnchorDemo extends StatefulWidget { + const SearchAnchorDemo({super.key}); + + @override + State createState() => _SearchAnchorDemoState(); +} + +class _SearchAnchorDemoState extends State { + Color? selectedColorSeed; + List searchHistory = []; + + Iterable getHistoryList(SearchController controller) { + return searchHistory.map( + (ColorLabel color) => ListTile( + leading: const Icon(Icons.history), + title: Text(color.label), + trailing: IconButton( + icon: const Icon(Icons.call_missed), + onPressed: () { + controller.text = color.label; + controller.selection = TextSelection.collapsed(offset: controller.text.length); + }, + ), + ), + ); + } + + Iterable getSuggestions(SearchController controller) { + final String input = controller.value.text; + return ColorLabel.values.where((ColorLabel color) => color.label.contains(input)).map( + (ColorLabel filteredColor) => ListTile( + leading: CircleAvatar(backgroundColor: filteredColor.color), + title: Text(filteredColor.label), + trailing: IconButton( + icon: const Icon(Icons.call_missed), + onPressed: () { + controller.text = filteredColor.label; + controller.selection = TextSelection.collapsed(offset: controller.text.length); + }, + ), + onTap: () { + controller.closeView(filteredColor.label); + handleSelection(filteredColor); + }, + ), + ); + } + + void handleSelection(ColorLabel selectedColor) { + setState(() { + selectedColorSeed = selectedColor.color; + if (searchHistory.length >= 5) { + searchHistory.removeLast(); + } + searchHistory.insert(0, selectedColor); + }); + } + + Map colorMaps(ColorScheme colors) => { + 'primary':colors.primary , + 'secondary':colors.secondary , + 'inverseSurface':colors.inverseSurface , + 'background':colors.background , + + + 'onPrimaryContainer':colors.onPrimaryContainer , + 'onErrorContainer':colors.onErrorContainer , + 'onBackground':colors.onBackground , + 'onTertiaryContainer':colors.onTertiaryContainer , + + + 'error':colors.error , + 'inversePrimary':colors.inversePrimary , + 'primaryContainer':colors.primaryContainer , + 'errorContainer':colors.errorContainer , + + 'onPrimary':colors.onPrimary , + 'onSecondary':colors.onSecondary , + 'onError':colors.onError , + 'onTertiary':colors.onTertiary , + 'onSurfaceVariant':colors.onSurfaceVariant , + 'shadow':colors.shadow , + }; + + + + @override + Widget build(BuildContext context) { + final ThemeData themeData = ThemeData(useMaterial3: true, colorSchemeSeed: selectedColorSeed); + final ColorScheme colors = themeData.colorScheme; + Map data = colorMaps(colors); + SizedBox cardSize = const SizedBox( + width: 80, + height: 30, + child: Text(''), + ); + + return Scaffold( + appBar: AppBar(title: const Text('搜索颜色')), + body: Align( + alignment: Alignment.topCenter, + child: Column( + children: [ + SearchAnchor.bar( + barHintText: '输入颜色', + suggestionsBuilder: (BuildContext context, SearchController controller) { + if (controller.text.isEmpty) { + if (searchHistory.isNotEmpty) { + return getHistoryList(controller); + } + return [Center(child: Text('暂无历史记录.', style: TextStyle(color: colors.outline)))]; + } + return getSuggestions(controller); + }, + ), + cardSize, + Wrap( + children: data.keys.map((key) => Card(color: data[key], child: SizedBox( + width: 80, + height: 30, + child: Center(child: Text(key,style: TextStyle(fontSize: 8,color: Colors.white,shadows: [ + BoxShadow(color: Colors.black,offset: Offset(.1,.1),blurRadius: 2) + ]),)), + ))).toList(), + ), + + ], + ), + ), + ); + } +} + + +enum ColorLabel { + red('red', Colors.red), + orange('orange', Colors.orange), + yellow('yellow', Colors.yellow), + green('green', Colors.green), + blue('blue', Colors.blue), + indigo('indigo', Colors.indigo), + violet('violet', Color(0xFF8F00FF)), + purple('purple', Colors.purple), + pink('pink', Colors.pink), + silver('silver', Color(0xFF808080)), + gold('gold', Color(0xFFFFD700)), + beige('beige', Color(0xFFF5F5DC)), + brown('brown', Colors.brown), + grey('grey', Colors.grey), + black('black', Colors.black), + white('white', Colors.white); + + const ColorLabel(this.label, this.color); + final String label; + final Color color; +} diff --git a/lib/11/color_detail.dart b/lib/11/color_detail.dart new file mode 100644 index 0000000..4c3a208 --- /dev/null +++ b/lib/11/color_detail.dart @@ -0,0 +1,24 @@ +import 'package:flutter/material.dart'; + +class ColorDetailPage extends StatelessWidget { + final Color color; + const ColorDetailPage({super.key, required this.color}); + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: color, + appBar: AppBar( + centerTitle: true, + iconTheme: IconThemeData(color: Colors.white), + titleTextStyle: TextStyle(color: Colors.white,fontSize: 16,fontWeight: FontWeight.bold), + backgroundColor: color, + title: Text('颜色详情页'), + ), + body: Center( + child: Text( '#${color.value.toRadixString(16)}',style: TextStyle(color: Colors.white,fontSize: 26,fontWeight: FontWeight.bold),), + ), + ); + } +} + diff --git a/lib/11/color_page.dart b/lib/11/color_page.dart new file mode 100644 index 0000000..dc1bead --- /dev/null +++ b/lib/11/color_page.dart @@ -0,0 +1,66 @@ +import 'package:flutter/material.dart'; +import '../common/components/colors_panel.dart'; +import 'color_detail.dart'; +import 'transition.dart'; + +class ColorPage extends StatefulWidget { + const ColorPage({super.key}); + + @override + State createState() => _ColorPageState(); +} + +class _ColorPageState extends State { + final List _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) { + Route route = PageRouteBuilder( + barrierColor: Colors.white, + pageBuilder: (_, __, ___) => ColorDetailPage(color:color), + transitionsBuilder: kSlideBottomToTopWithSecondary, + ); + Navigator.push(context, route); + // Navigator.push( + // context, + // MaterialPageRoute(builder: (_)=>ColorDetailPage(color:color))); + } + + void _toAddPage() { + } +} diff --git a/lib/11/main.dart b/lib/11/main.dart new file mode 100644 index 0000000..482c742 --- /dev/null +++ b/lib/11/main.dart @@ -0,0 +1,72 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_localizations/flutter_localizations.dart'; +import 'package:iroute/11/transition.dart'; + +import 'color_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', + localizationsDelegates: GlobalMaterialLocalizations.delegates, + supportedLocales: const [ + Locale('zh', 'CN'), + ], + locale: const Locale('zh', 'CN'), + debugShowCheckedModeBanner: false, + theme: ThemeData( + colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), + useMaterial3: true, + ), + home: const HomePage(), + ); + } +} + +class HomePage extends StatefulWidget { + const HomePage({super.key}); + + @override + State createState() => _HomePageState(); +} + +class _HomePageState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text("Cose 酷色"), + ), + body: Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + ElevatedButton( + onPressed: _toColorHome, + child: Text('打开颜色界面'), + ), + ], + ), + ), + ); + } + + void _toColorHome() { + Route route = PageRouteBuilder( + barrierColor: Colors.white, + pageBuilder: (_, __, ___) => const ColorPage(), + transitionsBuilder: kSlideBottomToTopWithSecondary, + ); + Navigator.push(context, route); + // Navigator.pushReplacement(context, route); + + } +} diff --git a/lib/11/transition.dart b/lib/11/transition.dart new file mode 100644 index 0000000..34e6955 --- /dev/null +++ b/lib/11/transition.dart @@ -0,0 +1,22 @@ +import 'package:flutter/material.dart'; + +RouteTransitionsBuilder kSlideBottomToTopWithSecondary = ( + BuildContext context, + Animation animation, + Animation secondaryAnimation, + Widget child, +) { + return SlideTransition( + position: Tween( + begin: const Offset(0.0, 1.0), + end: Offset.zero, + ).animate(animation), + child: SlideTransition( + position: Tween( + begin: Offset.zero, + end: const Offset(0.0, 1.0), + ).animate(secondaryAnimation), + child: child, + ), + ); +}; diff --git a/pubspec.lock b/pubspec.lock index 0a1e86d..bad937c 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -102,6 +102,11 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "2.0.2" + flutter_localizations: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" flutter_test: dependency: "direct dev" description: flutter @@ -120,6 +125,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "10.1.0" + intl: + dependency: transitive + description: + name: intl + sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d" + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.18.1" lints: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 7fcec05..5179f40 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -30,6 +30,8 @@ environment: dependencies: flutter: sdk: flutter + flutter_localizations: + sdk: flutter flutter_colorpicker: ^1.0.3 # window_manager: ^0.3.7 adaptive_navigation: ^0.0.4 @@ -43,8 +45,8 @@ dependencies: # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.2 - toly_menu: - path: E:\Projects\Flutter\packages\toly_menu +# toly_menu: +# path: E:\Projects\Flutter\packages\toly_menu dev_dependencies: flutter_test: diff --git a/test/parser/main.dart b/test/parser/main.dart index 403d9a6..160a4a5 100644 --- a/test/parser/main.dart +++ b/test/parser/main.dart @@ -1,20 +1,9 @@ +import 'package:iroute/10/more_pop_icon.dart'; import 'package:iroute/13/04/app/navigation/router/iroute.dart'; void main() { - String path = '/color/detail/a'; - // List parts = path.split('/'); - // print(parts); - // print(parserPath(path)); - - Uri uri = Uri.parse(path); - print(uri.fragment); - print(uri.pathSegments); - - List parts = uri.pathSegments; - - parts = List.of(parts)..removeLast(); - String result = parts.join('/'); - print(result); + bool b = MenuAction.help > MenuAction.about; + print(b); }