From 5cd9ab84d443edf031aca4e9c88459902c99a4c2 Mon Sep 17 00:00:00 2001 From: toly <1981462002@qq.com> Date: Mon, 10 Aug 2020 10:48:48 +0800 Subject: [PATCH] =?UTF-8?q?:sparkles:=20=E5=A2=9E=E5=8A=A0InteractiveViewe?= =?UTF-8?q?r?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 8 +- assets/flutter.db | Bin 757760 -> 761856 bytes .../InteractiveViewer/node1_base.dart | 57 +++++++ .../InteractiveViewer/node2_constrained.dart | 59 +++++++ .../InteractiveViewer/node3_controller.dart | 157 ++++++++++++++++++ lib/views/widgets/exp/stateful_unit.dart | 3 + lib/views/widgets/widgets_map.dart | 6 + 7 files changed, 286 insertions(+), 4 deletions(-) create mode 100644 lib/views/widgets/StatefulWidget/InteractiveViewer/node1_base.dart create mode 100644 lib/views/widgets/StatefulWidget/InteractiveViewer/node2_constrained.dart create mode 100644 lib/views/widgets/StatefulWidget/InteractiveViewer/node3_controller.dart diff --git a/README.md b/README.md index 73558c0..2ccf7c4 100644 --- a/README.md +++ b/README.md @@ -31,10 +31,10 @@ ``` a1@toly ~ % flutter --version -Flutter 1.17.4 • channel stable • https://github.com/flutter/flutter.git -Framework • revision 1ad9baa8b9 (4 weeks ago) • 2020-06-17 14:41:16 -0700 -Engine • revision ee76268252 -Tools • Dart 2.8.4 +Flutter 1.20.1 • channel stable • https://github.com/flutter/flutter.git +Framework • revision 2ae34518b8 (2 days ago) • 2020-08-05 19:53:19 -0700 +Engine • revision c8e3b94853 +Tools • Dart 2.9.0 ``` --- diff --git a/assets/flutter.db b/assets/flutter.db index 717bfd3dcce7f545726d75fa3a0d3daa60dadbb2..f794d19427c08590dcab1730f3bf8670b9503cd1 100644 GIT binary patch delta 7599 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 Vvvku);%|@_b95#7yM1yV`#;x7$tC~* delta 2798 zcmZwId2AHd9S87vGru>-nt2%`8{(O zI|l59T?&{&APGr<0#5xaC{(5m5j~PZgR1oSBPk(@NRu=vAcWGUzo}Fy5NmfoBhByq z-kX{4+uhoZl-lDd`+M{Knx^z*`7>2Oo>kMyGinO? zrkX^)p$rIaE79EbOAo&xOK^{|SWUKlS zc~p%ckEmhfVKs#Ou^LPsQiI5t8bC%>fAXN}M;=gp$cTEDY*EjU%_@=HuX>RCR06qI zbt9WpSMp`G-A9K;<&q6bkb9Iv)+>wLtxR&4GRU2ZkvrsevQBO#mE1x~xtXk$o5=05 zhTJBr$*r=A+#+8jH_KJzOL7IdNiHWh%1UyBT;@$zBbSitr58lC43q1m7sOiW1yLov zAlArY@qM0Hon#gx~y_v7AcYc;L+#j0d4~?XET53wr zpBf0I2K)j42!Dv)PgDYt+Tw=C8Zxs&>8Zia8va)aMKb5gCmJ%+f}O6AnMIXA7%7k=-TR9&ZSRLf-Hn-b1EW2}Dv$8-{)V)-ppG!K}_N$*V*@Ev7*Pb=u%n0+GUb-^(qKm690@e@gtYp>?hbOa( zW+d6)3-1qPU3)#_vs$&T#ZR5-@}SFPU#t7MJ3y>+-nT!tLsl#OAa1pGx8^cz&DB>O z0&@z>rgN#xXt49}&K=$6#-8NqIPPQp1mKr<^~566J!eL=nn=8V8P?<&Nv6@zvm8I0 zV)W!jeSR56CmQ(>P1a2`3k+Ce+NI_wwv8rT&2ZaQ;|dr%k~ZV=-x*1|(JL$D4`nAwvw$}oWv&mj&hxn&BNP zJ|z=z?HjPy#09NzQny&8X1T1As^tuSe-d8d&|D>ZW7Prp+Kv{03Gte<0>ydQU_j#% z`79=0hEF*(#mgkz*#^y~uM7QD=-_Df6>w;te;csJFZ*D@U*SC9mFtjenao+HIm@V6 z;XqS@?2AKw1qaM%tpJnp9vbgKB_GEHH{h;l{|I>4V%Ie53cE(o!6^Q>m(X=fwx{u9ucB-1c?9B<_iNs$38Dd6XvXstzohWXWjtQ4>B;$yOq-{3QW zjl|+x{H%+-gO_pNC`Z%t9c8?}S-TwT^Bev&s%yMXApeMe*HswWO3k>_KcHmFF;M%27eg=_NYMuKS8qCOwI%PTim*leG)6J|Mcs9^TQX;TO7CVI45IrQg%6 zWc?nsex^hHV3ma*4ikd`n#)uO!*Swob~MiA+`dA)fCjbMus2(c#Do1sw$<(z<2f6J z6EegFpF76U*mOtbMu(Kgn%CH~Voz7ueX(Yo_>i;Fm_JEKmu2J4Lebr(=X|GBJO^~; z>ooYBt)rQjGT2qE#$tM%s5T%PuX6CKMdCzvHV&INigmQr%+s2AnnoTop=FjDk7ss? zV#n5vW15|B9HT-DZO{?w1uQ%w&I0Tkp(bGAMRC@mus|5J-+j7>hjBcH`#m~xyGHqSs1skchO+; zFu2LBw%9^EQ|k_K*#i7iqr1)ZEvC&v5zcQJrR|H|>}Mxnb<8c`Y!O~N>W(u03ob$E AIRF3v diff --git a/lib/views/widgets/StatefulWidget/InteractiveViewer/node1_base.dart b/lib/views/widgets/StatefulWidget/InteractiveViewer/node1_base.dart new file mode 100644 index 0000000..e34cccc --- /dev/null +++ b/lib/views/widgets/StatefulWidget/InteractiveViewer/node1_base.dart @@ -0,0 +1,57 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +/// create by 张风捷特烈 on 2020/7/22 +/// contact me by email 1981462002@qq.com +/// 说明: 351 InteractiveViewer 交互视图 主要对移动、缩放等手势交互进行封装,简化使用,可指定移动边界、缩放比例、手势监听等。 +// { +// "widgetId": 351, +// "name": "InteractiveViewer基本使用", +// "priority": 1, +// "subtitle": "【alignPanAxis】 : 沿轴拖动 【bool】\n" +// "【boundaryMargin】 : 边界边距 【EdgeInsets】\n" +// "【panEnabled】 : 是否可平移 【bool】\n" +// "【scaleEnabled】 : 是否可缩放 【bool】\n" +// "【maxScale】 : 最大放大倍数 【double】\n" +// "【minScale】 : 最小缩小倍数 【double】\n" +// "【onInteractionEnd】 : 交互结束回调 【GestureScaleEndCallback】\n" +// "【onInteractionStart】 : 交互开始回调 【GestureScaleStartCallback】\n" +// "【onInteractionUpdate】 : 交互更新回调 【GestureScaleUpdateCallback】\n" +// "【child】 : 游标颜色 【Widget】", +// } + +class InteractiveViewerDemo extends StatelessWidget { + + @override + Widget build(BuildContext context) { + return Container( + height: 150, + color: Colors.grey.withAlpha(33), + child: InteractiveViewer( + boundaryMargin: EdgeInsets.all(40.0), + maxScale: 2.5, + minScale: 0.3, + panEnabled: true, + scaleEnabled: true, + child: Container( + child: Image.asset('assets/images/caver.jpeg'), + ), + onInteractionStart: _onInteractionStart, + onInteractionUpdate: _onInteractionUpdate, + onInteractionEnd: _onInteractionEnd, + ), + ); + } + + void _onInteractionStart(ScaleStartDetails details) { + print('onInteractionStart----' + details.toString()); + } + + void _onInteractionUpdate(ScaleUpdateDetails details) { + print('onInteractionUpdate----' + details.toString()); + } + + void _onInteractionEnd(ScaleEndDetails details) { + print('onInteractionEnd----' + details.toString()); + } +} diff --git a/lib/views/widgets/StatefulWidget/InteractiveViewer/node2_constrained.dart b/lib/views/widgets/StatefulWidget/InteractiveViewer/node2_constrained.dart new file mode 100644 index 0000000..ecb1c76 --- /dev/null +++ b/lib/views/widgets/StatefulWidget/InteractiveViewer/node2_constrained.dart @@ -0,0 +1,59 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +/// create by 张风捷特烈 on 2020/7/22 +/// contact me by email 1981462002@qq.com +/// 说明: +// { +// "widgetId": 351, +// "name": "constrained属性测试", +// "priority": 2, +// "subtitle": "【constrained】 : 受约束的 【bool】", +// } + +class InteractiveViewerDemo2 extends StatelessWidget { + + Widget build(BuildContext context) { + const int _rowCount = 20; + const int _columnCount = 4; + + return Container( + width: 300, + height: 200, + child: InteractiveViewer( + constrained: false, + scaleEnabled: false, + child: Table( + columnWidths: { + for (int column = 0; column < _columnCount; column += 1) + column: const FixedColumnWidth(150.0), + }, + children: buildRows(_rowCount, _columnCount), + ), + ), + ); + } + + List buildRows(int rowCount, int columnCount) { + return [ + for (int row = 0; row < rowCount; row += 1) + TableRow( + children: [ + for (int column = 0; column < columnCount; column += 1) + Container( + margin: EdgeInsets.all(2), + height: 50, + alignment: Alignment.center, + color: _colorful(row,column), + child: Text('($row,$column)',style: TextStyle(fontSize: 20,color: Colors.white),), + ), + ], + ), + ]; + } + + final colors = [Colors.red,Colors.yellow,Colors.blue,Colors.green]; + final colors2 = [Colors.yellow,Colors.blue,Colors.green,Colors.red]; + + _colorful(int row, int column ) => row % 2==0?colors[column]:colors2[column]; +} diff --git a/lib/views/widgets/StatefulWidget/InteractiveViewer/node3_controller.dart b/lib/views/widgets/StatefulWidget/InteractiveViewer/node3_controller.dart new file mode 100644 index 0000000..c1a84ff --- /dev/null +++ b/lib/views/widgets/StatefulWidget/InteractiveViewer/node3_controller.dart @@ -0,0 +1,157 @@ +import 'dart:math'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +/// create by 张风捷特烈 on 2020/7/22 +/// contact me by email 1981462002@qq.com +/// 说明: +// { +// "widgetId": 351, +// "name": "变换控制器的使用", +// "priority": 3, +// "subtitle": "【transformationController】 : 变换控制器 【TransformationController】", +// } + +class InteractiveViewerDemo3 extends StatefulWidget { + @override + _InteractiveViewerDemo3State createState() => _InteractiveViewerDemo3State(); +} + +class _InteractiveViewerDemo3State extends State + with SingleTickerProviderStateMixin { + final TransformationController _transformationController = + TransformationController(); + Animation _animationReset; + AnimationController _controllerReset; + + void _onAnimateReset() { + _transformationController.value = _animationReset.value; + if (!_controllerReset.isAnimating) { + _animationReset?.removeListener(_onAnimateReset); + _animationReset = null; + _controllerReset.reset(); + } + } + + void _animateResetInitialize() { + _controllerReset.reset(); + _animationReset = Matrix4Tween( + begin: _transformationController.value, + end: Matrix4.identity(), + ).animate(_controllerReset); + _animationReset.addListener(_onAnimateReset); + _controllerReset.forward(); + } + + void _animateResetStop() { + _controllerReset.stop(); + _animationReset?.removeListener(_onAnimateReset); + _animationReset = null; + _controllerReset.reset(); + } + + void _onInteractionStart(ScaleStartDetails details) { + if (_controllerReset.status == AnimationStatus.forward) { + _animateResetStop(); + } + } + + @override + void initState() { + super.initState(); + _controllerReset = AnimationController( + vsync: this, + duration: const Duration(milliseconds: 400), + ); + } + + @override + void dispose() { + _controllerReset.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Wrap( + direction: Axis.vertical, + spacing: 10, + crossAxisAlignment: WrapCrossAlignment.center, + alignment: WrapAlignment.center, + children: [ + Container( + height: 150, + color: Colors.grey.withAlpha(33), + child: InteractiveViewer( + boundaryMargin: EdgeInsets.all(40), + transformationController: _transformationController, + minScale: 0.1, + maxScale: 1.8, + onInteractionStart: _onInteractionStart, + child: Container( + child: Image.asset('assets/images/caver.jpeg'), + ), + ), + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + _buildButton(), + _buildButton2(), + _buildButton3(), + ], + ) + ], + ); + } + + Widget _buildButton() { + return MaterialButton( + child: Icon( + Icons.refresh, + color: Colors.white, + ), + color: Colors.green, + shape: CircleBorder( + side: BorderSide(width: 2.0, color: Color(0xFFFFDFDFDF)), + ), + onPressed: _animateResetInitialize); + } + + var _x = 0.0; + + Widget _buildButton2() { + return MaterialButton( + child: Icon( + Icons.navigate_before, + color: Colors.white, + ), + color: Colors.green, + shape: CircleBorder( + side: BorderSide(width: 2.0, color: Color(0xFFFFDFDFDF)), + ), + onPressed: () { + var temp = _transformationController.value.clone(); + temp.translate(_x - 4); + _transformationController.value = temp; + }); + } + + Widget _buildButton3() { + return MaterialButton( + child: Icon( + Icons.navigate_next, + color: Colors.white, + ), + color: Colors.green, + shape: CircleBorder( + side: BorderSide(width: 2.0, color: Color(0xFFFFDFDFDF)), + ), + onPressed: () { + var temp = _transformationController.value.clone(); + temp.translate(_x + 4); + _transformationController.value = temp; + }); + } +} diff --git a/lib/views/widgets/exp/stateful_unit.dart b/lib/views/widgets/exp/stateful_unit.dart index 988235d..b0ae18e 100644 --- a/lib/views/widgets/exp/stateful_unit.dart +++ b/lib/views/widgets/exp/stateful_unit.dart @@ -31,6 +31,9 @@ export '../StatefulWidget/CupertinoSwitch/node1_base.dart'; export '../StatefulWidget/CupertinoSegmentedControl/node1_base.dart'; export '../StatefulWidget/CupertinoSegmentedControl/node2_color.dart'; export '../StatefulWidget/Navigator/node1_base.dart'; +export '../StatefulWidget/InteractiveViewer/node1_base.dart'; +export '../StatefulWidget/InteractiveViewer/node2_constrained.dart'; +export '../StatefulWidget/InteractiveViewer/node3_controller.dart'; export '../StatefulWidget/Image/node1_base.dart'; export '../StatefulWidget/Image/node2_fit.dart'; diff --git a/lib/views/widgets/widgets_map.dart b/lib/views/widgets/widgets_map.dart index cc98df7..9d849db 100644 --- a/lib/views/widgets/widgets_map.dart +++ b/lib/views/widgets/widgets_map.dart @@ -134,6 +134,12 @@ class WidgetsMap { return [ CustomFadeInImage(), ]; + case "InteractiveViewer": + return [ + InteractiveViewerDemo(), + InteractiveViewerDemo2(), + InteractiveViewerDemo3(), + ]; case "CircleAvatar": return [ CustomCircleAvatar(),