diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 4f77e0fd..bb4e86ed 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -10,6 +10,7 @@ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 333E5DAE7FC10AC69FEC26C0 /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DDA792F029EDD7A11295D192 /* libPods-Runner.a */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */ = {isa = PBXBuildFile; fileRef = 2D5378251FAA1A9400D5DBA9 /* flutter_assets */; }; 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; }; 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; }; @@ -40,6 +41,7 @@ 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 2D5378251FAA1A9400D5DBA9 /* flutter_assets */ = {isa = PBXFileReference; lastKnownFileType = folder; name = flutter_assets; path = Flutter/flutter_assets; sourceTree = SOURCE_ROOT; }; 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; @@ -90,6 +92,7 @@ children = ( 3B80C3931E831B6300D905FE /* App.framework */, 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 2D5378251FAA1A9400D5DBA9 /* flutter_assets */, 9740EEBA1CF902C7004384FC /* Flutter.framework */, 9740EEB21CF90195004384FC /* Debug.xcconfig */, 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, @@ -206,6 +209,7 @@ files = ( 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */, 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, ); diff --git a/lib/common/widget_name_to_icon.dart b/lib/common/widget_name_to_icon.dart index fa123118..909bf110 100644 --- a/lib/common/widget_name_to_icon.dart +++ b/lib/common/widget_name_to_icon.dart @@ -153,5 +153,7 @@ class WidgetName2Icon { "CupertinoNavigationBar":Icons.payment, "CupertinoPageRoute":Icons.router, "CupertinoPageScaffold":Icons.pages, + "CupertinoPicker":Icons.add_alarm, + "CupertinoPopupSurface":Icons.center_focus_weak, }; } diff --git a/lib/widgets/themes/Cupertino/CupertinoPicker/demo.dart b/lib/widgets/themes/Cupertino/CupertinoPicker/demo.dart new file mode 100644 index 00000000..6a327ab9 --- /dev/null +++ b/lib/widgets/themes/Cupertino/CupertinoPicker/demo.dart @@ -0,0 +1,291 @@ +/** + * Created with Android Studio. + * User: ryan + * Date: 2019/1/20 + * Time: 上午11:34 + * email: zhu.yan@alibaba-inc.com + * tartget: CupertinoPageScaffold 的示例 + */ + +import 'package:flutter/cupertino.dart'; +import 'package:intl/intl.dart'; + +//import '../../gallery/demo.dart'; +//import 'cupertino_navigation_demo.dart' show coolColorNames; + +const double _kPickerSheetHeight = 216.0; +const double _kPickerItemHeight = 32.0; + +const List coolColorNames = [ + 'Sarcoline', 'Coquelicot', 'Smaragdine', 'Mikado', 'Glaucous', 'Wenge', + 'Fulvous', 'Xanadu', 'Falu', 'Eburnean', 'Amaranth', 'Australien', + 'Banan', 'Falu', 'Gingerline', 'Incarnadine', 'Labrador', 'Nattier', + 'Pervenche', 'Sinoper', 'Verditer', 'Watchet', 'Zaffre', +]; + +class CupertinoPickerDemo extends StatefulWidget { + static const String routeName = '/cupertino/picker'; + + @override + _CupertinoPickerDemoState createState() => _CupertinoPickerDemoState(); +} + +class _CupertinoPickerDemoState extends State { + int _selectedColorIndex = 0; + + Duration timer = const Duration(); + + // Value that is shown in the date picker in date mode. + DateTime date = DateTime.now(); + + // Value that is shown in the date picker in time mode. + DateTime time = DateTime.now(); + + // Value that is shown in the date picker in dateAndTime mode. + DateTime dateTime = DateTime.now(); + + Widget _buildMenu(List children) { + return Container( + decoration: BoxDecoration( + color: CupertinoTheme.of(context).scaffoldBackgroundColor, + border: const Border( + top: BorderSide(color: Color(0xFFBCBBC1), width: 0.0), + bottom: BorderSide(color: Color(0xFFBCBBC1), width: 0.0), + ), + ), + height: 44.0, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: SafeArea( + top: false, + bottom: false, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: children, + ), + ), + ), + ); + } + + Widget _buildBottomPicker(Widget picker) { + return Container( + height: _kPickerSheetHeight, + padding: const EdgeInsets.only(top: 6.0), + color: CupertinoColors.white, + child: DefaultTextStyle( + style: const TextStyle( + color: CupertinoColors.black, + fontSize: 22.0, + ), + child: GestureDetector( + // Blocks taps from propagating to the modal sheet and popping. + onTap: () {}, + child: SafeArea( + top: false, + child: picker, + ), + ), + ), + ); + } + + Widget _buildColorPicker(BuildContext context) { + final FixedExtentScrollController scrollController = + FixedExtentScrollController(initialItem: _selectedColorIndex); + + return GestureDetector( + onTap: () async { + await showCupertinoModalPopup( + context: context, + builder: (BuildContext context) { + return _buildBottomPicker( + CupertinoPicker( + magnification:1.0, // 整体放大率 + //offAxisFraction:10.0,// 球面效果的透视系数,消失点位置 + scrollController: scrollController,// 用于读取和控制当前项的FixedxtentScrollController + itemExtent: _kPickerItemHeight,// 所以子节点 统一高度 + backgroundColor: CupertinoColors.white,// 所有子节点下面的背景颜色 + useMagnifier:true,// 是否使用放大效果 + onSelectedItemChanged: (int index) { // 当正中间选项改变时的回调 + setState(() => _selectedColorIndex = index); + }, + children: List.generate(coolColorNames.length, (int index) { + return Center(child: + Text(coolColorNames[index]), + ); + }), + ), + ); + }, + ); + }, + child: _buildMenu( + [ + const Text('Favorite Color'), + Text( + coolColorNames[_selectedColorIndex], + style: const TextStyle( + color: CupertinoColors.inactiveGray + ), + ), + ], + ), + ); + } + + Widget _buildCountdownTimerPicker(BuildContext context) { + return GestureDetector( + onTap: () { + showCupertinoModalPopup( + context: context, + builder: (BuildContext context) { + return _buildBottomPicker( + CupertinoTimerPicker( + initialTimerDuration: timer, + onTimerDurationChanged: (Duration newTimer) { + setState(() => timer = newTimer); + }, + ), + ); + }, + ); + }, + child: _buildMenu( + [ + const Text('Countdown Timer'), + Text( + '${timer.inHours}:' + '${(timer.inMinutes % 60).toString().padLeft(2,'0')}:' + '${(timer.inSeconds % 60).toString().padLeft(2,'0')}', + style: const TextStyle(color: CupertinoColors.inactiveGray), + ), + ], + ), + ); + } + + Widget _buildDatePicker(BuildContext context) { + return GestureDetector( + onTap: () { + showCupertinoModalPopup( + context: context, + builder: (BuildContext context) { + return _buildBottomPicker( + CupertinoDatePicker( + mode: CupertinoDatePickerMode.date, + initialDateTime: date, + onDateTimeChanged: (DateTime newDateTime) { + setState(() => date = newDateTime); + }, + ), + ); + }, + ); + }, + child: _buildMenu( + [ + const Text('Date'), + Text( + DateFormat.yMMMMd().format(date), + style: const TextStyle(color: CupertinoColors.inactiveGray), + ), + ] + ), + ); + } + + Widget _buildTimePicker(BuildContext context) { + return GestureDetector( + onTap: () { + showCupertinoModalPopup( + context: context, + builder: (BuildContext context) { + return _buildBottomPicker( + CupertinoDatePicker( + mode: CupertinoDatePickerMode.time, + initialDateTime: time, + onDateTimeChanged: (DateTime newDateTime) { + setState(() => time = newDateTime); + }, + ), + ); + }, + ); + }, + child: _buildMenu( + [ + const Text('Time'), + Text( + DateFormat.jm().format(time), + style: const TextStyle(color: CupertinoColors.inactiveGray), + ), + ], + ), + ); + } + + Widget _buildDateAndTimePicker(BuildContext context) { + return GestureDetector( + onTap: () { + showCupertinoModalPopup( + context: context, + builder: (BuildContext context) { + return _buildBottomPicker( + CupertinoDatePicker( + mode: CupertinoDatePickerMode.dateAndTime, + initialDateTime: dateTime, + onDateTimeChanged: (DateTime newDateTime) { + setState(() => dateTime = newDateTime); + }, + ), + ); + }, + ); + }, + child: _buildMenu( + [ + const Text('Date and Time'), + Text( + DateFormat.yMMMd().add_jm().format(dateTime), + style: const TextStyle(color: CupertinoColors.inactiveGray), + ), + ], + ), + ); + } + + @override + Widget build(BuildContext context) { + return SizedBox( + height:MediaQuery.of(context).size.height, + child:CupertinoPageScaffold( +// navigationBar: CupertinoNavigationBar( +// middle: const Text('Picker'), +// previousPageTitle: 'Cupertino' +// ), + child: DefaultTextStyle( + style: CupertinoTheme.of(context).textTheme.textStyle, + child: DecoratedBox( + decoration: BoxDecoration( + color: CupertinoTheme.of(context).brightness == Brightness.light + ? CupertinoColors.extraLightBackgroundGray + : CupertinoColors.darkBackgroundGray, + ), + child: ListView( + children: [ + const Padding(padding: EdgeInsets.only(top: 32.0)), + _buildColorPicker(context), + _buildCountdownTimerPicker(context), + _buildDatePicker(context), + _buildTimePicker(context), + _buildDateAndTimePicker(context), + ], + ), + ), + ), + ) + ); + + } +} diff --git a/lib/widgets/themes/Cupertino/CupertinoPicker/index.dart b/lib/widgets/themes/Cupertino/CupertinoPicker/index.dart new file mode 100644 index 00000000..30ab6e2e --- /dev/null +++ b/lib/widgets/themes/Cupertino/CupertinoPicker/index.dart @@ -0,0 +1,45 @@ +/** + * Created with Android Studio. + * User: 一晟 + * Date: 2019/1/20 + * Time: 下午10:57 + * email: zhu.yan@alibaba-inc.com + * tartget: CupertinoPicker 的示例 + */ +import 'package:flutter/material.dart'; +import '../../../../common/widget_demo.dart'; +import './demo.dart' as demoBox; + +const String content0 = ''' +### **简介** +> iOS风格的选择器 +- 以 wheel 的方式显示子 widget,选择发生改变后的回调; +- 通常和 showModalBottomSheet 搭配在屏幕底部显示 picker 选择器; +'''; + +const String content1 = ''' +### **基本用法** +> CupertinoPicker 的一个示例 +'''; + +class Demo extends StatefulWidget { + static const String routeName = '/themes/Cupertino/CupertinoPicker'; + _DemoState createState() => _DemoState(); +} + +class _DemoState extends State { + @override + Widget build(BuildContext context) { + return WidgetDemo( + contentList: [ + content0, + content1, + demoBox.CupertinoPickerDemo(), + SizedBox(height:50) + ], + title: 'CupertinoPicker', + docUrl: 'https://docs.flutter.io/flutter/cupertino/CupertinoPicker-class.html', + codeUrl: '/themes/Cupertino/CupertinoPicker/demo.dart', + ); + } +} \ No newline at end of file diff --git a/lib/widgets/themes/Cupertino/CupertinoPopupSurface/demo.dart b/lib/widgets/themes/Cupertino/CupertinoPopupSurface/demo.dart new file mode 100644 index 00000000..92651e4d --- /dev/null +++ b/lib/widgets/themes/Cupertino/CupertinoPopupSurface/demo.dart @@ -0,0 +1,45 @@ +/** + * Created with Android Studio. + * User: ryan + * Date: 2019/1/20 + * Time: 上午11:34 + * email: zhu.yan@alibaba-inc.com + * tartget: CupertinoPopupSurface 的示例 + */ + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +/* +* CupertinoPopupSurface 默认的实例 +* */ +class CupertinoPopupSurfaceFullDefault extends StatefulWidget { + const CupertinoPopupSurfaceFullDefault() : super(); + + @override + State createState() => _CupertinoPopupSurfaceFullDefault(); +} + +/* +* CupertinoPopupSurface 默认的实例,有状态 +* */ +class _CupertinoPopupSurfaceFullDefault extends State { + @override + Widget build(BuildContext context) { + return SizedBox( + height: MediaQuery.of(context).size.height/5, + child: CupertinoPopupSurfaceBar(context) + ); + } + + Widget CupertinoPopupSurfaceBar(BuildContext context) { + return CupertinoPopupSurface( + isSurfacePainted:false, + child: Container( + color: CupertinoColors.inactiveGray, + alignment: Alignment.center, + child: Text('这里是内容', style: TextStyle(color: Colors.white)) + ), // 应用程序默认路由,(Navigator.defaultRouteName,即/) + ); + } +} diff --git a/lib/widgets/themes/Cupertino/CupertinoPopupSurface/index.dart b/lib/widgets/themes/Cupertino/CupertinoPopupSurface/index.dart new file mode 100644 index 00000000..742a6134 --- /dev/null +++ b/lib/widgets/themes/Cupertino/CupertinoPopupSurface/index.dart @@ -0,0 +1,44 @@ +/** + * Created with Android Studio. + * User: 一晟 + * Date: 2019/1/20 + * Time: 下午10:57 + * email: zhu.yan@alibaba-inc.com + * tartget: CupertinoPopupSurface 的示例 + */ +import 'package:flutter/material.dart'; +import '../../../../common/widget_demo.dart'; +import './demo.dart' as demoBox; + +const String content0 = ''' +### **简介** +> 像iOS弹出式表面 +- 快速实现一个圆角弹框,类似 alert dialog 和 sheet; +'''; + +const String content1 = ''' +### **基本用法** +> CupertinoPopupSurface 的一个示例 +'''; + +class Demo extends StatefulWidget { + static const String routeName = '/themes/Cupertino/CupertinoPopupSurface'; + _DemoState createState() => _DemoState(); +} + +class _DemoState extends State { + @override + Widget build(BuildContext context) { + return WidgetDemo( + contentList: [ + content0, + content1, + demoBox.CupertinoPopupSurfaceFullDefault(), + SizedBox(height:50) + ], + title: 'CupertinoPopupSurface', + docUrl: 'https://docs.flutter.io/flutter/cupertino/CupertinoPopupSurface-class.html', + codeUrl: '/themes/Cupertino/CupertinoPopupSurface/demo.dart', + ); + } +} \ No newline at end of file diff --git a/lib/widgets/themes/Cupertino/index.dart b/lib/widgets/themes/Cupertino/index.dart index a2a9200c..4a216d37 100644 --- a/lib/widgets/themes/Cupertino/index.dart +++ b/lib/widgets/themes/Cupertino/index.dart @@ -9,6 +9,8 @@ import './CupertinoIcons/index.dart' as CupertinoIcons; import './CupertinoNavigationBar/index.dart' as CupertinoNavigationBar; import './CupertinoPageRoute/index.dart' as CupertinoPageRoute; import './CupertinoPageScaffold/index.dart' as CupertinoPageScaffold; +import './CupertinoPicker/index.dart' as CupertinoPicker; +import './CupertinoPopupSurface/index.dart' as CupertinoPopupSurface; import './CupertinoScrollbar/index.dart' as CupertinoScrollbar; import './CupertinoSlider/index.dart' as CupertinoSlider; @@ -17,6 +19,16 @@ import './CupertinoSliverNavigationBar/index.dart' as CupertinoSliverNavigationB import './CupertinoSwitch/index.dart' as CupertinoSwitch; List widgetPoints = [ + WidgetPoint( + name: 'CupertinoPopupSurface', + routerName: CupertinoPopupSurface.Demo.routeName, + buildRouter: (BuildContext context) => CupertinoPopupSurface.Demo(), + ), + WidgetPoint( + name: 'CupertinoPicker', + routerName: CupertinoPicker.Demo.routeName, + buildRouter: (BuildContext context) => CupertinoPicker.Demo(), + ), WidgetPoint( name: 'CupertinoPageScaffold', routerName: CupertinoPageScaffold.Demo.routeName, diff --git a/pubspec.yaml b/pubspec.yaml index 4baa4b5b..340db1b4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -30,6 +30,8 @@ dependencies: shared_preferences: ^0.4.3 dio: ^1.0.6 flutter_webview_plugin: ^0.3.0+2 + # 日期格式化 + intl: 0.15.7 dev_dependencies: flutter_test: