diff --git a/README.md b/README.md index 255123c..8429a7f 100644 --- a/README.md +++ b/README.md @@ -2,10 +2,10 @@ [![GitHub stars](https://img.shields.io/github/stars/toly1994328/FlutterUnit)](https://github.com/toly1994328/FlutterUnit/stargazers) [![GitHub forks](https://img.shields.io/github/forks/toly1994328/FlutterUnit)](https://github.com/toly1994328/FlutterUnit/network) [![GitHub license](https://img.shields.io/github/license/toly1994328/FlutterUnit)](https://github.com/toly1994328/FlutterUnit/blob/master/LICENSE) + ### FlutterUnit apk 下载体验: - -![](https://user-gold-cdn.xitu.io/2020/4/24/171a9911d22d34a8?w=300&h=390&f=png&s=22765) +![](https://toly1994328.gitee.io/photo/ewm/flutter_unit_ewm.png) > 当前Flutter 版本 @@ -18,6 +18,10 @@ Engine • revision e1e6ced81d Tools • Dart 2.7.0 ``` +#### Flutter Unit 周边 + +- 🔥 [Flutter Unit 更新记录 ](http://blog.toly1994.com/FlutterUnit_update.html) + --- diff --git a/assets/flutter.db b/assets/flutter.db index b9bb5c7..87d4826 100644 Binary files a/assets/flutter.db and b/assets/flutter.db differ diff --git a/assets/images/widgets/CircleAvatar.png b/assets/images/widgets/CircleAvatar.png deleted file mode 100644 index 45c3e43..0000000 Binary files a/assets/images/widgets/CircleAvatar.png and /dev/null differ diff --git a/assets/images/widgets/FadeInImage.png b/assets/images/widgets/FadeInImage.png deleted file mode 100644 index c11b3d3..0000000 Binary files a/assets/images/widgets/FadeInImage.png and /dev/null differ diff --git a/lib/components/permanent/code/back/code_panel.dart b/lib/components/permanent/code/back/code_panel.dart deleted file mode 100755 index f56cd38..0000000 --- a/lib/components/permanent/code/back/code_panel.dart +++ /dev/null @@ -1,66 +0,0 @@ -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; - -import '../high_light_code.dart'; -import '../highlighter_style.dart'; - - -class CodeWidget extends StatelessWidget { - CodeWidget({ - Key key, - @required this.code, - this.style, - this.fontSize = 13, - this.fontFamily, - }) : super(key: key); - - final String code; - final HighlighterStyle style; - final double fontSize; - final String fontFamily; - @override - Widget build(BuildContext context) { - if (code == null) { - return Container(); - } - - Widget _codeWidget = FutureBuilder( - future: compute(_hightlight, _HightlightArgs(style, code)), - builder: (context, snapshot) { - if (snapshot.hasError) { - return Text(code); - } - if (snapshot.hasData) - return RichText( - text: TextSpan( - children: [snapshot.data], - ), - ); - // computing - return SizedBox.shrink(); - }, - ); - - return SingleChildScrollView( - child: Container( - child: DefaultTextStyle( - child: _codeWidget, - style: TextStyle(fontSize: fontSize, fontFamily: fontFamily), - ), - padding: EdgeInsets.all(10), - decoration: BoxDecoration( - color: style.backgroundColor ?? Color(0xffF6F8FA), - borderRadius: BorderRadius.all(Radius.circular(5.0))), - ), - ); - } -} - -class _HightlightArgs { - final HighlighterStyle style; - final String code; - _HightlightArgs(this.style, this.code); -} - -TextSpan _hightlight(_HightlightArgs args) => - DartHighlighter(args.style).format(args.code); diff --git a/lib/components/project/widget_node_panel.dart b/lib/components/project/widget_node_panel.dart index 36662d9..e27af74 100644 --- a/lib/components/project/widget_node_panel.dart +++ b/lib/components/project/widget_node_panel.dart @@ -130,12 +130,12 @@ class _WidgetNodePanelState extends State { width: MediaQuery.of(context).size.width, child: CodeWidget( fontFamily: widget.codeFamily, - code: widget.code, + code: isFirst?'':widget.code, style: widget.codeStyle ?? HighlighterStyle.fromColors(HighlighterStyle.lightColor), ), ), - duration: Duration(milliseconds: 500), + duration: Duration(milliseconds: 200), crossFadeState: _crossFadeState, ); diff --git a/lib/storage/dao/node_dao.dart b/lib/storage/dao/node_dao.dart index 33b22e4..c8e3990 100644 --- a/lib/storage/dao/node_dao.dart +++ b/lib/storage/dao/node_dao.dart @@ -37,7 +37,7 @@ class NodeDao { return await db.rawQuery( "SELECT name,subtitle,code " "FROM node " - "WHERE widgetId = ?", + "WHERE widgetId = ? ORDER BY priority", [id]); } } diff --git a/lib/views/app/splash/unit_splash.dart b/lib/views/app/splash/unit_splash.dart index 914061b..0a07449 100644 --- a/lib/views/app/splash/unit_splash.dart +++ b/lib/views/app/splash/unit_splash.dart @@ -22,7 +22,6 @@ class UnitSplash extends StatefulWidget { class _UnitSplashState extends State with TickerProviderStateMixin { AnimationController _controller; - AnimationController _secondController; double _factor; Animation _curveAnim; @@ -42,17 +41,12 @@ class _UnitSplashState extends State with TickerProviderStateMixin { if (s == AnimationStatus.completed) { setState(() { _animEnd = true; - _secondController.forward(); + Future.delayed(Duration(milliseconds: 600)).then((e){ + Navigator.of(context).pushReplacementNamed(Router.nav); + }); }); } }); - _secondController = - AnimationController(duration: Duration(milliseconds: 600), vsync: this) - ..addStatusListener((s) { - if (s == AnimationStatus.completed) { - Navigator.of(context).pushReplacementNamed(Router.nav); - } - }); _curveAnim = CurvedAnimation(parent: _controller, curve: Curves.fastOutSlowIn); _controller.forward(); @@ -98,36 +92,19 @@ class _UnitSplashState extends State with TickerProviderStateMixin { ); return Positioned( - top: winH / 1.55, - child: Container( - height: 150, - width: winW, - child: AlignTransition( - alignment: - AlignmentTween(begin: Alignment(-1, 0), end: Alignment.center) - .animate(_secondController), - child: AnimatedOpacity( - duration: const Duration(milliseconds: 300), + top: winH / 1.4, + child:AnimatedOpacity( + duration: const Duration(milliseconds: 400), opacity: _animEnd ? 1.0 : 0.0, - child: ShaderMask( - shaderCallback: _buildShader, - child: Text( - 'Flutter Unit', - style: shadowStyle, - ))), - ), - ), + child: Text( + 'Flutter Unit', + style: shadowStyle, + )), ); } final colors = [Colors.red, Colors.yellow, Colors.blue]; - Shader _buildShader(Rect bounds) => RadialGradient( - center: Alignment.topLeft, - radius: 1.0, - tileMode: TileMode.mirror, - colors: colors) - .createShader(bounds); Widget buildLogo(Color primaryColor) { return SlideTransition( diff --git a/lib/views/widgets/MultiChildRenderObjectWidget/Column/node1_base.dart b/lib/views/widgets/MultiChildRenderObjectWidget/Column/node1_base.dart index 66828d1..8af2ac7 100644 --- a/lib/views/widgets/MultiChildRenderObjectWidget/Column/node1_base.dart +++ b/lib/views/widgets/MultiChildRenderObjectWidget/Column/node1_base.dart @@ -1,10 +1,9 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; /// create by 张风捷特烈 on 2020-03-30 /// contact me by email 1981462002@qq.com /// 说明: // { -// "widgetId": 95, +// "widgetId": 96, // "name": 'Column基本使用', // "priority": 1, // "subtitle": diff --git a/lib/views/widgets/MultiChildRenderObjectWidget/Flex/node1_direction.dart b/lib/views/widgets/MultiChildRenderObjectWidget/Flex/node1_direction.dart index c3beea8..6745f7d 100644 --- a/lib/views/widgets/MultiChildRenderObjectWidget/Flex/node1_direction.dart +++ b/lib/views/widgets/MultiChildRenderObjectWidget/Flex/node1_direction.dart @@ -6,7 +6,7 @@ import 'package:flutter/material.dart'; // { // "widgetId": 94, -// "name": 'Flex的排布方向基本使用', +// "name": 'Flex的排布方向', // "priority": 1, // "subtitle": // "【children】 : 组件列表 【List】\n" diff --git a/lib/views/widgets/MultiChildRenderObjectWidget/RichText/node1_base.dart b/lib/views/widgets/MultiChildRenderObjectWidget/RichText/node1_base.dart index 842a695..5aa4a78 100644 --- a/lib/views/widgets/MultiChildRenderObjectWidget/RichText/node1_base.dart +++ b/lib/views/widgets/MultiChildRenderObjectWidget/RichText/node1_base.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:flutter_unit/app/utils/color_utils.dart'; +import '../../../../app/utils/color_utils.dart'; /// create by 张风捷特烈 on 2020-03-30 /// contact me by email 1981462002@qq.com /// 说明: diff --git a/lib/views/widgets/MultiChildRenderObjectWidget/RichText/node2_widget.dart b/lib/views/widgets/MultiChildRenderObjectWidget/RichText/node2_widget.dart index de79363..9c7c145 100644 --- a/lib/views/widgets/MultiChildRenderObjectWidget/RichText/node2_widget.dart +++ b/lib/views/widgets/MultiChildRenderObjectWidget/RichText/node2_widget.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:flutter_unit/app/utils/color_utils.dart'; /// create by 张风捷特烈 on 2020-03-30 /// contact me by email 1981462002@qq.com /// 说明: diff --git a/lib/views/widgets/MultiChildRenderObjectWidget/Row/node1_base.dart b/lib/views/widgets/MultiChildRenderObjectWidget/Row/node1_base.dart index 04bea20..2732a51 100644 --- a/lib/views/widgets/MultiChildRenderObjectWidget/Row/node1_base.dart +++ b/lib/views/widgets/MultiChildRenderObjectWidget/Row/node1_base.dart @@ -1,4 +1,3 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; /// create by 张风捷特烈 on 2020-03-30 /// contact me by email 1981462002@qq.com diff --git a/lib/views/widgets/Other/Table/node1_base.dart b/lib/views/widgets/Other/Table/node1_base.dart index 1d9f9fe..dab4708 100644 --- a/lib/views/widgets/Other/Table/node1_base.dart +++ b/lib/views/widgets/Other/Table/node1_base.dart @@ -1,5 +1,7 @@ import 'package:flutter/material.dart'; - +/// create by 张风捷特烈 on 2020/4/30 +/// contact me by email 1981462002@qq.com +/// 说明: // { // "widgetId": 110, // "name": 'Table基本使用', diff --git a/lib/views/widgets/ProxyWidget/DefaultTextStyle/node1_base.dart b/lib/views/widgets/ProxyWidget/DefaultTextStyle/node1_base.dart index decbd62..f7d5634 100644 --- a/lib/views/widgets/ProxyWidget/DefaultTextStyle/node1_base.dart +++ b/lib/views/widgets/ProxyWidget/DefaultTextStyle/node1_base.dart @@ -1,4 +1,4 @@ -import 'package:flutter/cupertino.dart'; + import 'package:flutter/material.dart'; /// create by 张风捷特烈 on 2020-04-12 diff --git a/lib/views/widgets/ProxyWidget/Expanded/node1_base.dart b/lib/views/widgets/ProxyWidget/Expanded/node1_base.dart index 89165b7..9896200 100644 --- a/lib/views/widgets/ProxyWidget/Expanded/node1_base.dart +++ b/lib/views/widgets/ProxyWidget/Expanded/node1_base.dart @@ -1,5 +1,5 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_unit/app/utils/color_utils.dart'; + import 'package:flutter/material.dart'; + import '../../../../app/utils/color_utils.dart'; /// create by 张风捷特烈 on 2020-03-22 /// contact me by email 1981462002@qq.com diff --git a/lib/views/widgets/ProxyWidget/Flexible/node1_base.dart b/lib/views/widgets/ProxyWidget/Flexible/node1_base.dart index 8451be1..08616f5 100644 --- a/lib/views/widgets/ProxyWidget/Flexible/node1_base.dart +++ b/lib/views/widgets/ProxyWidget/Flexible/node1_base.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:flutter_unit/app/utils/color_utils.dart'; /// create by 张风捷特烈 on 2020-03-22 /// contact me by email 1981462002@qq.com diff --git a/lib/views/widgets/ProxyWidget/Positioned/node1_base.dart b/lib/views/widgets/ProxyWidget/Positioned/node1_base.dart index 51f7026..0e249eb 100644 --- a/lib/views/widgets/ProxyWidget/Positioned/node1_base.dart +++ b/lib/views/widgets/ProxyWidget/Positioned/node1_base.dart @@ -7,7 +7,7 @@ import 'package:flutter/material.dart'; // { // "widgetId": 108, // "name": 'Positioned基本使用', -// "priority": 2, +// "priority": 1, // "subtitle": // "【child】 : 组件 【Widget】\n" // "【top】 : 到父顶距离 【double】\n" diff --git a/lib/views/widgets/SingleChildRenderObjectWidget/AbsorbPointer/node1_base.dart b/lib/views/widgets/SingleChildRenderObjectWidget/AbsorbPointer/node1_base.dart index 85c7e8d..ec83929 100644 --- a/lib/views/widgets/SingleChildRenderObjectWidget/AbsorbPointer/node1_base.dart +++ b/lib/views/widgets/SingleChildRenderObjectWidget/AbsorbPointer/node1_base.dart @@ -1,12 +1,11 @@ import 'package:flutter/material.dart'; -import 'package:flutter_unit/views/dialogs/dialog_about.dart'; /// create by 张风捷特烈 on 2020-04-19 /// contact me by email 1981462002@qq.com /// 说明: // { -// "widgetId": 292, +// "widgetId": 295, // "name": 'AbsorbPointer基本使用', // "priority": 1, // "subtitle": @@ -51,7 +50,7 @@ class _CustomAbsorbPointerState extends State { 'To About', style: TextStyle(color: Colors.white), ), - onPressed: () => DialogAbout.show(context)); + onPressed: () => Navigator.of(context).pushNamed('AboutMePage')); _buildSwitch() => Switch( value: _absorbing, diff --git a/lib/views/widgets/SingleChildRenderObjectWidget/Align/node1_base.dart b/lib/views/widgets/SingleChildRenderObjectWidget/Align/node1_base.dart index fcdac1a..d396cd4 100644 --- a/lib/views/widgets/SingleChildRenderObjectWidget/Align/node1_base.dart +++ b/lib/views/widgets/SingleChildRenderObjectWidget/Align/node1_base.dart @@ -1,4 +1,3 @@ -import 'dart:math'; import 'package:flutter/material.dart'; /// create by 张风捷特烈 on 2020-04-19 diff --git a/lib/views/widgets/SingleChildRenderObjectWidget/AnimatedSize/node1_base.dart b/lib/views/widgets/SingleChildRenderObjectWidget/AnimatedSize/node1_base.dart index 19137f0..df49a4b 100644 --- a/lib/views/widgets/SingleChildRenderObjectWidget/AnimatedSize/node1_base.dart +++ b/lib/views/widgets/SingleChildRenderObjectWidget/AnimatedSize/node1_base.dart @@ -6,7 +6,7 @@ import 'package:flutter/material.dart'; // { // "widgetId": 201, -// "name": 'AnimatedAlign基本使用', +// "name": 'AnimatedSize基本使用', // "priority": 1, // "subtitle": // "【child】 : 孩子组件 【Widget】\n" diff --git a/lib/views/widgets/SingleChildRenderObjectWidget/AspectRatio/node1_base.dart b/lib/views/widgets/SingleChildRenderObjectWidget/AspectRatio/node1_base.dart index 51ce571..137128c 100644 --- a/lib/views/widgets/SingleChildRenderObjectWidget/AspectRatio/node1_base.dart +++ b/lib/views/widgets/SingleChildRenderObjectWidget/AspectRatio/node1_base.dart @@ -1,4 +1,7 @@ import 'package:flutter/material.dart'; +/// create by 张风捷特烈 on 2020/4/30 +/// contact me by email 1981462002@qq.com +/// 说明: // { // "widgetId": 77, // "name": 'AspectRatio基本使用', diff --git a/lib/views/widgets/SingleChildRenderObjectWidget/ColorFiltered/node1_base.dart b/lib/views/widgets/SingleChildRenderObjectWidget/ColorFiltered/node1_base.dart index 00f111b..928447f 100644 --- a/lib/views/widgets/SingleChildRenderObjectWidget/ColorFiltered/node1_base.dart +++ b/lib/views/widgets/SingleChildRenderObjectWidget/ColorFiltered/node1_base.dart @@ -1,12 +1,12 @@ import 'package:flutter/material.dart'; -import 'package:flutter_unit/app/utils/color_utils.dart'; +import '../../../../app/utils/color_utils.dart'; /// create by 张风捷特烈 on 2020-04-19 /// contact me by email 1981462002@qq.com /// 说明: // { // "widgetId": 88, -// "name": 'FittedBox基本使用', +// "name": 'ColorFiltered基本使用', // "priority": 1, // "subtitle": // "【child】 : 孩子组件 【Widget】\n" diff --git a/lib/views/widgets/SingleChildRenderObjectWidget/DecoratedBox/node1_base.dart b/lib/views/widgets/SingleChildRenderObjectWidget/DecoratedBox/node1_base.dart index a30410e..c4435a2 100644 --- a/lib/views/widgets/SingleChildRenderObjectWidget/DecoratedBox/node1_base.dart +++ b/lib/views/widgets/SingleChildRenderObjectWidget/DecoratedBox/node1_base.dart @@ -9,11 +9,10 @@ import 'package:flutter/material.dart'; // "priority": 1, // "subtitle": // "【decoration】 : 装饰对象 【Decoration】\n" -// "【decoration】 : 裁剪行为 【Clip】\n" // "【position】 : 前景色(左)/后景色(右) 【DecorationPosition】", // } -class CustomDecoratedBox extends StatelessWidget { - final rainbow = [ +class BoxDecorationDemo extends StatelessWidget { + final rainbow = const [ 0xffff0000, 0xffFF7F00, 0xffFFFF00, @@ -25,48 +24,16 @@ class CustomDecoratedBox extends StatelessWidget { @override Widget build(BuildContext context) { - return Wrap( - spacing: 30, - children: [_buildDecoratedBox1(), _buildDecoratedBox2()], - ); - } - - Widget _buildDecoratedBox2() { - return DecoratedBox( - position: DecorationPosition.foreground, - decoration: BoxDecoration( - border: Border(left: BorderSide(color: Colors.black, width: 2)), - //添加渐变色 - gradient: LinearGradient( - stops: [0.0, 1 / 6, 2 / 6, 3 / 6, 4 / 6, 5 / 6, 1.0], - colors: rainbow.map((e) => Color(e)).toList()), - boxShadow: [ - BoxShadow( - color: Colors.orangeAccent, - offset: Offset(1, 1), - blurRadius: 10, - spreadRadius: 1), - ]), - child: Icon( - Icons.android, - size: 80, - color: Colors.black.withAlpha(123), - ), - ); - } - - Widget _buildDecoratedBox1() { return DecoratedBox( position: DecorationPosition.background, decoration: BoxDecoration( - //添加渐变色 gradient: LinearGradient( stops: [0.0, 1 / 6, 2 / 6, 3 / 6, 4 / 6, 5 / 6, 1.0], colors: rainbow.map((e) => Color(e)).toList()), borderRadius: BorderRadius.only( - topLeft: Radius.circular(20), bottomRight: Radius.circular(40)), + topLeft: Radius.circular(20), bottomRight: Radius.circular(20)), boxShadow: [ - BoxShadow( + const BoxShadow( color: Colors.orangeAccent, offset: Offset(1, 1), blurRadius: 10, diff --git a/lib/views/widgets/SingleChildRenderObjectWidget/DecoratedBox/node2_image.dart b/lib/views/widgets/SingleChildRenderObjectWidget/DecoratedBox/node2_image.dart new file mode 100644 index 0000000..f30aece --- /dev/null +++ b/lib/views/widgets/SingleChildRenderObjectWidget/DecoratedBox/node2_image.dart @@ -0,0 +1,36 @@ +import 'package:flutter/material.dart'; +/// create by 张风捷特烈 on 2020-04-19 +/// contact me by email 1981462002@qq.com +/// 说明: + +// { +// "widgetId": 70, +// "name": 'DecoratedBox形状和图片装饰', +// "priority": 2, +// "subtitle": +// "【shape】 : 形状 【BoxShape】\n" +// "【image】 : 背景图片 【DecorationImage】\n", +// } +class ShapeImageDemo extends StatelessWidget { + @override + Widget build(BuildContext context) { + return DecoratedBox( + decoration: BoxDecoration( + shape: BoxShape.circle, + image: DecorationImage( + fit: BoxFit.cover, + image: AssetImage( + 'assets/images/wy_200x300.jpg', + ))), + child: SizedBox( + height: 80, + width: 80, + child: Icon( + Icons.ac_unit, + color: Colors.white, + size: 40, + ), + ), + ); + } +} diff --git a/lib/views/widgets/SingleChildRenderObjectWidget/DecoratedBox/node3_border.dart b/lib/views/widgets/SingleChildRenderObjectWidget/DecoratedBox/node3_border.dart new file mode 100644 index 0000000..39f7c76 --- /dev/null +++ b/lib/views/widgets/SingleChildRenderObjectWidget/DecoratedBox/node3_border.dart @@ -0,0 +1,32 @@ +import 'package:flutter/material.dart'; + +/// create by 张风捷特烈 on 2020/4/30 +/// contact me by email 1981462002@qq.com +/// 说明: +// { +// "widgetId": 70, +// "name": 'DecoratedBox边线装饰', +// "priority": 3, +// "subtitle": "【border】 : 边线 【BoxBorder】\n", +// } +class BorderDemo extends StatelessWidget { + @override + Widget build(BuildContext context) { + return DecoratedBox( + position: DecorationPosition.foreground, + decoration: BoxDecoration( + border: Border( + bottom: BorderSide(color: Colors.orange, width: 2), + top: BorderSide(color: Colors.orange, width: 2)), + ), + child: SizedBox( + height: 80, + width: 100, + child: Image.asset( + 'assets/images/wy_200x300.jpg', + fit: BoxFit.cover, + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/views/widgets/SingleChildRenderObjectWidget/DecoratedBox/node4_shape.dart b/lib/views/widgets/SingleChildRenderObjectWidget/DecoratedBox/node4_shape.dart new file mode 100644 index 0000000..54d8ecb --- /dev/null +++ b/lib/views/widgets/SingleChildRenderObjectWidget/DecoratedBox/node4_shape.dart @@ -0,0 +1,43 @@ +import 'package:flutter/material.dart'; + +/// create by 张风捷特烈 on 2020/4/30 +/// contact me by email 1981462002@qq.com +/// 说明: +// { +// "widgetId": 70, +// "name": 'DecoratedBox形状装饰', +// "priority": 4, +// "subtitle": "通过ShapeDecoration对象可指定边线形状\n", +// } +class ShapeDecorationDemo extends StatelessWidget { + @override + Widget build(BuildContext context) { + return DecoratedBox( + decoration: ShapeDecoration( + shadows: [ + const BoxShadow( + color: Colors.orangeAccent, + offset: Offset(0, 0), + blurRadius: 2, + spreadRadius: 1), + ], + image: DecorationImage( + fit: BoxFit.cover, + image: AssetImage( + 'assets/images/wy_200x300.jpg', + )), + shape: CircleBorder( + side: BorderSide(width: 1.0, color: Colors.orangeAccent), + )), + child: SizedBox( + height: 100, + width: 100, + child: Icon( + Icons.ac_unit, + color: Colors.white, + size: 40, + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/views/widgets/SingleChildRenderObjectWidget/DecoratedBox/node5_line.dart b/lib/views/widgets/SingleChildRenderObjectWidget/DecoratedBox/node5_line.dart new file mode 100644 index 0000000..0128892 --- /dev/null +++ b/lib/views/widgets/SingleChildRenderObjectWidget/DecoratedBox/node5_line.dart @@ -0,0 +1,26 @@ +import 'package:flutter/material.dart'; + +/// create by 张风捷特烈 on 2020/4/30 +/// contact me by email 1981462002@qq.com +/// 说明: +// { +// "widgetId": 70, +// "name": 'DecoratedBox底线装饰', +// "priority": 5, +// "subtitle": "通过UnderlineTabIndicator对象可指定底线\n", +// } +class UnderlineTabIndicatorDemo extends StatelessWidget { + @override + Widget build(BuildContext context) { + return DecoratedBox( + decoration: UnderlineTabIndicator( + insets: EdgeInsets.symmetric(horizontal: 5, vertical: -5), + borderSide: BorderSide(color: Colors.orange, width: 2)), + child: Icon( + Icons.ac_unit, + color: Colors.blue, + size: 40, + ), + ); + } +} \ No newline at end of file diff --git a/lib/views/widgets/SingleChildRenderObjectWidget/DecoratedBox/node6_flutterLogo.dart b/lib/views/widgets/SingleChildRenderObjectWidget/DecoratedBox/node6_flutterLogo.dart new file mode 100644 index 0000000..573856c --- /dev/null +++ b/lib/views/widgets/SingleChildRenderObjectWidget/DecoratedBox/node6_flutterLogo.dart @@ -0,0 +1,27 @@ +import 'package:flutter/material.dart'; + +/// create by 张风捷特烈 on 2020/4/30 +/// contact me by email 1981462002@qq.com +/// 说明: +// { +// "widgetId": 70, +// "name": 'FlutterLogoDecoration装饰', +// "priority": 6, +// "subtitle": "通过FlutterLogoDecoration对象可指定Flutter图标装饰(并没有什么太大的作用)\n", +// } + +class FlutterLogoDecorationDemo extends StatelessWidget { + @override + Widget build(BuildContext context) { + return DecoratedBox( + decoration: FlutterLogoDecoration( + darkColor: Colors.orange, + lightColor: Colors.deepPurpleAccent, + style: FlutterLogoStyle.stacked), + child: SizedBox( + width: 100, + height: 100, + ), + ); + } +} diff --git a/lib/views/widgets/SingleChildRenderObjectWidget/FittedBox/node1_base.dart b/lib/views/widgets/SingleChildRenderObjectWidget/FittedBox/node1_base.dart index 9dd113a..7cb27cb 100644 --- a/lib/views/widgets/SingleChildRenderObjectWidget/FittedBox/node1_base.dart +++ b/lib/views/widgets/SingleChildRenderObjectWidget/FittedBox/node1_base.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:flutter_unit/app/res/cons.dart'; + /// create by 张风捷特烈 on 2020-04-19 /// contact me by email 1981462002@qq.com /// 说明: @@ -22,6 +22,16 @@ class _CustomFittedBoxState extends State { double _childW = 20; double _childH = 30; + final rainbow = [ + 0xffff0000, + 0xffFF7F00, + 0xffFFFF00, + 0xff00FF00, + 0xff00FFFF, + 0xff0000FF, + 0xff8B00FF + ]; + @override Widget build(BuildContext context) { return Column( @@ -59,7 +69,7 @@ class _CustomFittedBoxState extends State { //添加渐变色 gradient: LinearGradient( stops: [0.0, 1 / 6, 2 / 6, 3 / 6, 4 / 6, 5 / 6, 1.0], - colors: Cons.rainbow.map((e) => Color(e)).toList()), + colors: rainbow.map((e) => Color(e)).toList()), ), ), ), diff --git a/lib/views/widgets/SingleChildRenderObjectWidget/FractionallySizedBox/node1_base.dart b/lib/views/widgets/SingleChildRenderObjectWidget/FractionallySizedBox/node1_base.dart index 3cd88e6..362200b 100644 --- a/lib/views/widgets/SingleChildRenderObjectWidget/FractionallySizedBox/node1_base.dart +++ b/lib/views/widgets/SingleChildRenderObjectWidget/FractionallySizedBox/node1_base.dart @@ -4,7 +4,7 @@ import 'package:flutter/material.dart'; /// 说明: // { -// "widgetId": 81, +// "widgetId": 82, // "name": 'FractionallySizedBox基本使用', // "priority": 1, // "subtitle": diff --git a/lib/views/widgets/SingleChildRenderObjectWidget/IgnorePointer/node1_base.dart b/lib/views/widgets/SingleChildRenderObjectWidget/IgnorePointer/node1_base.dart index 1982267..f6247ff 100644 --- a/lib/views/widgets/SingleChildRenderObjectWidget/IgnorePointer/node1_base.dart +++ b/lib/views/widgets/SingleChildRenderObjectWidget/IgnorePointer/node1_base.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:flutter_unit/views/dialogs/dialog_about.dart'; /// create by 张风捷特烈 on 2020-04-19 /// contact me by email 1981462002@qq.com @@ -51,7 +50,7 @@ class _CustomIgnorePointerState extends State { 'To About', style: TextStyle(color: Colors.white), ), - onPressed: () => DialogAbout.show(context)); + onPressed: () => Navigator.of(context).pushNamed('AboutMePage')); _buildSwitch() => Switch( value: _ignore, diff --git a/lib/views/widgets/SingleChildRenderObjectWidget/Opacity/node1_base.dart b/lib/views/widgets/SingleChildRenderObjectWidget/Opacity/node1_base.dart index 14e23df..301240f 100644 --- a/lib/views/widgets/SingleChildRenderObjectWidget/Opacity/node1_base.dart +++ b/lib/views/widgets/SingleChildRenderObjectWidget/Opacity/node1_base.dart @@ -25,10 +25,10 @@ class _CustomOpacityState extends State { children: [_buildSlider(), _buildOpacity()], ); } - + // 创建Opacity Widget _buildOpacity() => Opacity( opacity: _opacity, - child: Image.asset( + child: Image.asset(// 图片 'assets/images/icon_head.png', width: 100, ), diff --git a/lib/views/widgets/SingleChildRenderObjectWidget/Padding/node1_all.dart b/lib/views/widgets/SingleChildRenderObjectWidget/Padding/node1_all.dart new file mode 100644 index 0000000..0f3da50 --- /dev/null +++ b/lib/views/widgets/SingleChildRenderObjectWidget/Padding/node1_all.dart @@ -0,0 +1,40 @@ +import 'package:flutter/material.dart'; + +/// create by 张风捷特烈 on 2020/5/3 +/// contact me by email 1981462002@qq.com +/// 说明: + +// { +// "widgetId": 74, +// "name": 'Padding四面等边距', +// "priority": 1, +// "subtitle": +// "【child】 : 孩子组件 【Widget】\n" +// "【padding】 : 内四边距 【EdgeInsetsGeometry】" +// "EdgeInsets.all用来限定相同的四边边距", +// } +class PaddingAll extends StatelessWidget { + + @override + Widget build(BuildContext context) { + return Container( + color: Colors.grey.withAlpha(22), + width: 200, + height: 150, + child: Padding( + padding: EdgeInsets.all(20), + child: _buildChild(), + ), + ); + } + + Widget _buildChild() { + return Container( + alignment: Alignment.center, + color: Colors.cyanAccent, + width: 100, + height: 100, + child: Text("孩子"), + ); + } +} \ No newline at end of file diff --git a/lib/views/widgets/SingleChildRenderObjectWidget/Padding/node2_only.dart b/lib/views/widgets/SingleChildRenderObjectWidget/Padding/node2_only.dart new file mode 100644 index 0000000..81bdb00 --- /dev/null +++ b/lib/views/widgets/SingleChildRenderObjectWidget/Padding/node2_only.dart @@ -0,0 +1,38 @@ +import 'package:flutter/material.dart'; + +/// create by 张风捷特烈 on 2020/5/3 +/// contact me by email 1981462002@qq.com +/// 说明: + +// { +// "widgetId": 74, +// "name": 'Padding单独边距边距', +// "priority": 2, +// "subtitle": +// "EdgeInsets.only用来限定相同的四边边距", +// } +class PaddingOnly extends StatelessWidget { + + @override + Widget build(BuildContext context) { + return Container( + color: Colors.grey.withAlpha(22), + width: 200, + height: 150, + child: Padding( + padding: EdgeInsets.only(top:10,left: 10), + child: _buildChild(), + ), + ); + } + + Widget _buildChild() { + return Container( + alignment: Alignment.center, + color: Colors.cyanAccent, + width: 100, + height: 100, + child: Text("孩子"), + ); + } +} \ No newline at end of file diff --git a/lib/views/widgets/SingleChildRenderObjectWidget/Padding/node3_symmetric.dart b/lib/views/widgets/SingleChildRenderObjectWidget/Padding/node3_symmetric.dart new file mode 100644 index 0000000..2c7c643 --- /dev/null +++ b/lib/views/widgets/SingleChildRenderObjectWidget/Padding/node3_symmetric.dart @@ -0,0 +1,38 @@ +import 'package:flutter/material.dart'; + +/// create by 张风捷特烈 on 2020/5/3 +/// contact me by email 1981462002@qq.com +/// 说明: + +// { +// "widgetId": 74, +// "name": 'Padding方向边距', +// "priority": 3, +// "subtitle": +// "EdgeInsets.symmetric用来限定水平和竖直方向的边距", +// } +class PaddingSymmetric extends StatelessWidget { + + @override + Widget build(BuildContext context) { + return Container( + color: Colors.grey.withAlpha(22), + width: 200, + height: 150, + child: Padding( + padding: EdgeInsets.symmetric(vertical: 30,horizontal: 10), + child: _buildChild(), + ), + ); + } + + Widget _buildChild() { + return Container( + alignment: Alignment.center, + color: Colors.cyanAccent, + width: 100, + height: 100, + child: Text("孩子"), + ); + } +} \ No newline at end of file diff --git a/lib/views/widgets/SingleChildRenderObjectWidget/Transform/node1_skew.dart b/lib/views/widgets/SingleChildRenderObjectWidget/Transform/node1_skew.dart index d06d6cc..6bfa97b 100644 --- a/lib/views/widgets/SingleChildRenderObjectWidget/Transform/node1_skew.dart +++ b/lib/views/widgets/SingleChildRenderObjectWidget/Transform/node1_skew.dart @@ -1,5 +1,4 @@ import 'dart:math'; -import 'dart:math' as prefix0; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; diff --git a/lib/views/widgets/SingleChildRenderObjectWidget/Transform/node5_perspective.dart b/lib/views/widgets/SingleChildRenderObjectWidget/Transform/node5_perspective.dart index 69b1546..fb21a00 100644 --- a/lib/views/widgets/SingleChildRenderObjectWidget/Transform/node5_perspective.dart +++ b/lib/views/widgets/SingleChildRenderObjectWidget/Transform/node5_perspective.dart @@ -11,7 +11,7 @@ import 'package:flutter/material.dart'; // "name": '透视变换rotation', // "priority": 5, // "subtitle": -// "由R3C1、R3C2、R3C3控制透视" +// "由R3C1、R3C2、R3C3控制透视", // } class R3C2 extends StatefulWidget { @override diff --git a/lib/views/widgets/Sliver/CustomScrollView/node1_base.dart b/lib/views/widgets/Sliver/CustomScrollView/node1_base.dart index c0ac2bd..f8c7db1 100644 --- a/lib/views/widgets/Sliver/CustomScrollView/node1_base.dart +++ b/lib/views/widgets/Sliver/CustomScrollView/node1_base.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:flutter_unit/app/utils/color_utils.dart'; /// create by 张风捷特烈 on 2020-03-30 /// contact me by email 1981462002@qq.com diff --git a/lib/views/widgets/Sliver/FlexibleSpaceBar/node1_base.dart b/lib/views/widgets/Sliver/FlexibleSpaceBar/node1_base.dart index 9240e84..600a198 100644 --- a/lib/views/widgets/Sliver/FlexibleSpaceBar/node1_base.dart +++ b/lib/views/widgets/Sliver/FlexibleSpaceBar/node1_base.dart @@ -3,12 +3,11 @@ /// 说明: import 'package:flutter/material.dart'; -import 'package:flutter_unit/app/utils/color_utils.dart'; /// 说明: // { // "widgetId": 196, -// "name": 'SliverAppBar基本使用', +// "name": 'FlexibleSpaceBar基本使用', // "priority": 1, // "subtitle": // "【title】 : 标题组件 【Widget】\n" diff --git a/lib/views/widgets/Sliver/SliverAppBar/node1_base.dart b/lib/views/widgets/Sliver/SliverAppBar/node1_base.dart index 8a78706..67dd92e 100644 --- a/lib/views/widgets/Sliver/SliverAppBar/node1_base.dart +++ b/lib/views/widgets/Sliver/SliverAppBar/node1_base.dart @@ -1,11 +1,10 @@ import 'package:flutter/material.dart'; -import 'package:flutter_unit/app/utils/color_utils.dart'; /// create by 张风捷特烈 on 2020-03-30 /// contact me by email 1981462002@qq.com /// 说明: // { -// "widgetId": 183, +// "widgetId": 184, // "name": 'SliverAppBar基本使用', // "priority": 1, // "subtitle": diff --git a/lib/views/widgets/Sliver/SliverFillViewport/node1_base.dart b/lib/views/widgets/Sliver/SliverFillViewport/node1_base.dart index d809bfb..b27cf12 100644 --- a/lib/views/widgets/Sliver/SliverFillViewport/node1_base.dart +++ b/lib/views/widgets/Sliver/SliverFillViewport/node1_base.dart @@ -4,8 +4,8 @@ import 'package:flutter/material.dart'; /// contact me by email 1981462002@qq.com /// 说明: // { -// "widgetId": 186, -// "name": 'SliverFixedExtentList基本使用', +// "widgetId": 187, +// "name": 'SliverFillViewport基本使用', // "priority": 1, // "subtitle": // "【viewportFraction】 : 视口分率 【double】\n" diff --git a/lib/views/widgets/Sliver/SliverGrid/node1_base.dart b/lib/views/widgets/Sliver/SliverGrid/node1_base.dart index eda5d5e..298ac32 100644 --- a/lib/views/widgets/Sliver/SliverGrid/node1_base.dart +++ b/lib/views/widgets/Sliver/SliverGrid/node1_base.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:flutter_unit/app/utils/color_utils.dart'; /// create by 张风捷特烈 on 2020-03-30 /// contact me by email 1981462002@qq.com diff --git a/lib/views/widgets/Sliver/SliverList/node1_base.dart b/lib/views/widgets/Sliver/SliverList/node1_base.dart index b907238..1ae36b5 100644 --- a/lib/views/widgets/Sliver/SliverList/node1_base.dart +++ b/lib/views/widgets/Sliver/SliverList/node1_base.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:flutter_unit/app/utils/color_utils.dart'; /// create by 张风捷特烈 on 2020-03-30 /// contact me by email 1981462002@qq.com diff --git a/lib/views/widgets/StatefulWidget/AlignTransition/node1_base.dart b/lib/views/widgets/StatefulWidget/AlignTransition/node1_base.dart index 861bd0b..4973ebe 100644 --- a/lib/views/widgets/StatefulWidget/AlignTransition/node1_base.dart +++ b/lib/views/widgets/StatefulWidget/AlignTransition/node1_base.dart @@ -1,6 +1,8 @@ -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; +import 'package:flutter/material.dart'; +/// create by 张风捷特烈 on 2020/4/30 +/// contact me by email 1981462002@qq.com +/// 说明: // { // "widgetId": 111, // "name": 'AlignTransition基本使用', diff --git a/lib/views/widgets/StatefulWidget/BottomAppBar/node1_base.dart b/lib/views/widgets/StatefulWidget/BottomAppBar/node1_base.dart index d3b439c..1cfcb9f 100755 --- a/lib/views/widgets/StatefulWidget/BottomAppBar/node1_base.dart +++ b/lib/views/widgets/StatefulWidget/BottomAppBar/node1_base.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:flutter_unit/views/dialogs/dialog_about.dart'; + /// create by 张风捷特烈 on 2020-03-23 /// contact me by email 1981462002@qq.com @@ -39,7 +39,7 @@ class _CustomBottomAppBarState extends State { child: Scaffold( backgroundColor: Colors.purple.withAlpha(22), floatingActionButton: FloatingActionButton( - onPressed: () => DialogAbout.show(context), + onPressed: () => Navigator.of(context).pushNamed('AboutMePage'), child: Icon(Icons.add), ), bottomNavigationBar: _buildBottomAppBar(), diff --git a/lib/views/widgets/StatefulWidget/Checkbox/node1_base.dart b/lib/views/widgets/StatefulWidget/Checkbox/node1_base.dart index a6af6ab..436123b 100644 --- a/lib/views/widgets/StatefulWidget/Checkbox/node1_base.dart +++ b/lib/views/widgets/StatefulWidget/Checkbox/node1_base.dart @@ -11,7 +11,7 @@ import 'package:flutter/material.dart'; // "【value】 : 是否选中 【double】\n" // "【checkColor】: 选中时✔️gou颜色 【Color】\n" // "【activeColor】: 选中时框内颜色 【Color】\n" -// "【onChanged】: 状态改变事件 【Function(bool)】\n" +// "【onChanged】: 状态改变事件 【Function(bool)】\n", // } class CustomCheckbox extends StatefulWidget { diff --git a/lib/views/widgets/StatefulWidget/CupertinoActivityIndicator/node1_base.dart b/lib/views/widgets/StatefulWidget/CupertinoActivityIndicator/node1_base.dart index 0eb3e3a..5a2d48f 100644 --- a/lib/views/widgets/StatefulWidget/CupertinoActivityIndicator/node1_base.dart +++ b/lib/views/widgets/StatefulWidget/CupertinoActivityIndicator/node1_base.dart @@ -9,7 +9,7 @@ import 'package:flutter/material.dart'; // "priority": 1, // "subtitle": // "【animating】 : 是否loading动画 【bool】\n" -// "【radius】 : 半径 【double】" +// "【radius】 : 半径 【double】", // } class CustomCupertinoActivityIndicator extends StatelessWidget { diff --git a/lib/views/widgets/StatefulWidget/CupertinoButton/node1_base.dart b/lib/views/widgets/StatefulWidget/CupertinoButton/node1_base.dart index 21bf7c1..ade5190 100755 --- a/lib/views/widgets/StatefulWidget/CupertinoButton/node1_base.dart +++ b/lib/views/widgets/StatefulWidget/CupertinoButton/node1_base.dart @@ -15,7 +15,6 @@ // } import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_unit/views/dialogs/dialog_about.dart'; class CustomCupertinoButton extends StatelessWidget { @override @@ -29,7 +28,7 @@ class CustomCupertinoButton extends StatelessWidget { spacing: 20, children:data.keys.map((e)=> CupertinoButton( padding: EdgeInsets.zero, - onPressed: () => DialogAbout.show(context), + onPressed: () => Navigator.of(context).pushNamed('AboutMePage'), color: e, pressedOpacity: 0.4, borderRadius: BorderRadius.all(Radius.circular(data[e])), diff --git a/lib/views/widgets/StatefulWidget/CupertinoContextMenuAction/node1_base.dart b/lib/views/widgets/StatefulWidget/CupertinoContextMenuAction/node1_base.dart index 0ec6b05..e6770c5 100644 --- a/lib/views/widgets/StatefulWidget/CupertinoContextMenuAction/node1_base.dart +++ b/lib/views/widgets/StatefulWidget/CupertinoContextMenuAction/node1_base.dart @@ -13,7 +13,6 @@ // } import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_unit/views/dialogs/dialog_about.dart'; class CustomCupertinoContextMenuAction extends StatelessWidget { @override @@ -26,7 +25,7 @@ class CustomCupertinoContextMenuAction extends StatelessWidget { child: CupertinoContextMenuAction( trailingIcon: CupertinoIcons.settings, isDefaultAction: true, - onPressed: () => DialogAbout.show(context), + onPressed: () => Navigator.of(context).pushNamed('AboutMePage'), child: Text('张风捷特烈')), ), Container( @@ -35,7 +34,7 @@ class CustomCupertinoContextMenuAction extends StatelessWidget { child: CupertinoContextMenuAction( trailingIcon: CupertinoIcons.home, isDefaultAction: false, - onPressed: () => DialogAbout.show(context), + onPressed: () => Navigator.of(context).pushNamed('AboutMePage'), child: Text('百里·巫缨')), ), ], diff --git a/lib/views/widgets/StatefulWidget/CupertinoTabBar/node1_base.dart b/lib/views/widgets/StatefulWidget/CupertinoTabBar/node1_base.dart index a3c6aeb..69fe867 100755 --- a/lib/views/widgets/StatefulWidget/CupertinoTabBar/node1_base.dart +++ b/lib/views/widgets/StatefulWidget/CupertinoTabBar/node1_base.dart @@ -5,12 +5,11 @@ import 'package:flutter/material.dart'; /// 说明: // { // "widgetId": 63, -// "name": 'CupertinoNavigationBar基本用法', +// "name": 'CupertinoTabBar基本用法', // "priority": 1, // "subtitle": // "【currentIndex】 : 当前激活索引 【Widget】\n" // "【items】 : 条目组件 【Widget】\n" -// "【trailing】 : 尾部组件 【Widget】\n" // "【backgroundColor】 : 背景色 【Color】\n" // "【inactiveColor】 : 非激活色 【Color】\n" // "【activeColor】 : 激活色 【Color】\n" diff --git a/lib/views/widgets/StatefulWidget/DefaultTextStyleTransition/node1_base.dart b/lib/views/widgets/StatefulWidget/DefaultTextStyleTransition/node1_base.dart index dee90ed..334508e 100644 --- a/lib/views/widgets/StatefulWidget/DefaultTextStyleTransition/node1_base.dart +++ b/lib/views/widgets/StatefulWidget/DefaultTextStyleTransition/node1_base.dart @@ -4,7 +4,7 @@ import 'package:flutter/material.dart'; /// contact me by email 1981462002@qq.com /// 说明: // { -// "widgetId": 113, +// "widgetId": 114, // "name": 'DefaultTextStyleTransition基本使用', // "priority": 1, // "subtitle": diff --git a/lib/views/widgets/StatefulWidget/Draggable/node3_use.dart b/lib/views/widgets/StatefulWidget/Draggable/node3_use.dart index 9fbc041..2608cf7 100644 --- a/lib/views/widgets/StatefulWidget/Draggable/node3_use.dart +++ b/lib/views/widgets/StatefulWidget/Draggable/node3_use.dart @@ -9,7 +9,7 @@ import 'package:flutter/material.dart'; // "name": 'Draggable其他使用', // "priority": 3, // "subtitle": -// "可以根据拖拽来处理一些事件。如删除、查询、弹框等" +// "可以根据拖拽来处理一些事件。如删除、查询、弹框等", // } class DeleteDraggable extends StatefulWidget { diff --git a/lib/views/widgets/StatefulWidget/DropdownButton/node1_base.dart b/lib/views/widgets/StatefulWidget/DropdownButton/node1_base.dart index 560b853..6accccc 100644 --- a/lib/views/widgets/StatefulWidget/DropdownButton/node1_base.dart +++ b/lib/views/widgets/StatefulWidget/DropdownButton/node1_base.dart @@ -6,7 +6,7 @@ import 'package:flutter/material.dart'; // { // "widgetId": 55, -// "name": 'DropdownButton基本语法', +// "name": 'DropdownButton基本用法', // "priority": 1, // "subtitle": // "【value】 : 当前值 【T】\n" diff --git a/lib/views/widgets/StatefulWidget/ExpansionTile/node1_base.dart b/lib/views/widgets/StatefulWidget/ExpansionTile/node1_base.dart index c9e6451..ea376b4 100644 --- a/lib/views/widgets/StatefulWidget/ExpansionTile/node1_base.dart +++ b/lib/views/widgets/StatefulWidget/ExpansionTile/node1_base.dart @@ -1,6 +1,8 @@ import 'package:flutter/material.dart'; -import 'package:flutter_unit/views/widgets/exp/stateless_unit.dart'; - +import '../../StatelessWidget/RadioListTile/node1_base.dart'; +/// create by 张风捷特烈 on 2020/4/30 +/// contact me by email 1981462002@qq.com +/// 说明: // { // "widgetId": 52, // "name": 'ExpansionTile基本使用', diff --git a/lib/views/widgets/StatefulWidget/Hero/node1_base.dart b/lib/views/widgets/StatefulWidget/Hero/node1_base.dart index 1849a4e..b6c2e1b 100644 --- a/lib/views/widgets/StatefulWidget/Hero/node1_base.dart +++ b/lib/views/widgets/StatefulWidget/Hero/node1_base.dart @@ -6,7 +6,7 @@ import 'package:flutter/material.dart'; /// 说明: // { -// "widgetId": tag, +// "widgetId": 171, // "name": 'Hero基本使用', // "priority": 1, // "subtitle": diff --git a/lib/views/widgets/StatefulWidget/Image/node2_fit.dart b/lib/views/widgets/StatefulWidget/Image/node2_fit.dart index 31241d4..425d834 100644 --- a/lib/views/widgets/StatefulWidget/Image/node2_fit.dart +++ b/lib/views/widgets/StatefulWidget/Image/node2_fit.dart @@ -8,7 +8,7 @@ import 'package:flutter/material.dart'; // "name": '图片的适应模式', // "priority": 2, // "subtitle": -// "【fit】 : 适应模式*7 【BoxFit】\n" +// "【fit】 : 适应模式*7 【BoxFit】\n", // }, class FitImage extends StatefulWidget { diff --git a/lib/views/widgets/StatefulWidget/Image/node3_alignment.dart b/lib/views/widgets/StatefulWidget/Image/node3_alignment.dart index 8511d52..7ccf5f5 100644 --- a/lib/views/widgets/StatefulWidget/Image/node3_alignment.dart +++ b/lib/views/widgets/StatefulWidget/Image/node3_alignment.dart @@ -9,7 +9,7 @@ import 'package:flutter/material.dart'; // "priority": 3, // "subtitle": // "【alignment】 : 颜色 【AlignmentGeometry】\n" -// " 常用Alignment类的九个静态常量,但也可定制位置" +// " 常用Alignment类的九个静态常量,但也可定制位置", // }, class AlignmentImage extends StatelessWidget { diff --git a/lib/views/widgets/StatefulWidget/Image/node4_colorBlendMode.dart b/lib/views/widgets/StatefulWidget/Image/node4_colorBlendMode.dart index 4676df3..50a202b 100644 --- a/lib/views/widgets/StatefulWidget/Image/node4_colorBlendMode.dart +++ b/lib/views/widgets/StatefulWidget/Image/node4_colorBlendMode.dart @@ -9,7 +9,7 @@ import 'package:flutter/material.dart'; // "priority": 4, // "subtitle": // "【color】 : 颜色 【Color】\n" -// "【colorBlendMode】: 混合模式*29 【BlendMode】" +// "【colorBlendMode】: 混合模式*29 【BlendMode】", // }, class BlendModeImage extends StatelessWidget { diff --git a/lib/views/widgets/StatefulWidget/Image/node5_repeat.dart b/lib/views/widgets/StatefulWidget/Image/node5_repeat.dart index 383a26d..64eeffa 100644 --- a/lib/views/widgets/StatefulWidget/Image/node5_repeat.dart +++ b/lib/views/widgets/StatefulWidget/Image/node5_repeat.dart @@ -8,7 +8,7 @@ import 'package:flutter/material.dart'; // "name": '图片重复模式', // "priority": 5, // "subtitle": -// "【repeat】 : 重复模式*4 【ImageRepeat】" +// "【repeat】 : 重复模式*4 【ImageRepeat】", // }, class RepeatImage extends StatelessWidget { diff --git a/lib/views/widgets/StatefulWidget/Image/node6_centerSlice.dart b/lib/views/widgets/StatefulWidget/Image/node6_centerSlice.dart index ee65f00..4c7359d 100644 --- a/lib/views/widgets/StatefulWidget/Image/node6_centerSlice.dart +++ b/lib/views/widgets/StatefulWidget/Image/node6_centerSlice.dart @@ -11,7 +11,7 @@ import 'package:flutter/material.dart'; // "name": '图片实现局部放大', // "priority": 6, // "subtitle": -// "【centerSlice】 : 保留的区域 【Rect】" +// "【centerSlice】 : 保留的区域 【Rect】", // }, class CenterSliceImage extends StatelessWidget { diff --git a/lib/views/widgets/StatefulWidget/Ink/node2_image.dart b/lib/views/widgets/StatefulWidget/Ink/node2_image.dart index 2f9acea..ca82740 100644 --- a/lib/views/widgets/StatefulWidget/Ink/node2_image.dart +++ b/lib/views/widgets/StatefulWidget/Ink/node2_image.dart @@ -8,7 +8,7 @@ import 'package:flutter/material.dart'; // "name": 'Ink.image图片水波纹', // "priority": 2, // "subtitle": -// " 其中属性与Image组件一致,详见Image组件" +// " 其中属性与Image组件一致,详见Image组件", // } class InkImage extends StatelessWidget { diff --git a/lib/views/widgets/StatefulWidget/LinearProgressIndicator/node1_base.dart b/lib/views/widgets/StatefulWidget/LinearProgressIndicator/node1_base.dart index 6bc56f1..42cf95b 100644 --- a/lib/views/widgets/StatefulWidget/LinearProgressIndicator/node1_base.dart +++ b/lib/views/widgets/StatefulWidget/LinearProgressIndicator/node1_base.dart @@ -1,4 +1,7 @@ import 'package:flutter/material.dart'; +/// create by 张风捷特烈 on 2020/4/30 +/// contact me by email 1981462002@qq.com +/// 说明: // { // "widgetId": 47, // "name": 'LinearProgressIndicator基本使用', diff --git a/lib/views/widgets/StatefulWidget/MaterialApp/node1_base.dart b/lib/views/widgets/StatefulWidget/MaterialApp/node1_base.dart index 0f66d50..cfb7494 100644 --- a/lib/views/widgets/StatefulWidget/MaterialApp/node1_base.dart +++ b/lib/views/widgets/StatefulWidget/MaterialApp/node1_base.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:flutter_unit/app/router.dart'; -import 'package:flutter_unit/views/widgets/StatefulWidget/Scaffold/node1_base.dart'; +import '../../../../app/router.dart'; +import '../../StatefulWidget/Scaffold/node1_base.dart'; /// create by 张风捷特烈 on 2020-03-17 /// contact me by email 1981462002@qq.com @@ -14,7 +14,7 @@ import 'package:flutter_unit/views/widgets/StatefulWidget/Scaffold/node1_base.da // "【theme】 : 主题 【ThemeData】\n" // "【title】 : 任务栏标题 【String】\n" // "【onGenerateRoute】 : 路由生成器 【RouteFactory】\n" -// "【home】 : 主页 【Widget】" +// "【home】 : 主页 【Widget】", // } class CustomMaterialApp extends StatelessWidget { @override diff --git a/lib/views/widgets/StatefulWidget/PopupMenuButton/node1_base.dart b/lib/views/widgets/StatefulWidget/PopupMenuButton/node1_base.dart index 2680a34..e7e99db 100644 --- a/lib/views/widgets/StatefulWidget/PopupMenuButton/node1_base.dart +++ b/lib/views/widgets/StatefulWidget/PopupMenuButton/node1_base.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:flutter_unit/views/dialogs/dialog_about.dart'; +import '../../../dialogs/dialog_about.dart'; /// create by 张风捷特烈 on 2020-03-16 /// contact me by email 1981462002@qq.com diff --git a/lib/views/widgets/StatefulWidget/PopupMenuDivider/node1_base.dart b/lib/views/widgets/StatefulWidget/PopupMenuDivider/node1_base.dart index 44e9859..e657c5c 100644 --- a/lib/views/widgets/StatefulWidget/PopupMenuDivider/node1_base.dart +++ b/lib/views/widgets/StatefulWidget/PopupMenuDivider/node1_base.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:flutter_unit/views/dialogs/dialog_about.dart'; +import '../../../dialogs/dialog_about.dart'; /// create by 张风捷特烈 on 2020-03-29 /// contact me by email 1981462002@qq.com diff --git a/lib/views/widgets/StatefulWidget/PositionedTransition/node1_base.dart b/lib/views/widgets/StatefulWidget/PositionedTransition/node1_base.dart index 82eb148..aba0f6a 100644 --- a/lib/views/widgets/StatefulWidget/PositionedTransition/node1_base.dart +++ b/lib/views/widgets/StatefulWidget/PositionedTransition/node1_base.dart @@ -3,7 +3,7 @@ import 'package:flutter/material.dart'; /// contact me by email 1981462002@qq.com /// 说明: // { -// "widgetId": 92, +// "widgetId": 93, // "name": 'PositionedTransition基本使用', // "priority": 1, // "subtitle": diff --git a/lib/views/widgets/StatefulWidget/RangeSlider/node1_base.dart b/lib/views/widgets/StatefulWidget/RangeSlider/node1_base.dart index 97bff14..9dacc40 100644 --- a/lib/views/widgets/StatefulWidget/RangeSlider/node1_base.dart +++ b/lib/views/widgets/StatefulWidget/RangeSlider/node1_base.dart @@ -4,7 +4,7 @@ import 'package:flutter/material.dart'; /// 说明: // { // "widgetId": 44, -// "name": 'Slider基本使用', +// "name": 'RangeSlider基本使用', // "priority": 1, // "subtitle": // "【values】 : 数值 【RangeValues】\n" diff --git a/lib/views/widgets/StatefulWidget/RawChip/node1_press.dart b/lib/views/widgets/StatefulWidget/RawChip/node1_press.dart index 48cc0df..45cdbbd 100644 --- a/lib/views/widgets/StatefulWidget/RawChip/node1_press.dart +++ b/lib/views/widgets/StatefulWidget/RawChip/node1_press.dart @@ -1,6 +1,5 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_unit/views/dialogs/dialog_about.dart'; /// create by 张风捷特烈 on 2020-03-26 /// contact me by email 1981462002@qq.com @@ -32,7 +31,7 @@ class PressRawChip extends StatelessWidget { elevation: 3, pressElevation: 5, shadowColor: Colors.orangeAccent, - onPressed: () => DialogAbout.show(context), + onPressed: () => Navigator.of(context).pushNamed('AboutMePage'), ), ); } diff --git a/lib/views/widgets/StatefulWidget/RawChip/node2_select.dart b/lib/views/widgets/StatefulWidget/RawChip/node2_select.dart index d143929..5427766 100644 --- a/lib/views/widgets/StatefulWidget/RawChip/node2_select.dart +++ b/lib/views/widgets/StatefulWidget/RawChip/node2_select.dart @@ -1,6 +1,5 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_unit/views/dialogs/dialog_about.dart'; /// create by 张风捷特烈 on 2020-03-26 /// contact me by email 1981462002@qq.com @@ -40,7 +39,7 @@ class _SelectRawChipState extends State { pressElevation: 5, shadowColor: Colors.orangeAccent, onSelected: (v)=> setState(() => _selected=v), - onDeleted: () => DialogAbout.show(context), + onDeleted: () => Navigator.of(context).pushNamed('AboutMePage'), ), ); } diff --git a/lib/views/widgets/StatefulWidget/RawMaterialButton/node1_base.dart b/lib/views/widgets/StatefulWidget/RawMaterialButton/node1_base.dart index 91dca57..f213fe8 100644 --- a/lib/views/widgets/StatefulWidget/RawMaterialButton/node1_base.dart +++ b/lib/views/widgets/StatefulWidget/RawMaterialButton/node1_base.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:flutter_unit/views/dialogs/dialog_about.dart'; + /// create by 张风捷特烈 on 2020-03-29 /// contact me by email 1981462002@qq.com diff --git a/lib/views/widgets/StatefulWidget/RawMaterialButton/node2_shape.dart b/lib/views/widgets/StatefulWidget/RawMaterialButton/node2_shape.dart index 8fb19a7..41a678a 100644 --- a/lib/views/widgets/StatefulWidget/RawMaterialButton/node2_shape.dart +++ b/lib/views/widgets/StatefulWidget/RawMaterialButton/node2_shape.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:flutter_unit/views/dialogs/dialog_about.dart'; /// create by 张风捷特烈 on 2020-03-29 /// contact me by email 1981462002@qq.com diff --git a/lib/views/widgets/StatefulWidget/RefreshIndicator/node1_base.dart b/lib/views/widgets/StatefulWidget/RefreshIndicator/node1_base.dart index caaae62..a3c25c8 100644 --- a/lib/views/widgets/StatefulWidget/RefreshIndicator/node1_base.dart +++ b/lib/views/widgets/StatefulWidget/RefreshIndicator/node1_base.dart @@ -1,4 +1,7 @@ import 'package:flutter/material.dart'; +/// create by 张风捷特烈 on 2020/4/30 +/// contact me by email 1981462002@qq.com +/// 说明: // { // "widgetId": 49, // "name": 'RefreshIndicator基本使用', diff --git a/lib/views/widgets/StatefulWidget/RelativePositionedTransition/node1_base.dart b/lib/views/widgets/StatefulWidget/RelativePositionedTransition/node1_base.dart index 69814d7..8961c86 100644 --- a/lib/views/widgets/StatefulWidget/RelativePositionedTransition/node1_base.dart +++ b/lib/views/widgets/StatefulWidget/RelativePositionedTransition/node1_base.dart @@ -1,4 +1,7 @@ import 'package:flutter/material.dart'; +/// create by 张风捷特烈 on 2020/4/30 +/// contact me by email 1981462002@qq.com +/// 说明: // { // "widgetId": 115, diff --git a/lib/views/widgets/StatefulWidget/RotationTransition/node1_base.dart b/lib/views/widgets/StatefulWidget/RotationTransition/node1_base.dart index ef9e4bd..aa3fff9 100644 --- a/lib/views/widgets/StatefulWidget/RotationTransition/node1_base.dart +++ b/lib/views/widgets/StatefulWidget/RotationTransition/node1_base.dart @@ -1,5 +1,9 @@ import 'package:flutter/material.dart'; +/// create by 张风捷特烈 on 2020/4/30 +/// contact me by email 1981462002@qq.com +/// 说明: + // { // "widgetId": 90, // "name": 'RotationTransition基本使用', diff --git a/lib/views/widgets/StatefulWidget/Scaffold/node1_base.dart b/lib/views/widgets/StatefulWidget/Scaffold/node1_base.dart index bde5495..7228d42 100755 --- a/lib/views/widgets/StatefulWidget/Scaffold/node1_base.dart +++ b/lib/views/widgets/StatefulWidget/Scaffold/node1_base.dart @@ -1,6 +1,8 @@ import 'package:flutter/material.dart'; -import 'package:flutter_unit/views/widgets/StatefulWidget/PopupMenuButton/node1_base.dart'; - +import '../PopupMenuButton/node1_base.dart'; +/// create by 张风捷特烈 on 2020/4/30 +/// contact me by email 1981462002@qq.com +/// 说明: // { // "widgetId": 64, // "name": 'Scaffold基本用法', diff --git a/lib/views/widgets/StatefulWidget/ScaleTransition/node1_base.dart b/lib/views/widgets/StatefulWidget/ScaleTransition/node1_base.dart index ecc02f0..1fe7372 100644 --- a/lib/views/widgets/StatefulWidget/ScaleTransition/node1_base.dart +++ b/lib/views/widgets/StatefulWidget/ScaleTransition/node1_base.dart @@ -1,5 +1,7 @@ import 'package:flutter/material.dart'; - +/// create by 张风捷特烈 on 2020/4/30 +/// contact me by email 1981462002@qq.com +/// 说明: // { // "widgetId": 91, // "name": 'ScaleTransition基本使用', diff --git a/lib/views/widgets/StatefulWidget/SelectableText/node1_base.dart b/lib/views/widgets/StatefulWidget/SelectableText/node1_base.dart index fd26b31..354dca8 100644 --- a/lib/views/widgets/StatefulWidget/SelectableText/node1_base.dart +++ b/lib/views/widgets/StatefulWidget/SelectableText/node1_base.dart @@ -13,7 +13,7 @@ import 'package:flutter/material.dart'; // "【cursorColor】 : 光标颜色 【Color】\n" // "【cursorWidth】 : 光标宽度 【double】\n" // "【showCursor】 : 是否显示光标 【bool】\n" -// "【autofocus】 : 自动聚焦 【bool】" +// "【autofocus】 : 自动聚焦 【bool】", // } class CustomSelectableText extends StatelessWidget { final text = " 始臣之解牛之时,所见无非牛者。三年之后,未尝见全牛也。方今之时," diff --git a/lib/views/widgets/StatefulWidget/SizeTransition/node1_base.dart b/lib/views/widgets/StatefulWidget/SizeTransition/node1_base.dart index ead3be6..1a9724d 100644 --- a/lib/views/widgets/StatefulWidget/SizeTransition/node1_base.dart +++ b/lib/views/widgets/StatefulWidget/SizeTransition/node1_base.dart @@ -5,7 +5,7 @@ import 'package:flutter/material.dart'; /// 说明: // { // "widgetId": 92, -// "name": 'FadeTransition基本使用', +// "name": 'SizeTransition基本使用', // "priority": 1, // "subtitle": // "【child】 : 孩子组件 【Widget】\n" diff --git a/lib/views/widgets/StatefulWidget/SlideTransition/node1_base.dart b/lib/views/widgets/StatefulWidget/SlideTransition/node1_base.dart index b7d9a6b..f51e92e 100644 --- a/lib/views/widgets/StatefulWidget/SlideTransition/node1_base.dart +++ b/lib/views/widgets/StatefulWidget/SlideTransition/node1_base.dart @@ -1,6 +1,8 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; - +/// create by 张风捷特烈 on 2020/4/30 +/// contact me by email 1981462002@qq.com +/// 说明: // { // "widgetId": 112, // "name": 'SlideTransition基本使用', diff --git a/lib/views/widgets/StatefulWidget/Switch/node1_base.dart b/lib/views/widgets/StatefulWidget/Switch/node1_base.dart index c5df7cb..1fc7cbc 100644 --- a/lib/views/widgets/StatefulWidget/Switch/node1_base.dart +++ b/lib/views/widgets/StatefulWidget/Switch/node1_base.dart @@ -6,7 +6,7 @@ import 'package:flutter/material.dart'; /// { // "widgetId": 40, -// "name": 'Switch基础语法', +// "name": 'Switch基础用法', // "priority": 1, // "subtitle": // "【inactiveThumbColor】 : 未选中小圈颜色 【Color】\n" diff --git a/lib/views/widgets/StatefulWidget/Switch/node2_image.dart b/lib/views/widgets/StatefulWidget/Switch/node2_image.dart index 4edd18f..bd73408 100644 --- a/lib/views/widgets/StatefulWidget/Switch/node2_image.dart +++ b/lib/views/widgets/StatefulWidget/Switch/node2_image.dart @@ -10,7 +10,7 @@ import 'package:flutter/material.dart'; // "priority": 2, // "subtitle": // "【inactiveThumbImage】 : 未选中小圈图片 【ImageProvider】\n" -// "【activeThumbImage】 : 选中时滑槽颜色 【ImageProvider】" +// "【activeThumbImage】 : 选中时滑槽颜色 【ImageProvider】", // } class ImageSwitch extends StatefulWidget { @override diff --git a/lib/views/widgets/StatefulWidget/TabBarView/node1_base.dart b/lib/views/widgets/StatefulWidget/TabBarView/node1_base.dart index 6feb48a..a47bbdb 100644 --- a/lib/views/widgets/StatefulWidget/TabBarView/node1_base.dart +++ b/lib/views/widgets/StatefulWidget/TabBarView/node1_base.dart @@ -9,7 +9,7 @@ import 'package:flutter/material.dart'; // "subtitle": // "【controller】 : 控制器 【TabController】\n" // "【children】 : 孩子们 【指示器颜色】\n" -// "【physics】 : 表现 【ScrollPhysics】" +// "【physics】 : 表现 【ScrollPhysics】", // } class CustomTabBarView extends StatefulWidget { @override diff --git a/lib/views/widgets/StatefulWidget/TextField/node1_base.dart b/lib/views/widgets/StatefulWidget/TextField/node1_base.dart index 3d765f5..9c8bcf4 100644 --- a/lib/views/widgets/StatefulWidget/TextField/node1_base.dart +++ b/lib/views/widgets/StatefulWidget/TextField/node1_base.dart @@ -1,6 +1,8 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; - +/// create by 张风捷特烈 on 2020/4/30 +/// contact me by email 1981462002@qq.com +/// 说明: // { // "widgetId": 54, // "name": 'TextField基本用法', diff --git a/lib/views/widgets/StatefulWidget/Tooltip/node1_base.dart b/lib/views/widgets/StatefulWidget/Tooltip/node1_base.dart index b0482a7..7b37676 100644 --- a/lib/views/widgets/StatefulWidget/Tooltip/node1_base.dart +++ b/lib/views/widgets/StatefulWidget/Tooltip/node1_base.dart @@ -13,7 +13,7 @@ import 'package:flutter/material.dart'; // "【message】 : 消息内容 【String】\n" // "【showDuration】 : 展示时间 【Duration】\n" // "【waitDuration】 : 悬浮出现时间 【Duration】\n" -// "【child】 : 孩子 【Widget】" +// "【child】 : 孩子 【Widget】", // } class CustomTooltip extends StatelessWidget { @override diff --git a/lib/views/widgets/StatefulWidget/Tooltip/node2_decoration.dart b/lib/views/widgets/StatefulWidget/Tooltip/node2_decoration.dart index fbc4832..861890e 100644 --- a/lib/views/widgets/StatefulWidget/Tooltip/node2_decoration.dart +++ b/lib/views/widgets/StatefulWidget/Tooltip/node2_decoration.dart @@ -9,7 +9,7 @@ import 'package:flutter/material.dart'; // "priority": 2, // "subtitle": // "【decoration】 : 装饰对象 【Decoration】\n" -// "【textStyle】 : 文字样式 【double】" +// "【textStyle】 : 文字样式 【double】", // } class DecorationTooltip extends StatelessWidget { @override diff --git a/lib/views/widgets/StatelessWidget/ActionChip/node1_base.dart b/lib/views/widgets/StatelessWidget/ActionChip/node1_base.dart index e556771..0100d90 100644 --- a/lib/views/widgets/StatelessWidget/ActionChip/node1_base.dart +++ b/lib/views/widgets/StatelessWidget/ActionChip/node1_base.dart @@ -15,7 +15,7 @@ import 'package:flutter/material.dart'; -import 'package:flutter_unit/views/dialogs/dialog_about.dart'; +import '../../../dialogs/dialog_about.dart'; class CustomActionChip extends StatelessWidget { diff --git a/lib/views/widgets/StatelessWidget/Banner/node1_base.dart b/lib/views/widgets/StatelessWidget/Banner/node1_base.dart index 32cb29c..4b7e3a0 100644 --- a/lib/views/widgets/StatelessWidget/Banner/node1_base.dart +++ b/lib/views/widgets/StatelessWidget/Banner/node1_base.dart @@ -1,4 +1,6 @@ - +/// create by 张风捷特烈 on 2020/4/30 +/// contact me by email 1981462002@qq.com +/// 说明: // { // "widgetId": 5, // "priority": 1, diff --git a/lib/views/widgets/StatelessWidget/ButtonBar/node1_base.dart b/lib/views/widgets/StatelessWidget/ButtonBar/node1_base.dart index 89db637..c469d3f 100755 --- a/lib/views/widgets/StatelessWidget/ButtonBar/node1_base.dart +++ b/lib/views/widgets/StatelessWidget/ButtonBar/node1_base.dart @@ -10,7 +10,7 @@ // } import 'package:flutter/material.dart'; -import 'package:flutter_unit/views/dialogs/dialog_about.dart'; +import '../../../dialogs/dialog_about.dart'; class CustomButtonBar extends StatelessWidget { @@ -36,27 +36,3 @@ class CustomButtonBar extends StatelessWidget { } } -class PaddingButtonBar extends StatelessWidget { - @override - Widget build(BuildContext context) { - return ButtonBar( - alignment: MainAxisAlignment.center, - buttonHeight: 40, - buttonPadding: EdgeInsets.only(left: 15,right: 15), - children: [ - RaisedButton( - color: Colors.blue, - child: Text("Raised"), - onPressed: () => DialogAbout.show(context)), - OutlineButton( - child: Text("Outline"), - onPressed: () => DialogAbout.show(context)), - FlatButton( - color: Colors.blue, - onPressed: () => DialogAbout.show(context), - child: Text("Flat"), - ) - ], - ); - } -} diff --git a/lib/views/widgets/StatelessWidget/ButtonBar/node2_padding.dart b/lib/views/widgets/StatelessWidget/ButtonBar/node2_padding.dart new file mode 100644 index 0000000..0f58bc6 --- /dev/null +++ b/lib/views/widgets/StatelessWidget/ButtonBar/node2_padding.dart @@ -0,0 +1,38 @@ + +import 'package:flutter/material.dart'; +import '../../../dialogs/dialog_about.dart'; + +/// create by 张风捷特烈 on 2020-03-25 +/// contact me by email 1981462002@qq.com +/// 说明: +// { +// "widgetId": 29, +// "priority": 2, +// "name": "ButtonBar边距和高", +// "subtitle": "【buttonPadding】: 内边距 【EdgeInsetsGeometry】\n" +// "【buttonHeight】: 高 【double】", +// } +class PaddingButtonBar extends StatelessWidget { + @override + Widget build(BuildContext context) { + return ButtonBar( + alignment: MainAxisAlignment.center, + buttonHeight: 40, + buttonPadding: EdgeInsets.only(left: 15,right: 15), + children: [ + RaisedButton( + color: Colors.blue, + child: Text("Raised"), + onPressed: () => DialogAbout.show(context)), + OutlineButton( + child: Text("Outline"), + onPressed: () => DialogAbout.show(context)), + FlatButton( + color: Colors.blue, + onPressed: () => DialogAbout.show(context), + child: Text("Flat"), + ) + ], + ); + } +} diff --git a/lib/views/widgets/StatelessWidget/Card/node2_shape.dart b/lib/views/widgets/StatelessWidget/Card/node2_shape.dart index 40b5e83..3f5f622 100644 --- a/lib/views/widgets/StatelessWidget/Card/node2_shape.dart +++ b/lib/views/widgets/StatelessWidget/Card/node2_shape.dart @@ -14,7 +14,7 @@ // } import 'package:flutter/material.dart'; -import 'package:flutter_unit/app/utils/pather.dart'; +import '../../../../app/utils/pather.dart'; class ShapeCard extends StatelessWidget { @override diff --git a/lib/views/widgets/StatelessWidget/Chip/node3_delete.dart b/lib/views/widgets/StatelessWidget/Chip/node3_delete.dart index bf31064..910d936 100644 --- a/lib/views/widgets/StatelessWidget/Chip/node3_delete.dart +++ b/lib/views/widgets/StatelessWidget/Chip/node3_delete.dart @@ -13,7 +13,7 @@ // "【onDeleted】: 右侧组件点击事件 【Function】", // } import 'package:flutter/material.dart'; -import 'package:flutter_unit/views/dialogs/dialog_about.dart'; +import '../../../dialogs/dialog_about.dart'; class DeleteOfChip extends StatelessWidget { @override diff --git a/lib/views/widgets/StatelessWidget/CupertinoActionSheetAction/node1_base.dart b/lib/views/widgets/StatelessWidget/CupertinoActionSheetAction/node1_base.dart index d720ad1..b38d8d1 100644 --- a/lib/views/widgets/StatelessWidget/CupertinoActionSheetAction/node1_base.dart +++ b/lib/views/widgets/StatelessWidget/CupertinoActionSheetAction/node1_base.dart @@ -3,7 +3,7 @@ /// 说明: // { // "widgetId": 132, -// "name": 'CupertinoActionSheet基本使用', +// "name": 'CupertinoActionSheetAction基本使用', // "priority": 1, // "subtitle": // "【child】 : 子组件 【Widget】\n" @@ -13,7 +13,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_unit/views/dialogs/dialog_about.dart'; +import '../../../dialogs/dialog_about.dart'; class CustomCupertinoActionSheetAction extends StatelessWidget { @override diff --git a/lib/views/widgets/StatelessWidget/CupertinoDialogAction/node1_base.dart b/lib/views/widgets/StatelessWidget/CupertinoDialogAction/no_node1_base.dart similarity index 100% rename from lib/views/widgets/StatelessWidget/CupertinoDialogAction/node1_base.dart rename to lib/views/widgets/StatelessWidget/CupertinoDialogAction/no_node1_base.dart diff --git a/lib/views/widgets/StatelessWidget/FloatingActionButton/node3_shape.dart b/lib/views/widgets/StatelessWidget/FloatingActionButton/node3_shape.dart index d1c50e1..9b5551c 100644 --- a/lib/views/widgets/StatelessWidget/FloatingActionButton/node3_shape.dart +++ b/lib/views/widgets/StatelessWidget/FloatingActionButton/node3_shape.dart @@ -13,7 +13,7 @@ import 'dart:math'; import 'package:flutter/material.dart'; -import 'package:flutter_unit/app/utils/pather.dart'; +import '../../../../app/utils/pather.dart'; class ShapeFAB extends StatelessWidget { @override diff --git a/lib/views/widgets/StatelessWidget/Icon/node2_diy.dart b/lib/views/widgets/StatelessWidget/Icon/node2_diy.dart index 1a3784d..8651fea 100644 --- a/lib/views/widgets/StatelessWidget/Icon/node2_diy.dart +++ b/lib/views/widgets/StatelessWidget/Icon/node2_diy.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:flutter_unit/app/style/TolyIcon.dart'; +import '../../../../app/style/TolyIcon.dart'; /// create by 张风捷特烈 on 2020/4/27 /// contact me by email 1981462002@qq.com diff --git a/lib/views/widgets/StatelessWidget/InputChip/node1_base.dart b/lib/views/widgets/StatelessWidget/InputChip/node1_base.dart index 7190ee8..3b80bda 100644 --- a/lib/views/widgets/StatelessWidget/InputChip/node1_base.dart +++ b/lib/views/widgets/StatelessWidget/InputChip/node1_base.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:flutter_unit/views/dialogs/dialog_about.dart'; /// create by 张风捷特烈 on 2020/4/27 /// contact me by email 1981462002@qq.com @@ -35,7 +34,7 @@ class _PressInputChipState extends State { selectedShadowColor: Colors.blue, shadowColor: Colors.orangeAccent, elevation: 3, - onPressed: () => DialogAbout.show(context), + onPressed: () => Navigator.of(context).pushNamed('AboutMePage'), onDeleted: () => setState(() => _delete = !_delete)); } } \ No newline at end of file diff --git a/lib/views/widgets/StatelessWidget/InputChip/node2_select.dart b/lib/views/widgets/StatelessWidget/InputChip/node2_select.dart index 1eb5959..64b33fd 100644 --- a/lib/views/widgets/StatelessWidget/InputChip/node2_select.dart +++ b/lib/views/widgets/StatelessWidget/InputChip/node2_select.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:flutter_unit/views/dialogs/dialog_about.dart'; @@ -35,7 +34,7 @@ class _SelectInputChipState extends State { selectedShadowColor: Colors.blue, shadowColor: Colors.orangeAccent, elevation: 3, - onDeleted: () => DialogAbout.show(context), + onDeleted: () => Navigator.of(context).pushNamed('AboutMePage'), onSelected: (bool value) { setState(() { _select = value; diff --git a/lib/views/widgets/StatelessWidget/ListTile/node1_base.dart b/lib/views/widgets/StatelessWidget/ListTile/node1_base.dart index 3d31f34..01c41b3 100644 --- a/lib/views/widgets/StatelessWidget/ListTile/node1_base.dart +++ b/lib/views/widgets/StatelessWidget/ListTile/node1_base.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:flutter_unit/views/dialogs/dialog_about.dart'; /// create by 张风捷特烈 on 2020-03-25 /// contact me by email 1981462002@qq.com @@ -28,7 +27,7 @@ class CustomListTile extends StatelessWidget { subtitle: Text("海子"), contentPadding: EdgeInsets.all(5), trailing: Icon(Icons.more_vert), - onLongPress: () => DialogAbout.show(context), + onLongPress: () => Navigator.of(context).pushNamed('AboutMePage'), ), ); } diff --git a/lib/views/widgets/StatelessWidget/MaterialButton/node1_base.dart b/lib/views/widgets/StatelessWidget/MaterialButton/node1_base.dart index d73a363..9e3c20e 100644 --- a/lib/views/widgets/StatelessWidget/MaterialButton/node1_base.dart +++ b/lib/views/widgets/StatelessWidget/MaterialButton/node1_base.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:flutter_unit/views/dialogs/dialog_about.dart'; /// create by 张风捷特烈 on 2020-03-25 /// contact me by email 1981462002@qq.com @@ -31,6 +30,6 @@ class CustomMaterialButton extends StatelessWidget { splashColor: Colors.blue, padding: EdgeInsets.all(8), child: Text("MaterialButton"), - onPressed: () => DialogAbout.show(context)); + onPressed: () => Navigator.of(context).pushNamed('AboutMePage')); } } \ No newline at end of file diff --git a/lib/views/widgets/StatelessWidget/MaterialButton/node2_onLongPress.dart b/lib/views/widgets/StatelessWidget/MaterialButton/node2_onLongPress.dart index 8ec33ad..b033435 100644 --- a/lib/views/widgets/StatelessWidget/MaterialButton/node2_onLongPress.dart +++ b/lib/views/widgets/StatelessWidget/MaterialButton/node2_onLongPress.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:flutter_unit/views/dialogs/dialog_about.dart'; /// create by 张风捷特烈 on 2020-03-25 /// contact me by email 1981462002@qq.com @@ -24,7 +23,7 @@ class LongPressMaterialButton extends StatelessWidget { textColor: Colors.white, padding: EdgeInsets.all(8), child: Text("MaterialButton"), - onLongPress: () => DialogAbout.show(context), - onPressed: () => DialogAbout.show(context)); + onLongPress: () => Navigator.of(context).pushNamed('AboutMePage'), + onPressed: () => Navigator.of(context).pushNamed('AboutMePage')); } } \ No newline at end of file diff --git a/lib/views/widgets/StatelessWidget/MaterialButton/node3_shape.dart b/lib/views/widgets/StatelessWidget/MaterialButton/node3_shape.dart index 97a7335..6a1dada 100644 --- a/lib/views/widgets/StatelessWidget/MaterialButton/node3_shape.dart +++ b/lib/views/widgets/StatelessWidget/MaterialButton/node3_shape.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:flutter_unit/views/dialogs/dialog_about.dart'; /// create by 张风捷特烈 on 2020-03-25 /// contact me by email 1981462002@qq.com @@ -35,8 +34,8 @@ class ShapeMaterialButton extends StatelessWidget { shape: CircleBorder( side: BorderSide(width: 2.0, color: Color(0xFFFFDFDFDF)), ), - onLongPress: () => DialogAbout.show(context), - onPressed: () => DialogAbout.show(context)), + onLongPress: () => Navigator.of(context).pushNamed('AboutMePage'), + onPressed: () => Navigator.of(context).pushNamed('AboutMePage')), ), Container( width: 100, @@ -54,8 +53,8 @@ class ShapeMaterialButton extends StatelessWidget { ), shape: RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(15))), - onLongPress: () => DialogAbout.show(context), - onPressed: () => DialogAbout.show(context)), + onLongPress: () => Navigator.of(context).pushNamed('AboutMePage'), + onPressed: () => Navigator.of(context).pushNamed('AboutMePage')), ), ], ); diff --git a/lib/views/widgets/StatelessWidget/PreferredSize/node1_base.dart b/lib/views/widgets/StatelessWidget/PreferredSize/node1_base.dart new file mode 100644 index 0000000..7b52570 --- /dev/null +++ b/lib/views/widgets/StatelessWidget/PreferredSize/node1_base.dart @@ -0,0 +1,27 @@ +import 'package:flutter/material.dart'; + +/// create by 张风捷特烈 on 2020/5/3 +/// contact me by email 1981462002@qq.com +/// 说明: +// { +// "widgetId": 204, +// "name": 'PreferredSize调整AppBar高度', +// "priority": 1, +// "subtitle": "【preferredSize】 : 尺寸 【Size】", +// } +class CustomPreferredSize extends StatelessWidget { + @override + Widget build(BuildContext context) { + return Container( + height: 200, + child: Scaffold( + appBar: PreferredSize( + preferredSize: Size.fromHeight(150), + child: AppBar( + title: Text('PreferredSize'), + ), + ), + ), + ); + } +} diff --git a/lib/views/widgets/StatelessWidget/PreferredSize/node2_adapter.dart b/lib/views/widgets/StatelessWidget/PreferredSize/node2_adapter.dart new file mode 100644 index 0000000..60cee0a --- /dev/null +++ b/lib/views/widgets/StatelessWidget/PreferredSize/node2_adapter.dart @@ -0,0 +1,34 @@ +import 'package:flutter/material.dart'; + +/// create by 张风捷特烈 on 2020/5/3 +/// contact me by email 1981462002@qq.com +/// 说明: +// { +// "widgetId": 204, +// "name": 'PreferredSize的转化使用', +// "priority": 2, +// "subtitle": "【PreferredSize将普通组件转化为PreferredSizeWidget", +// } +class AdapterPreferredSize extends StatelessWidget { + @override + Widget build(BuildContext context) { + return Container( + height: 200, + child: Scaffold( + appBar: PreferredSize( + preferredSize: Size.fromHeight(150), + child: AppBar( + title: Text('PreferredSize'), + bottom: PreferredSize( + preferredSize: Size.fromHeight(40), + child: Container( + height: 40, + color: Colors.orange, + ), + ), + ), + ), + ), + ); + } +} diff --git a/lib/views/widgets/StatelessWidget/SimpleDialogOption/node1_base.dart b/lib/views/widgets/StatelessWidget/SimpleDialogOption/node1_base.dart index 8b1654e..321f27c 100644 --- a/lib/views/widgets/StatelessWidget/SimpleDialogOption/node1_base.dart +++ b/lib/views/widgets/StatelessWidget/SimpleDialogOption/node1_base.dart @@ -1,6 +1,4 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_unit/views/dialogs/dialog_about.dart'; /// create by 张风捷特烈 on 2020-03-25 /// contact me by email 1981462002@qq.com @@ -25,7 +23,7 @@ class CustomSimpleDialogOption extends StatelessWidget { margin: EdgeInsets.all(5), color: Colors.grey.withAlpha(33), child: SimpleDialogOption( - onPressed: () => DialogAbout.show(context), + onPressed: () => Navigator.of(context).pushNamed('AboutMePage'), child: Text('张风捷特烈')), ), Container( @@ -35,7 +33,7 @@ class CustomSimpleDialogOption extends StatelessWidget { color: Colors.grey.withAlpha(33), margin: EdgeInsets.all(5), child: SimpleDialogOption( - onPressed: () => DialogAbout.show(context), + onPressed: () => Navigator.of(context).pushNamed('AboutMePage'), child: Text('百里·巫缨')), ), ], diff --git a/lib/views/widgets/StatelessWidget/TabBar/no_shadow_tab_bar.dart b/lib/views/widgets/StatelessWidget/TabBar/no_shadow_tab_bar.dart new file mode 100644 index 0000000..a1ae1ae --- /dev/null +++ b/lib/views/widgets/StatelessWidget/TabBar/no_shadow_tab_bar.dart @@ -0,0 +1,1345 @@ +/// create by 张风捷特烈 on 2020-03-16 +/// contact me by email 1981462002@qq.com +/// 说明: + +// Copyright 2015 The Chromium 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 'dart:async'; +import 'dart:ui' show lerpDouble; + +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter/gestures.dart' show DragStartBehavior; + + +const double _kTabHeight = 46.0; +const double _kTextAndIconTabHeight = 72.0; + +/// Defines how the bounds of the selected tab indicator are computed. +/// +/// See also: +/// +/// * [TabBar], which displays a row of tabs. +/// * [TabBarView], which displays a widget for the currently selected tab. +/// * [TabBar.indicator], which defines the appearance of the selected tab +/// indicator relative to the tab's bounds. +enum TabBarIndicatorSize { + /// The tab indicator's bounds are as wide as the space occupied by the tab + /// in the tab bar: from the right edge of the previous tab to the left edge + /// of the next tab. + tab, + + /// The tab's bounds are only as wide as the (centered) tab widget itself. + /// + /// This value is used to align the tab's label, typically a [Tab] + /// widget's text or icon, with the selected tab indicator. + label, +} + +class _TabStyle extends AnimatedWidget { + const _TabStyle({ + Key key, + Animation animation, + this.selected, + this.labelColor, + this.unselectedLabelColor, + this.labelStyle, + this.unselectedLabelStyle, + @required this.child, + }) : super(key: key, listenable: animation); + + final TextStyle labelStyle; + final TextStyle unselectedLabelStyle; + final bool selected; + final Color labelColor; + final Color unselectedLabelColor; + final Widget child; + + @override + Widget build(BuildContext context) { + final ThemeData themeData = Theme.of(context); + final TabBarTheme tabBarTheme = TabBarTheme.of(context); + final Animation animation = listenable; + + // To enable TextStyle.lerp(style1, style2, value), both styles must have + // the same value of inherit. Force that to be inherit=true here. + final TextStyle defaultStyle = (labelStyle + ?? tabBarTheme.labelStyle + ?? themeData.primaryTextTheme.body2 + ).copyWith(inherit: true); + final TextStyle defaultUnselectedStyle = (unselectedLabelStyle + ?? tabBarTheme.unselectedLabelStyle + ?? labelStyle + ?? themeData.primaryTextTheme.body2 + ).copyWith(inherit: true); + final TextStyle textStyle = selected + ? TextStyle.lerp(defaultStyle, defaultUnselectedStyle, animation.value) + : TextStyle.lerp(defaultUnselectedStyle, defaultStyle, animation.value); + + final Color selectedColor = labelColor + ?? tabBarTheme.labelColor + ?? themeData.primaryTextTheme.body2.color; + final Color unselectedColor = unselectedLabelColor + ?? tabBarTheme.unselectedLabelColor + ?? selectedColor.withAlpha(0xB2); // 70% alpha + final Color color = selected + ? Color.lerp(selectedColor, unselectedColor, animation.value) + : Color.lerp(unselectedColor, selectedColor, animation.value); + + return DefaultTextStyle( + style: textStyle.copyWith(color: color), + child: IconTheme.merge( + data: IconThemeData( + size: 24.0, + color: color, + ), + child: child, + ), + ); + } +} + +typedef _LayoutCallback = void Function(List xOffsets, TextDirection textDirection, double width); + +class _TabLabelBarRenderer extends RenderFlex { + _TabLabelBarRenderer({ + List children, + @required Axis direction, + @required MainAxisSize mainAxisSize, + @required MainAxisAlignment mainAxisAlignment, + @required CrossAxisAlignment crossAxisAlignment, + @required TextDirection textDirection, + @required VerticalDirection verticalDirection, + @required this.onPerformLayout, + }) : assert(onPerformLayout != null), + assert(textDirection != null), + super( + children: children, + direction: direction, + mainAxisSize: mainAxisSize, + mainAxisAlignment: mainAxisAlignment, + crossAxisAlignment: crossAxisAlignment, + textDirection: textDirection, + verticalDirection: verticalDirection, + ); + + _LayoutCallback onPerformLayout; + + @override + void performLayout() { + super.performLayout(); + // xOffsets will contain childCount+1 values, giving the offsets of the + // leading edge of the first tab as the first value, of the leading edge of + // the each subsequent tab as each subsequent value, and of the trailing + // edge of the last tab as the last value. + RenderBox child = firstChild; + final List xOffsets = []; + while (child != null) { + final FlexParentData childParentData = child.parentData; + xOffsets.add(childParentData.offset.dx); + assert(child.parentData == childParentData); + child = childParentData.nextSibling; + } + assert(textDirection != null); + switch (textDirection) { + case TextDirection.rtl: + xOffsets.insert(0, size.width); + break; + case TextDirection.ltr: + xOffsets.add(size.width); + break; + } + onPerformLayout(xOffsets, textDirection, size.width); + } +} + +// This class and its renderer class only exist to report the widths of the tabs +// upon layout. The tab widths are only used at paint time (see _IndicatorPainter) +// or in response to input. +class _TabLabelBar extends Flex { + _TabLabelBar({ + Key key, + List children = const [], + this.onPerformLayout, + }) : super( + key: key, + children: children, + direction: Axis.horizontal, + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + verticalDirection: VerticalDirection.down, + ); + + final _LayoutCallback onPerformLayout; + + @override + RenderFlex createRenderObject(BuildContext context) { + return _TabLabelBarRenderer( + direction: direction, + mainAxisAlignment: mainAxisAlignment, + mainAxisSize: mainAxisSize, + crossAxisAlignment: crossAxisAlignment, + textDirection: getEffectiveTextDirection(context), + verticalDirection: verticalDirection, + onPerformLayout: onPerformLayout, + ); + } + + @override + void updateRenderObject(BuildContext context, _TabLabelBarRenderer renderObject) { + super.updateRenderObject(context, renderObject); + renderObject.onPerformLayout = onPerformLayout; + } +} + +double _indexChangeProgress(TabController controller) { + final double controllerValue = controller.animation.value; + final double previousIndex = controller.previousIndex.toDouble(); + final double currentIndex = controller.index.toDouble(); + + // The controller's offset is changing because the user is dragging the + // TabBarView's PageView to the left or right. + if (!controller.indexIsChanging) + return (currentIndex - controllerValue).abs().clamp(0.0, 1.0); + + // The TabController animation's value is changing from previousIndex to currentIndex. + return (controllerValue - currentIndex).abs() / (currentIndex - previousIndex).abs(); +} + +class _IndicatorPainter extends CustomPainter { + _IndicatorPainter({ + @required this.controller, + @required this.indicator, + @required this.indicatorSize, + @required this.tabKeys, + _IndicatorPainter old, + }) : assert(controller != null), + assert(indicator != null), + super(repaint: controller.animation) { + if (old != null) + saveTabOffsets(old._currentTabOffsets, old._currentTextDirection); + } + + final TabController controller; + final Decoration indicator; + final TabBarIndicatorSize indicatorSize; + final List tabKeys; + + List _currentTabOffsets; + TextDirection _currentTextDirection; + Rect _currentRect; + BoxPainter _painter; + bool _needsPaint = false; + void markNeedsPaint() { + _needsPaint = true; + } + + void dispose() { + _painter?.dispose(); + } + + void saveTabOffsets(List tabOffsets, TextDirection textDirection) { + _currentTabOffsets = tabOffsets; + _currentTextDirection = textDirection; + } + + // _currentTabOffsets[index] is the offset of the start edge of the tab at index, and + // _currentTabOffsets[_currentTabOffsets.length] is the end edge of the last tab. + int get maxTabIndex => _currentTabOffsets.length - 2; + + double centerOf(int tabIndex) { + assert(_currentTabOffsets != null); + assert(_currentTabOffsets.isNotEmpty); + assert(tabIndex >= 0); + assert(tabIndex <= maxTabIndex); + return (_currentTabOffsets[tabIndex] + _currentTabOffsets[tabIndex + 1]) / 2.0; + } + + Rect indicatorRect(Size tabBarSize, int tabIndex) { + assert(_currentTabOffsets != null); + assert(_currentTextDirection != null); + assert(_currentTabOffsets.isNotEmpty); + assert(tabIndex >= 0); + assert(tabIndex <= maxTabIndex); + double tabLeft, tabRight; + switch (_currentTextDirection) { + case TextDirection.rtl: + tabLeft = _currentTabOffsets[tabIndex + 1]; + tabRight = _currentTabOffsets[tabIndex]; + break; + case TextDirection.ltr: + tabLeft = _currentTabOffsets[tabIndex]; + tabRight = _currentTabOffsets[tabIndex + 1]; + break; + } + + if (indicatorSize == TabBarIndicatorSize.label) { + final double tabWidth = tabKeys[tabIndex].currentContext.size.width; + final double delta = ((tabRight - tabLeft) - tabWidth) / 2.0; + tabLeft += delta; + tabRight -= delta; + } + + return Rect.fromLTWH(tabLeft, 0.0, tabRight - tabLeft, tabBarSize.height); + } + + @override + void paint(Canvas canvas, Size size) { + _needsPaint = false; + _painter ??= indicator.createBoxPainter(markNeedsPaint); + + if (controller.indexIsChanging) { + // The user tapped on a tab, the tab controller's animation is running. + final Rect targetRect = indicatorRect(size, controller.index); + _currentRect = Rect.lerp(targetRect, _currentRect ?? targetRect, _indexChangeProgress(controller)); + } else { + // The user is dragging the TabBarView's PageView left or right. + final int currentIndex = controller.index; + final Rect previous = currentIndex > 0 ? indicatorRect(size, currentIndex - 1) : null; + final Rect middle = indicatorRect(size, currentIndex); + final Rect next = currentIndex < maxTabIndex ? indicatorRect(size, currentIndex + 1) : null; + final double index = controller.index.toDouble(); + final double value = controller.animation.value; + if (value == index - 1.0) + _currentRect = previous ?? middle; + else if (value == index + 1.0) + _currentRect = next ?? middle; + else if (value == index) + _currentRect = middle; + else if (value < index) + _currentRect = previous == null ? middle : Rect.lerp(middle, previous, index - value); + else + _currentRect = next == null ? middle : Rect.lerp(middle, next, value - index); + } + assert(_currentRect != null); + + final ImageConfiguration configuration = ImageConfiguration( + size: _currentRect.size, + textDirection: _currentTextDirection, + ); + _painter.paint(canvas, _currentRect.topLeft, configuration); + } + + static bool _tabOffsetsEqual(List a, List b) { + // TODO(shihaohong): The following null check should be replaced when a fix + // for https://github.com/flutter/flutter/issues/40014 is available. + if (a == null || b == null || a.length != b.length) + return false; + for (int i = 0; i < a.length; i += 1) { + if (a[i] != b[i]) + return false; + } + return true; + } + + @override + bool shouldRepaint(_IndicatorPainter old) { + return _needsPaint + || controller != old.controller + || indicator != old.indicator + || tabKeys.length != old.tabKeys.length + || (!_tabOffsetsEqual(_currentTabOffsets, old._currentTabOffsets)) + || _currentTextDirection != old._currentTextDirection; + } +} + +class _ChangeAnimation extends Animation with AnimationWithParentMixin { + _ChangeAnimation(this.controller); + + final TabController controller; + + @override + Animation get parent => controller.animation; + + @override + void removeStatusListener(AnimationStatusListener listener) { + if (parent != null) + super.removeStatusListener(listener); + } + + @override + void removeListener(VoidCallback listener) { + if (parent != null) + super.removeListener(listener); + } + + @override + double get value => _indexChangeProgress(controller); +} + +class _DragAnimation extends Animation with AnimationWithParentMixin { + _DragAnimation(this.controller, this.index); + + final TabController controller; + final int index; + + @override + Animation get parent => controller.animation; + + @override + void removeStatusListener(AnimationStatusListener listener) { + if (parent != null) + super.removeStatusListener(listener); + } + + @override + void removeListener(VoidCallback listener) { + if (parent != null) + super.removeListener(listener); + } + + @override + double get value { + assert(!controller.indexIsChanging); + return (controller.animation.value - index.toDouble()).abs().clamp(0.0, 1.0); + } +} + +// This class, and TabBarScrollController, only exist to handle the case +// where a scrollable TabBar has a non-zero initialIndex. In that case we can +// only compute the scroll position's initial scroll offset (the "correct" +// pixels value) after the TabBar viewport width and scroll limits are known. +class _TabBarScrollPosition extends ScrollPositionWithSingleContext { + _TabBarScrollPosition({ + ScrollPhysics physics, + ScrollContext context, + ScrollPosition oldPosition, + this.tabBar, + }) : super( + physics: physics, + context: context, + initialPixels: null, + oldPosition: oldPosition, + ); + + final _TabBarState tabBar; + + bool _initialViewportDimensionWasZero; + + @override + bool applyContentDimensions(double minScrollExtent, double maxScrollExtent) { + bool result = true; + if (_initialViewportDimensionWasZero != true) { + // If the viewport never had a non-zero dimension, we just want to jump + // to the initial scroll position to avoid strange scrolling effects in + // release mode: In release mode, the viewport temporarily may have a + // dimension of zero before the actual dimension is calculated. In that + // scenario, setting the actual dimension would cause a strange scroll + // effect without this guard because the super call below would starts a + // ballistic scroll activity. + assert(viewportDimension != null); + _initialViewportDimensionWasZero = viewportDimension != 0.0; + correctPixels(tabBar._initialScrollOffset(viewportDimension, minScrollExtent, maxScrollExtent)); + result = false; + } + return super.applyContentDimensions(minScrollExtent, maxScrollExtent) && result; + } +} + +// This class, and TabBarScrollPosition, only exist to handle the case +// where a scrollable TabBar has a non-zero initialIndex. +class _TabBarScrollController extends ScrollController { + _TabBarScrollController(this.tabBar); + + final _TabBarState tabBar; + + @override + ScrollPosition createScrollPosition(ScrollPhysics physics, ScrollContext context, ScrollPosition oldPosition) { + return _TabBarScrollPosition( + physics: physics, + context: context, + oldPosition: oldPosition, + tabBar: tabBar, + ); + } +} + +/// A material design widget that displays a horizontal row of tabs. +/// +/// Typically created as the [AppBar.bottom] part of an [AppBar] and in +/// conjunction with a [TabBarView]. +/// +/// If a [TabController] is not provided, then a [DefaultTabController] ancestor +/// must be provided instead. The tab controller's [TabController.length] must +/// equal the length of the [tabs] list and the length of the +/// [TabBarView.children] list. +/// +/// Requires one of its ancestors to be a [Material] widget. +/// +/// Uses values from [TabBarTheme] if it is set in the current context. +/// +/// To see a sample implementation, visit the [TabController] documentation. +/// +/// See also: +/// +/// * [TabBarView], which displays page views that correspond to each tab. +class NoShadowTabBar extends StatefulWidget implements PreferredSizeWidget { + /// Creates a material design tab bar. + /// + /// The [tabs] argument must not be null and its length must match the [controller]'s + /// [TabController.length]. + /// + /// If a [TabController] is not provided, then there must be a + /// [DefaultTabController] ancestor. + /// + /// The [indicatorWeight] parameter defaults to 2, and must not be null. + /// + /// The [indicatorPadding] parameter defaults to [EdgeInsets.zero], and must not be null. + /// + /// If [indicator] is not null, then [indicatorWeight], [indicatorPadding], and + /// [indicatorColor] are ignored. + const NoShadowTabBar({ + Key key, + @required this.tabs, + this.controller, + this.isScrollable = false, + this.indicatorColor, + this.indicatorWeight = 2.0, + this.indicatorPadding = EdgeInsets.zero, + this.indicator, + this.indicatorSize, + this.labelColor, + this.labelStyle, + this.labelPadding, + this.unselectedLabelColor, + this.unselectedLabelStyle, + this.dragStartBehavior = DragStartBehavior.start, + this.onTap, + }) : assert(tabs != null), + assert(isScrollable != null), + assert(dragStartBehavior != null), + assert(indicator != null || (indicatorWeight != null && indicatorWeight > 0.0)), + assert(indicator != null || (indicatorPadding != null)), + super(key: key); + + /// Typically a list of two or more [Tab] widgets. + /// + /// The length of this list must match the [controller]'s [TabController.length] + /// and the length of the [TabBarView.children] list. + final List tabs; + + /// This widget's selection and animation state. + /// + /// If [TabController] is not provided, then the value of [DefaultTabController.of] + /// will be used. + final TabController controller; + + /// Whether this tab bar can be scrolled horizontally. + /// + /// If [isScrollable] is true, then each tab is as wide as needed for its label + /// and the entire [TabBar] is scrollable. Otherwise each tab gets an equal + /// share of the available space. + final bool isScrollable; + + /// The color of the line that appears below the selected tab. + /// + /// If this parameter is null, then the value of the Theme's indicatorColor + /// property is used. + /// + /// If [indicator] is specified, this property is ignored. + final Color indicatorColor; + + /// The thickness of the line that appears below the selected tab. + /// + /// The value of this parameter must be greater than zero and its default + /// value is 2.0. + /// + /// If [indicator] is specified, this property is ignored. + final double indicatorWeight; + + /// The horizontal padding for the line that appears below the selected tab. + /// + /// For [isScrollable] tab bars, specifying [kTabLabelPadding] will align + /// the indicator with the tab's text for [Tab] widgets and all but the + /// shortest [Tab.text] values. + /// + /// The [EdgeInsets.top] and [EdgeInsets.bottom] values of the + /// [indicatorPadding] are ignored. + /// + /// The default value of [indicatorPadding] is [EdgeInsets.zero]. + /// + /// If [indicator] is specified, this property is ignored. + final EdgeInsetsGeometry indicatorPadding; + + /// Defines the appearance of the selected tab indicator. + /// + /// If [indicator] is specified, the [indicatorColor], [indicatorWeight], + /// and [indicatorPadding] properties are ignored. + /// + /// The default, underline-style, selected tab indicator can be defined with + /// [UnderlineTabIndicator]. + /// + /// The indicator's size is based on the tab's bounds. If [indicatorSize] + /// is [TabBarIndicatorSize.tab] the tab's bounds are as wide as the space + /// occupied by the tab in the tab bar. If [indicatorSize] is + /// [TabBarIndicatorSize.label], then the tab's bounds are only as wide as + /// the tab widget itself. + final Decoration indicator; + + /// Defines how the selected tab indicator's size is computed. + /// + /// The size of the selected tab indicator is defined relative to the + /// tab's overall bounds if [indicatorSize] is [TabBarIndicatorSize.tab] + /// (the default) or relative to the bounds of the tab's widget if + /// [indicatorSize] is [TabBarIndicatorSize.label]. + /// + /// The selected tab's location appearance can be refined further with + /// the [indicatorColor], [indicatorWeight], [indicatorPadding], and + /// [indicator] properties. + final TabBarIndicatorSize indicatorSize; + + /// The color of selected tab labels. + /// + /// Unselected tab labels are rendered with the same color rendered at 70% + /// opacity unless [unselectedLabelColor] is non-null. + /// + /// If this parameter is null, then the color of the [ThemeData.primaryTextTheme]'s + /// body2 text color is used. + final Color labelColor; + + /// The color of unselected tab labels. + /// + /// If this property is null, unselected tab labels are rendered with the + /// [labelColor] with 70% opacity. + final Color unselectedLabelColor; + + /// The text style of the selected tab labels. + /// + /// If [unselectedLabelStyle] is null, then this text style will be used for + /// both selected and unselected label styles. + /// + /// If this property is null, then the text style of the + /// [ThemeData.primaryTextTheme]'s body2 definition is used. + final TextStyle labelStyle; + + /// The padding added to each of the tab labels. + /// + /// If this property is null, then kTabLabelPadding is used. + final EdgeInsetsGeometry labelPadding; + + /// The text style of the unselected tab labels + /// + /// If this property is null, then the [labelStyle] value is used. If [labelStyle] + /// is null, then the text style of the [ThemeData.primaryTextTheme]'s + /// body2 definition is used. + final TextStyle unselectedLabelStyle; + + /// {@macro flutter.widgets.scrollable.dragStartBehavior} + final DragStartBehavior dragStartBehavior; + + /// An optional callback that's called when the [TabBar] is tapped. + /// + /// The callback is applied to the index of the tab where the tap occurred. + /// + /// This callback has no effect on the default handling of taps. It's for + /// applications that want to do a little extra work when a tab is tapped, + /// even if the tap doesn't change the TabController's index. TabBar [onTap] + /// callbacks should not make changes to the TabController since that would + /// interfere with the default tap handler. + final ValueChanged onTap; + + /// A size whose height depends on if the tabs have both icons and text. + /// + /// [AppBar] uses this size to compute its own preferred size. + @override + Size get preferredSize { + for (Widget item in tabs) { + if (item is Tab) { + final Tab tab = item; + if (tab.text != null && tab.icon != null) + return Size.fromHeight(_kTextAndIconTabHeight + indicatorWeight); + } + } + return Size.fromHeight(_kTabHeight + indicatorWeight); + } + + @override + _TabBarState createState() => _TabBarState(); +} + +class _TabBarState extends State { + ScrollController _scrollController; + TabController _controller; + _IndicatorPainter _indicatorPainter; + int _currentIndex; + double _tabStripWidth; + List _tabKeys; + + @override + void initState() { + super.initState(); + // If indicatorSize is TabIndicatorSize.label, _tabKeys[i] is used to find + // the width of tab widget i. See _IndicatorPainter.indicatorRect(). + _tabKeys = widget.tabs.map((Widget tab) => GlobalKey()).toList(); + } + + Decoration get _indicator { + if (widget.indicator != null) + return widget.indicator; + final TabBarTheme tabBarTheme = TabBarTheme.of(context); + if (tabBarTheme.indicator != null) + return tabBarTheme.indicator; + + Color color = widget.indicatorColor ?? Theme.of(context).indicatorColor; + // ThemeData tries to avoid this by having indicatorColor avoid being the + // primaryColor. However, it's possible that the tab bar is on a + // Material that isn't the primaryColor. In that case, if the indicator + // color ends up matching the material's color, then this overrides it. + // When that happens, automatic transitions of the theme will likely look + // ugly as the indicator color suddenly snaps to white at one end, but it's + // not clear how to avoid that any further. + // + // The material's color might be null (if it's a transparency). In that case + // there's no good way for us to find out what the color is so we don't. + if (color.value == Material.of(context).color?.value) + color = Colors.white; + + return UnderlineTabIndicator( + insets: widget.indicatorPadding, + borderSide: BorderSide( + width: widget.indicatorWeight, + color: color, + ), + ); + } + + // If the TabBar is rebuilt with a new tab controller, the caller should + // dispose the old one. In that case the old controller's animation will be + // null and should not be accessed. + bool get _controllerIsValid => _controller?.animation != null; + + void _updateTabController() { + final TabController newController = widget.controller ?? DefaultTabController.of(context); + assert(() { + if (newController == null) { + throw FlutterError( + 'No TabController for ${widget.runtimeType}.\n' + 'When creating a ${widget.runtimeType}, you must either provide an explicit ' + 'TabController using the "controller" property, or you must ensure that there ' + 'is a DefaultTabController above the ${widget.runtimeType}.\n' + 'In this case, there was neither an explicit controller nor a default controller.' + ); + } + return true; + }()); + + if (newController == _controller) + return; + + if (_controllerIsValid) { + _controller.animation.removeListener(_handleTabControllerAnimationTick); + _controller.removeListener(_handleTabControllerTick); + } + _controller = newController; + if (_controller != null) { + _controller.animation.addListener(_handleTabControllerAnimationTick); + _controller.addListener(_handleTabControllerTick); + _currentIndex = _controller.index; + } + } + + void _initIndicatorPainter() { + _indicatorPainter = !_controllerIsValid ? null : _IndicatorPainter( + controller: _controller, + indicator: _indicator, + indicatorSize: widget.indicatorSize ?? TabBarTheme.of(context).indicatorSize, + tabKeys: _tabKeys, + old: _indicatorPainter, + ); + } + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + assert(debugCheckHasMaterial(context)); + _updateTabController(); + _initIndicatorPainter(); + } + + @override + void didUpdateWidget(NoShadowTabBar oldWidget) { + super.didUpdateWidget(oldWidget); + if (widget.controller != oldWidget.controller) { + _updateTabController(); + _initIndicatorPainter(); + } else if (widget.indicatorColor != oldWidget.indicatorColor || + widget.indicatorWeight != oldWidget.indicatorWeight || + widget.indicatorSize != oldWidget.indicatorSize || + widget.indicator != oldWidget.indicator) { + _initIndicatorPainter(); + } + + if (widget.tabs.length > oldWidget.tabs.length) { + final int delta = widget.tabs.length - oldWidget.tabs.length; + _tabKeys.addAll(List.generate(delta, (int n) => GlobalKey())); + } else if (widget.tabs.length < oldWidget.tabs.length) { + _tabKeys.removeRange(widget.tabs.length, oldWidget.tabs.length); + } + } + + @override + void dispose() { + _indicatorPainter.dispose(); + if (_controllerIsValid) { + _controller.animation.removeListener(_handleTabControllerAnimationTick); + _controller.removeListener(_handleTabControllerTick); + } + _controller = null; + // We don't own the _controller Animation, so it's not disposed here. + super.dispose(); + } + + int get maxTabIndex => _indicatorPainter.maxTabIndex; + + double _tabScrollOffset(int index, double viewportWidth, double minExtent, double maxExtent) { + if (!widget.isScrollable) + return 0.0; + double tabCenter = _indicatorPainter.centerOf(index); + switch (Directionality.of(context)) { + case TextDirection.rtl: + tabCenter = _tabStripWidth - tabCenter; + break; + case TextDirection.ltr: + break; + } + return (tabCenter - viewportWidth / 2.0).clamp(minExtent, maxExtent); + } + + double _tabCenteredScrollOffset(int index) { + final ScrollPosition position = _scrollController.position; + return _tabScrollOffset(index, position.viewportDimension, position.minScrollExtent, position.maxScrollExtent); + } + + double _initialScrollOffset(double viewportWidth, double minExtent, double maxExtent) { + return _tabScrollOffset(_currentIndex, viewportWidth, minExtent, maxExtent); + } + + void _scrollToCurrentIndex() { + final double offset = _tabCenteredScrollOffset(_currentIndex); + _scrollController.animateTo(offset, duration: kTabScrollDuration, curve: Curves.ease); + } + + void _scrollToControllerValue() { + final double leadingPosition = _currentIndex > 0 ? _tabCenteredScrollOffset(_currentIndex - 1) : null; + final double middlePosition = _tabCenteredScrollOffset(_currentIndex); + final double trailingPosition = _currentIndex < maxTabIndex ? _tabCenteredScrollOffset(_currentIndex + 1) : null; + + final double index = _controller.index.toDouble(); + final double value = _controller.animation.value; + double offset; + if (value == index - 1.0) + offset = leadingPosition ?? middlePosition; + else if (value == index + 1.0) + offset = trailingPosition ?? middlePosition; + else if (value == index) + offset = middlePosition; + else if (value < index) + offset = leadingPosition == null ? middlePosition : lerpDouble(middlePosition, leadingPosition, index - value); + else + offset = trailingPosition == null ? middlePosition : lerpDouble(middlePosition, trailingPosition, value - index); + + _scrollController.jumpTo(offset); + } + + void _handleTabControllerAnimationTick() { + assert(mounted); + if (!_controller.indexIsChanging && widget.isScrollable) { + // Sync the TabBar's scroll position with the TabBarView's PageView. + _currentIndex = _controller.index; + _scrollToControllerValue(); + } + } + + void _handleTabControllerTick() { + if (_controller.index != _currentIndex) { + _currentIndex = _controller.index; + if (widget.isScrollable) + _scrollToCurrentIndex(); + } + setState(() { + // Rebuild the tabs after a (potentially animated) index change + // has completed. + }); + } + + // Called each time layout completes. + void _saveTabOffsets(List tabOffsets, TextDirection textDirection, double width) { + _tabStripWidth = width; + _indicatorPainter?.saveTabOffsets(tabOffsets, textDirection); + } + + void _handleTap(int index) { + assert(index >= 0 && index < widget.tabs.length); + _controller.animateTo(index); + if (widget.onTap != null) { + widget.onTap(index); + } + } + + Widget _buildStyledTab(Widget child, bool selected, Animation animation) { + return _TabStyle( + animation: animation, + selected: selected, + labelColor: widget.labelColor, + unselectedLabelColor: widget.unselectedLabelColor, + labelStyle: widget.labelStyle, + unselectedLabelStyle: widget.unselectedLabelStyle, + child: child, + ); + } + + @override + Widget build(BuildContext context) { + assert(debugCheckHasMaterialLocalizations(context)); + assert(() { + if (_controller.length != widget.tabs.length) { + throw FlutterError( + 'Controller\'s length property (${_controller.length}) does not match the \n' + 'number of tabs (${widget.tabs.length}) present in TabBar\'s tabs property.' + ); + } + return true; + }()); + final MaterialLocalizations localizations = MaterialLocalizations.of(context); + if (_controller.length == 0) { + return Container( + height: _kTabHeight + widget.indicatorWeight, + ); + } + + final TabBarTheme tabBarTheme = TabBarTheme.of(context); + + final List wrappedTabs = List(widget.tabs.length); + for (int i = 0; i < widget.tabs.length; i += 1) { + wrappedTabs[i] = Center( + heightFactor: 1.0, + child: Padding( + padding: widget.labelPadding ?? tabBarTheme.labelPadding ?? kTabLabelPadding, + child: KeyedSubtree( + key: _tabKeys[i], + child: widget.tabs[i], + ), + ), + ); + + } + + // If the controller was provided by DefaultTabController and we're part + // of a Hero (typically the AppBar), then we will not be able to find the + // controller during a Hero transition. See https://github.com/flutter/flutter/issues/213. + if (_controller != null) { + final int previousIndex = _controller.previousIndex; + + if (_controller.indexIsChanging) { + // The user tapped on a tab, the tab controller's animation is running. + assert(_currentIndex != previousIndex); + final Animation animation = _ChangeAnimation(_controller); + wrappedTabs[_currentIndex] = _buildStyledTab(wrappedTabs[_currentIndex], true, animation); + wrappedTabs[previousIndex] = _buildStyledTab(wrappedTabs[previousIndex], false, animation); + } else { + // The user is dragging the TabBarView's PageView left or right. + final int tabIndex = _currentIndex; + final Animation centerAnimation = _DragAnimation(_controller, tabIndex); + wrappedTabs[tabIndex] = _buildStyledTab(wrappedTabs[tabIndex], true, centerAnimation); + if (_currentIndex > 0) { + final int tabIndex = _currentIndex - 1; + final Animation previousAnimation = ReverseAnimation(_DragAnimation(_controller, tabIndex)); + wrappedTabs[tabIndex] = _buildStyledTab(wrappedTabs[tabIndex], false, previousAnimation); + } + if (_currentIndex < widget.tabs.length - 1) { + final int tabIndex = _currentIndex + 1; + final Animation nextAnimation = ReverseAnimation(_DragAnimation(_controller, tabIndex)); + wrappedTabs[tabIndex] = _buildStyledTab(wrappedTabs[tabIndex], false, nextAnimation); + } + } + } + + // Add the tap handler to each tab. If the tab bar is not scrollable, + // then give all of the tabs equal flexibility so that they each occupy + // the same share of the tab bar's overall width. + final int tabCount = widget.tabs.length; + for (int index = 0; index < tabCount; index += 1) { + wrappedTabs[index] = GestureDetector( + onTap: () { _handleTap(index); }, + child: Container( + color: Colors.transparent, + padding: EdgeInsets.only(bottom: widget.indicatorWeight), + child: Stack( + children: [ + wrappedTabs[index], + Semantics( + selected: index == _currentIndex, + label: localizations.tabLabel(tabIndex: index + 1, tabCount: tabCount), + ), + ], + ), + ), + ); + if (!widget.isScrollable) + wrappedTabs[index] = Expanded(child: wrappedTabs[index]); + } + + Widget tabBar = CustomPaint( + painter: _indicatorPainter, + child: _TabStyle( + animation: kAlwaysDismissedAnimation, + selected: false, + labelColor: widget.labelColor, + unselectedLabelColor: widget.unselectedLabelColor, + labelStyle: widget.labelStyle, + unselectedLabelStyle: widget.unselectedLabelStyle, + child: _TabLabelBar( + onPerformLayout: _saveTabOffsets, + children: wrappedTabs, + ), + ), + ); + + if (widget.isScrollable) { + _scrollController ??= _TabBarScrollController(this); + tabBar = SingleChildScrollView( + dragStartBehavior: widget.dragStartBehavior, + scrollDirection: Axis.horizontal, + controller: _scrollController, + child: tabBar, + ); + } + + return tabBar; + } +} + + +final PageScrollPhysics _kTabBarViewPhysics = const PageScrollPhysics().applyTo(const ClampingScrollPhysics()); + +class _TabBarViewState extends State { + TabController _controller; + PageController _pageController; + List _children; + List _childrenWithKey; + int _currentIndex; + int _warpUnderwayCount = 0; + + // If the TabBarView is rebuilt with a new tab controller, the caller should + // dispose the old one. In that case the old controller's animation will be + // null and should not be accessed. + bool get _controllerIsValid => _controller?.animation != null; + + void _updateTabController() { + final TabController newController = widget.controller ?? DefaultTabController.of(context); + assert(() { + if (newController == null) { + throw FlutterError( + 'No TabController for ${widget.runtimeType}.\n' + 'When creating a ${widget.runtimeType}, you must either provide an explicit ' + 'TabController using the "controller" property, or you must ensure that there ' + 'is a DefaultTabController above the ${widget.runtimeType}.\n' + 'In this case, there was neither an explicit controller nor a default controller.' + ); + } + return true; + }()); + + if (newController == _controller) + return; + + if (_controllerIsValid) + _controller.animation.removeListener(_handleTabControllerAnimationTick); + _controller = newController; + if (_controller != null) + _controller.animation.addListener(_handleTabControllerAnimationTick); + } + + @override + void initState() { + super.initState(); + _updateChildren(); + } + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + _updateTabController(); + _currentIndex = _controller?.index; + _pageController = PageController(initialPage: _currentIndex ?? 0); + } + + @override + void didUpdateWidget(TabBarView oldWidget) { + super.didUpdateWidget(oldWidget); + if (widget.controller != oldWidget.controller) + _updateTabController(); + if (widget.children != oldWidget.children && _warpUnderwayCount == 0) + _updateChildren(); + } + + @override + void dispose() { + if (_controllerIsValid) + _controller.animation.removeListener(_handleTabControllerAnimationTick); + _controller = null; + // We don't own the _controller Animation, so it's not disposed here. + super.dispose(); + } + + void _updateChildren() { + _children = widget.children; + _childrenWithKey = KeyedSubtree.ensureUniqueKeysForList(widget.children); + } + + void _handleTabControllerAnimationTick() { + if (_warpUnderwayCount > 0 || !_controller.indexIsChanging) + return; // This widget is driving the controller's animation. + + if (_controller.index != _currentIndex) { + _currentIndex = _controller.index; + _warpToCurrentIndex(); + } + } + + Future _warpToCurrentIndex() async { + if (!mounted) + return Future.value(); + + if (_pageController.page == _currentIndex.toDouble()) + return Future.value(); + + final int previousIndex = _controller.previousIndex; + if ((_currentIndex - previousIndex).abs() == 1) + return _pageController.animateToPage(_currentIndex, duration: kTabScrollDuration, curve: Curves.ease); + + assert((_currentIndex - previousIndex).abs() > 1); + final int initialPage = _currentIndex > previousIndex + ? _currentIndex - 1 + : _currentIndex + 1; + final List originalChildren = _childrenWithKey; + setState(() { + _warpUnderwayCount += 1; + + _childrenWithKey = List.from(_childrenWithKey, growable: false); + final Widget temp = _childrenWithKey[initialPage]; + _childrenWithKey[initialPage] = _childrenWithKey[previousIndex]; + _childrenWithKey[previousIndex] = temp; + }); + _pageController.jumpToPage(initialPage); + + await _pageController.animateToPage(_currentIndex, duration: kTabScrollDuration, curve: Curves.ease); + if (!mounted) + return Future.value(); + setState(() { + _warpUnderwayCount -= 1; + if (widget.children != _children) { + _updateChildren(); + } else { + _childrenWithKey = originalChildren; + } + }); + } + + // Called when the PageView scrolls + bool _handleScrollNotification(ScrollNotification notification) { + if (_warpUnderwayCount > 0) + return false; + + if (notification.depth != 0) + return false; + + _warpUnderwayCount += 1; + if (notification is ScrollUpdateNotification && !_controller.indexIsChanging) { + if ((_pageController.page - _controller.index).abs() > 1.0) { + _controller.index = _pageController.page.floor(); + _currentIndex =_controller.index; + } + _controller.offset = (_pageController.page - _controller.index).clamp(-1.0, 1.0); + } else if (notification is ScrollEndNotification) { + _controller.index = _pageController.page.round(); + _currentIndex = _controller.index; + } + _warpUnderwayCount -= 1; + + return false; + } + + @override + Widget build(BuildContext context) { + assert(() { + if (_controller.length != widget.children.length) { + throw FlutterError( + 'Controller\'s length property (${_controller.length}) does not match the \n' + 'number of tabs (${widget.children.length}) present in TabBar\'s tabs property.' + ); + } + return true; + }()); + return NotificationListener( + onNotification: _handleScrollNotification, + child: PageView( + dragStartBehavior: widget.dragStartBehavior, + controller: _pageController, + physics: widget.physics == null ? _kTabBarViewPhysics : _kTabBarViewPhysics.applyTo(widget.physics), + children: _childrenWithKey, + ), + ); + } +} + +/// Displays a single circle with the specified border and background colors. +/// +/// Used by [TabPageSelector] to indicate the selected page. +class TabPageSelectorIndicator extends StatelessWidget { + /// Creates an indicator used by [TabPageSelector]. + /// + /// The [backgroundColor], [borderColor], and [size] parameters must not be null. + const TabPageSelectorIndicator({ + Key key, + @required this.backgroundColor, + @required this.borderColor, + @required this.size, + }) : assert(backgroundColor != null), + assert(borderColor != null), + assert(size != null), + super(key: key); + + /// The indicator circle's background color. + final Color backgroundColor; + + /// The indicator circle's border color. + final Color borderColor; + + /// The indicator circle's diameter. + final double size; + + @override + Widget build(BuildContext context) { + return Container( + width: size, + height: size, + margin: const EdgeInsets.all(4.0), + decoration: BoxDecoration( + color: backgroundColor, + border: Border.all(color: borderColor), + shape: BoxShape.circle, + ), + ); + } +} + +/// Displays a row of small circular indicators, one per tab. +/// +/// The selected tab's indicator is highlighted. Often used in conjunction with +/// a [TabBarView]. +/// +/// If a [TabController] is not provided, then there must be a +/// [DefaultTabController] ancestor. +class TabPageSelector extends StatelessWidget { + /// Creates a compact widget that indicates which tab has been selected. + const TabPageSelector({ + Key key, + this.controller, + this.indicatorSize = 12.0, + this.color, + this.selectedColor, + }) : assert(indicatorSize != null && indicatorSize > 0.0), + super(key: key); + + /// This widget's selection and animation state. + /// + /// If [TabController] is not provided, then the value of + /// [DefaultTabController.of] will be used. + final TabController controller; + + /// The indicator circle's diameter (the default value is 12.0). + final double indicatorSize; + + /// The indicator circle's fill color for unselected pages. + /// + /// If this parameter is null, then the indicator is filled with [Colors.transparent]. + final Color color; + + /// The indicator circle's fill color for selected pages and border color + /// for all indicator circles. + /// + /// If this parameter is null, then the indicator is filled with the theme's + /// accent color, [ThemeData.accentColor]. + final Color selectedColor; + + Widget _buildTabIndicator( + int tabIndex, + TabController tabController, + ColorTween selectedColorTween, + ColorTween previousColorTween, + ) { + Color background; + if (tabController.indexIsChanging) { + // The selection's animation is animating from previousValue to value. + final double t = 1.0 - _indexChangeProgress(tabController); + if (tabController.index == tabIndex) + background = selectedColorTween.lerp(t); + else if (tabController.previousIndex == tabIndex) + background = previousColorTween.lerp(t); + else + background = selectedColorTween.begin; + } else { + // The selection's offset reflects how far the TabBarView has / been dragged + // to the previous page (-1.0 to 0.0) or the next page (0.0 to 1.0). + final double offset = tabController.offset; + if (tabController.index == tabIndex) { + background = selectedColorTween.lerp(1.0 - offset.abs()); + } else if (tabController.index == tabIndex - 1 && offset > 0.0) { + background = selectedColorTween.lerp(offset); + } else if (tabController.index == tabIndex + 1 && offset < 0.0) { + background = selectedColorTween.lerp(-offset); + } else { + background = selectedColorTween.begin; + } + } + return TabPageSelectorIndicator( + backgroundColor: background, + borderColor: selectedColorTween.end, + size: indicatorSize, + ); + } + + @override + Widget build(BuildContext context) { + final Color fixColor = color ?? Colors.transparent; + final Color fixSelectedColor = selectedColor ?? Theme.of(context).accentColor; + final ColorTween selectedColorTween = ColorTween(begin: fixColor, end: fixSelectedColor); + final ColorTween previousColorTween = ColorTween(begin: fixSelectedColor, end: fixColor); + final TabController tabController = controller ?? DefaultTabController.of(context); + assert(() { + if (tabController == null) { + throw FlutterError( + 'No TabController for $runtimeType.\n' + 'When creating a $runtimeType, you must either provide an explicit TabController ' + 'using the "controller" property, or you must ensure that there is a ' + 'DefaultTabController above the $runtimeType.\n' + 'In this case, there was neither an explicit controller nor a default controller.' + ); + } + return true; + }()); + final Animation animation = CurvedAnimation( + parent: tabController.animation, + curve: Curves.fastOutSlowIn, + ); + return AnimatedBuilder( + animation: animation, + builder: (BuildContext context, Widget child) { + return Semantics( + label: 'Page ${tabController.index + 1} of ${tabController.length}', + child: Row( + mainAxisSize: MainAxisSize.min, + children: List.generate(tabController.length, (int tabIndex) { + return _buildTabIndicator(tabIndex, tabController, selectedColorTween, previousColorTween); + }).toList(), + ), + ); + }, + ); + } +} diff --git a/lib/views/widgets/StatelessWidget/TabBar/node2_noShadow.dart b/lib/views/widgets/StatelessWidget/TabBar/node2_noShadow.dart index a638674..709be82 100644 --- a/lib/views/widgets/StatelessWidget/TabBar/node2_noShadow.dart +++ b/lib/views/widgets/StatelessWidget/TabBar/node2_noShadow.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:flutter_unit/components/flutter/no_shadow_tab_bar.dart'; + +import 'no_shadow_tab_bar.dart'; /// create by 张风捷特烈 on 2020/4/27 /// contact me by email 1981462002@qq.com diff --git a/lib/views/widgets/exp/render_object_unit.dart b/lib/views/widgets/exp/render_object_unit.dart index 0190ea9..1738384 100644 --- a/lib/views/widgets/exp/render_object_unit.dart +++ b/lib/views/widgets/exp/render_object_unit.dart @@ -30,13 +30,20 @@ export '../SingleChildRenderObjectWidget/ConstrainedBox/node1_base.dart'; export '../SingleChildRenderObjectWidget/ColorFiltered/node1_base.dart'; export '../SingleChildRenderObjectWidget/Baseline/node1_base.dart'; export '../SingleChildRenderObjectWidget/DecoratedBox/node1_base.dart'; +export '../SingleChildRenderObjectWidget/DecoratedBox/node2_image.dart'; +export '../SingleChildRenderObjectWidget/DecoratedBox/node3_border.dart'; +export '../SingleChildRenderObjectWidget/DecoratedBox/node4_shape.dart'; +export '../SingleChildRenderObjectWidget/DecoratedBox/node5_line.dart'; +export '../SingleChildRenderObjectWidget/DecoratedBox/node6_flutterLogo.dart'; export '../SingleChildRenderObjectWidget/FadeTransition/node1_base.dart'; export '../SingleChildRenderObjectWidget/FittedBox/node1_base.dart'; export '../SingleChildRenderObjectWidget/FractionallySizedBox/node1_base.dart'; export '../SingleChildRenderObjectWidget/LimiteBox/node1_base.dart'; export '../SingleChildRenderObjectWidget/OffStage/node1_base.dart'; export '../SingleChildRenderObjectWidget/Opacity/node1_base.dart'; -export '../SingleChildRenderObjectWidget/Padding/node1_base.dart'; +export '../SingleChildRenderObjectWidget/Padding/node1_all.dart'; +export '../SingleChildRenderObjectWidget/Padding/node2_only.dart'; +export '../SingleChildRenderObjectWidget/Padding/node3_symmetric.dart'; export '../SingleChildRenderObjectWidget/RotatedBox/node1_base.dart'; export '../SingleChildRenderObjectWidget/SizedBox/node1_base.dart'; export '../SingleChildRenderObjectWidget/SizedOverflowBox/node1_base.dart'; diff --git a/lib/views/widgets/exp/stateless_unit.dart b/lib/views/widgets/exp/stateless_unit.dart index 9a9e6ce..063b40a 100644 --- a/lib/views/widgets/exp/stateless_unit.dart +++ b/lib/views/widgets/exp/stateless_unit.dart @@ -7,6 +7,8 @@ export '../StatelessWidget/AlertDialog/node1_base.dart'; export '../StatelessWidget/AnimatedIcon/node1_base.dart'; export '../StatelessWidget/Card/node1_base.dart'; export '../StatelessWidget/Card/node2_shape.dart'; +export '../StatelessWidget/PreferredSize/node1_base.dart'; +export '../StatelessWidget/PreferredSize/node2_adapter.dart'; export '../StatelessWidget/CheckboxListTile/node1_base.dart'; export '../StatelessWidget/CheckboxListTile/node2_select.dart'; @@ -95,6 +97,7 @@ export '../StatelessWidget/VerticalDivider/node2_height.dart'; export '../StatelessWidget/BackButton/node1_base.dart'; export '../StatelessWidget/ButtonBar/node1_base.dart'; +export '../StatelessWidget/ButtonBar/node2_padding.dart'; export '../StatelessWidget/CloseButton/node1_base.dart'; export '../StatelessWidget/FlatButton/node1_base.dart'; diff --git a/lib/views/widgets/widgets_map.dart b/lib/views/widgets/widgets_map.dart index e01c23a..bec3e1e 100644 --- a/lib/views/widgets/widgets_map.dart +++ b/lib/views/widgets/widgets_map.dart @@ -332,7 +332,12 @@ class WidgetsMap { ]; case "DecoratedBox": return [ - CustomDecoratedBox(), + BoxDecorationDemo(), + ShapeImageDemo(), + BorderDemo(), + ShapeDecorationDemo(), + UnderlineTabIndicatorDemo(), + FlutterLogoDecorationDemo(), ]; case "Offstage": return [ @@ -348,7 +353,9 @@ class WidgetsMap { ]; case "Padding": return [ - CustomPadding(), + PaddingAll(), + PaddingOnly(), + PaddingSymmetric(), ]; case "Baseline": return [ @@ -663,6 +670,11 @@ class WidgetsMap { return [ CustomTab(), ]; + case "PreferredSize": + return [ + CustomPreferredSize(), + AdapterPreferredSize(), + ]; case "InkResponse": return [ CustomInkResponse(),