From 16c98eccf21caa5931a9ee222efffa70e72b63b3 Mon Sep 17 00:00:00 2001 From: ouxiang <ouxiang@igengmei.com> Date: Thu, 21 Feb 2019 20:10:26 +0800 Subject: [PATCH] add layout & animate test --- lib/animationTest.dart | 912 +++++++++++++++++++++++++++++++++++++++++ lib/layoutTest.dart | 112 +++++ lib/main.dart | 26 +- 3 files changed, 1048 insertions(+), 2 deletions(-) create mode 100644 lib/animationTest.dart create mode 100644 lib/layoutTest.dart diff --git a/lib/animationTest.dart b/lib/animationTest.dart new file mode 100644 index 0000000..92178df --- /dev/null +++ b/lib/animationTest.dart @@ -0,0 +1,912 @@ +import 'dart:async'; +import 'dart:core'; +import 'dart:math' as math; + +import 'package:flutter/material.dart'; + +class AnimationPage extends StatefulWidget { + @override + State<StatefulWidget> createState() { + return new _AnimationPageState(); + } +} + +class _AnimationPageState extends State<AnimationPage> + with TickerProviderStateMixin { + int _aniIndex = 0; + + Widget _buildAnimation() { + Widget widget; + + switch (_aniIndex) { + case 0: + widget = new OpacityAniWidget(); + break; + case 1: + widget = new MovementAniWidget(); + break; + case 2: + widget = new RadiusAniWidget(); + break; + case 3: + widget = new ColorAniWidget(); + break; + case 4: + widget = new RotateAniWidget(); + break; + case 5: + widget = new DeformAniWidget(); + break; + case 6: + widget = new StaggeredAniWidget(); + break; + } + + return widget; + } + + @override + Widget build(BuildContext context) { + return new Scaffold( + appBar: new AppBar( + title: new Text("Animation"), + centerTitle: true, + ), + body: new Column( + children: <Widget>[ + new Row( + children: <Widget>[ + new Padding( + padding: + const EdgeInsets.only(left: 10.0, top: 10.0, right: 10.0), + child: new RaisedButton( + textColor: Colors.black, + child: new Text('opacity'), + onPressed: () { + setState(() { + _aniIndex = 0; + }); + }), + ), + new Padding( + padding: + const EdgeInsets.only(left: 10.0, top: 10.0, right: 10.0), + child: new RaisedButton( + textColor: Colors.black, + child: new Text('movement'), + onPressed: () { + setState(() { + _aniIndex = 1; + }); + }), + ), + new Padding( + padding: + const EdgeInsets.only(left: 10.0, top: 10.0, right: 10.0), + child: new RaisedButton( + textColor: Colors.black, + child: new Text('radius'), + onPressed: () { + setState(() { + _aniIndex = 2; + }); + }), + ), + ], + ), + new Row( + children: <Widget>[ + new Padding( + padding: + const EdgeInsets.only(left: 10.0, top: 10.0, right: 10.0), + child: new RaisedButton( + textColor: Colors.black, + child: new Text('color'), + onPressed: () { + setState(() { + _aniIndex = 3; + }); + }), + ), + new Padding( + padding: + const EdgeInsets.only(left: 10.0, top: 10.0, right: 10.0), + child: new RaisedButton( + textColor: Colors.black, + child: new Text('rotate'), + onPressed: () { + setState(() { + _aniIndex = 4; + }); + }), + ), + new Padding( + padding: + const EdgeInsets.only(left: 10.0, top: 10.0, right: 10.0), + child: new RaisedButton( + textColor: Colors.black, + child: new Text('deform'), + onPressed: () { + setState(() { + _aniIndex = 5; + }); + }), + ), + ], + ), + new Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: <Widget>[ + new Padding( + padding: + const EdgeInsets.only(left: 10.0, top: 10.0, right: 10.0), + child: new RaisedButton( + textColor: Colors.black, + child: new Text('Staggered'), + onPressed: () { + setState(() { + _aniIndex = 6; + }); + }), + ), + ], + ), + new Padding( + padding: const EdgeInsets.only(left: 10.0, top: 10.0, right: 10.0), + child: _buildAnimation(), + ), + ], + ), + ); + } +} + +class OpacityAniWidget extends StatefulWidget { + @override + State<StatefulWidget> createState() { + return new _OpacityAniWidgetState(); + } +} + +class _OpacityAniWidgetState extends State<OpacityAniWidget> + with TickerProviderStateMixin { + AnimationController _controller; + + Animation<double> opacity; + + void _initController() { + _controller = AnimationController( + duration: Duration(milliseconds: 2000), + vsync: this, + ); + } + + void _initAni() { + opacity = Tween<double>( + begin: 0.0, + end: 1.0, + ).animate( + CurvedAnimation( + parent: _controller, + curve: Interval( + 0.0, + 0.5, + curve: Curves.easeIn, + ), + ), + ) + ..addListener(() { + setState(() {}); + }) + ..addStatusListener((AnimationStatus status) { + print(status); + }); + } + + Future _startAnimation() async { + try { + await _controller.repeat(); +// +// await _controller +// .forward() +// .orCancel; +// await _controller +// .reverse() +// .orCancel; + } on TickerCanceled { + print('Animation Failed'); + } + } + + @override + void initState() { + super.initState(); + _initController(); + _initAni(); + _startAnimation(); + } + + @override + void dispose() { + _controller?.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return new Opacity( + opacity: opacity.value, + child: new Container( + color: Colors.red, + height: 200.0, + width: 200.0, + child: new Center( + child: new Text( + 'opacity', + style: new TextStyle(color: Colors.white, fontSize: 16.0), + ), + ), + ), + ); + } +} + +class MovementAniWidget extends StatefulWidget { + @override + State<StatefulWidget> createState() { + return new _MovementAniWidgetState(); + } +} + +class _MovementAniWidgetState extends State<MovementAniWidget> + with TickerProviderStateMixin { + AnimationController _controller; + + Animation<EdgeInsets> movement; + + void _initController() { + _controller = AnimationController( + duration: Duration(milliseconds: 5000), + vsync: this, + ); + } + + void _initAni() { + movement = EdgeInsetsTween( + begin: EdgeInsets.only(top: 0.0, right: 0.0), + end: EdgeInsets.only(top: 50.0, right: 100.0), + ).animate( + CurvedAnimation( + parent: _controller, + curve: Interval( + 0.1, + 0.5, + curve: Curves.fastOutSlowIn, + ), + ), + ) + ..addListener(() { + setState(() {}); + }) + ..addStatusListener((AnimationStatus status) { + print(status); + }); + } + + Future _startAnimation() async { + try { + await _controller.repeat(); +// await _controller +// .forward() +// .orCancel; +// await _controller +// .reverse() +// .orCancel; + } on TickerCanceled { + print('Animation Failed'); + } + } + + @override + void initState() { + super.initState(); + _initController(); + _initAni(); + _startAnimation(); + } + + @override + void dispose() { + _controller?.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return new Container( + color: Colors.blue, + height: 200.0, + width: 200.0, + padding: movement.value, + child: new Center( + child: new Text( + 'movement', + style: new TextStyle(color: Colors.white, fontSize: 16.0), + ), + ), + ); + } +} + +class RadiusAniWidget extends StatefulWidget { + @override + State<StatefulWidget> createState() { + return new _RadiusAniWidgetState(); + } +} + +class _RadiusAniWidgetState extends State<RadiusAniWidget> + with TickerProviderStateMixin { + AnimationController _controller; + + Animation<BorderRadius> radius; + + void _initController() { + _controller = AnimationController( + duration: Duration(milliseconds: 2000), + vsync: this, + ); + } + + void _initAni() { + radius = radius = BorderRadiusTween( + begin: BorderRadius.circular(0.0), + end: BorderRadius.circular(100.0), + ).animate( + CurvedAnimation( + parent: _controller, + curve: Interval( + 0.5, + 0.8, + curve: Curves.ease, + ), + ), + ) + ..addListener(() { + setState(() {}); + }) + ..addStatusListener((AnimationStatus status) { + print(status); + }); + } + + Future _startAnimation() async { + try { + await _controller.repeat(); +// await _controller +// .forward() +// .orCancel; +// await _controller +// .reverse() +// .orCancel; + } on TickerCanceled { + print('Animation Failed'); + } + } + + @override + void initState() { + super.initState(); + _initController(); + _initAni(); + _startAnimation(); + } + + @override + void dispose() { + _controller?.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return new Container( + height: 200.0, + width: 200.0, + child: new Center( + child: new Text( + 'radius', + style: new TextStyle(color: Colors.white, fontSize: 16.0), + ), + ), + decoration: BoxDecoration( + color: Colors.purple, + border: Border.all( + color: Colors.purple, + width: 2.0, + ), + borderRadius: radius.value, + ), + ); + } +} + +class ColorAniWidget extends StatefulWidget { + @override + State<StatefulWidget> createState() { + return new _ColorAniWidgetState(); + } +} + +class _ColorAniWidgetState extends State<ColorAniWidget> + with TickerProviderStateMixin { + AnimationController _controller; + + Animation<Color> color; + + void _initController() { + _controller = AnimationController( + duration: Duration(milliseconds: 2000), + vsync: this, + ); + } + + void _initAni() { + color = ColorTween( + begin: Colors.red[100], + end: Colors.blue[900], + ).animate( + CurvedAnimation( + parent: _controller, + curve: Interval( + 0.0, + 1.0, + curve: Curves.linear, + ), + ), + ) + ..addListener(() { + setState(() {}); + }) + ..addStatusListener((AnimationStatus status) { + print(status); + }); + } + + Future _startAnimation() async { + try { + await _controller.repeat(); +// await _controller +// .forward() +// .orCancel; +// await _controller +// .reverse() +// .orCancel; + } on TickerCanceled { + print('Animation Failed'); + } + } + + @override + void initState() { + super.initState(); + _initController(); + _initAni(); + _startAnimation(); + } + + @override + void dispose() { + _controller?.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return new Container( + color: color.value, + height: 200.0, + width: 200.0, + child: new Center( + child: new Text( + 'color', + style: new TextStyle(color: Colors.white, fontSize: 16.0), + ), + ), + ); + } +} + +class RotateAniWidget extends StatefulWidget { + @override + State<StatefulWidget> createState() { + return new _RotateAniWidgetState(); + } +} + +class _RotateAniWidgetState extends State<RotateAniWidget> + with TickerProviderStateMixin { + AnimationController _controller; + + Animation<double> rotate; + + void _initController() { + _controller = AnimationController( + duration: Duration(milliseconds: 2000), + vsync: this, + ); + } + + void _initAni() { + rotate = Tween<double>( + begin: 0.0, + end: math.pi * 2, + ).animate( + CurvedAnimation( + parent: _controller, + curve: Interval( + 0.1, + 0.3, + curve: Curves.ease, + ), + ), + ) + ..addListener(() { + setState(() {}); + }) + ..addStatusListener((AnimationStatus status) { + print(status); + }); + } + + Future _startAnimation() async { + try { + await _controller.repeat(); +// await _controller +// .forward() +// .orCancel; +// await _controller +// .reverse() +// .orCancel; + } on TickerCanceled { + print('Animation Failed'); + } + } + + @override + void initState() { + super.initState(); + _initController(); + _initAni(); + _startAnimation(); + } + + @override + void dispose() { + _controller?.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return new Container( + height: 200.0, + width: 200.0, + color: Colors.green, + transform: Matrix4.identity()..rotateZ(rotate.value), + child: new Center( + child: new Text( + 'rotate', + style: new TextStyle(color: Colors.white, fontSize: 16.0), + ), + ), + ); + } +} + +class DeformAniWidget extends StatefulWidget { + @override + State<StatefulWidget> createState() { + return new _DeformAniWidgetState(); + } +} + +class _DeformAniWidgetState extends State<DeformAniWidget> + with TickerProviderStateMixin { + AnimationController _controller; + + Animation<double> width; + + Animation<double> height; + + void _initController() { + _controller = AnimationController( + duration: Duration(milliseconds: 2000), + vsync: this, + ); + } + + void _initAni() { + height = Tween<double>( + begin: 100.0, + end: 200.0, + ).animate( + CurvedAnimation( + parent: _controller, + curve: Interval( + 0.3, + 0.6, + curve: Curves.fastOutSlowIn, + ), + ), + ) + ..addListener(() { + setState(() {}); + }) + ..addStatusListener((AnimationStatus status) { + print(status); + }); + + width = Tween<double>( + begin: 100.0, + end: 200.0, + ).animate( + CurvedAnimation( + parent: _controller, + curve: Interval( + 0.4, + 0.6, + curve: Curves.fastOutSlowIn, + ), + ), + ) + ..addListener(() { + setState(() {}); + }) + ..addStatusListener((AnimationStatus status) { + print(status); + }); + } + + Future _startAnimation() async { + try { + await _controller.repeat(); +// await _controller +// .forward() +// .orCancel; +// await _controller +// .reverse() +// .orCancel; + } on TickerCanceled { + print('Animation Failed'); + } + } + + @override + void initState() { + super.initState(); + _initController(); + _initAni(); + _startAnimation(); + } + + @override + void dispose() { + _controller?.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return new Container( + width: width.value, + height: height.value, + color: Colors.deepPurple, + child: new Center( + child: new Text( + 'deform', + style: new TextStyle(color: Colors.white, fontSize: 16.0), + ), + ), + ); + } +} + +class StaggeredAniWidget extends StatefulWidget { + @override + State<StatefulWidget> createState() { + return new _StaggeredAniWidgetState(); + } +} + +class _StaggeredAniWidgetState extends State<StaggeredAniWidget> + with TickerProviderStateMixin { + AnimationController _controller; + Animation<double> opacity; + Animation<EdgeInsets> movement; + Animation<Color> color; + Animation<BorderRadius> radius; + Animation<double> rotate; + Animation<double> width; + Animation<double> height; + + void _initController() { + _controller = AnimationController( + duration: Duration(milliseconds: 2000), + vsync: this, + ); + } + + void _initAni() { + opacity = Tween<double>( + begin: 0.0, + end: 1.0, + ).animate( + CurvedAnimation( + parent: _controller, + curve: Interval( + 0.0, + 0.1, + curve: Curves.easeIn, + ), + ), + ); + + rotate = Tween<double>( + begin: 0.0, + end: math.pi * 2, + ).animate( + CurvedAnimation( + parent: _controller, + curve: Interval( + 0.0, + 0.2, + curve: Curves.ease, + ), + ), + ); + + movement = EdgeInsetsTween( + begin: EdgeInsets.only(top: 0.0), + end: EdgeInsets.only(top: 100.0), + ).animate( + CurvedAnimation( + parent: _controller, + curve: Interval( + 0.2, + 0.375, + curve: Curves.fastOutSlowIn, + ), + ), + ); + + color = ColorTween( + begin: Colors.blue[300], + end: Colors.blue[900], + ).animate( + CurvedAnimation( + parent: _controller, + curve: Interval( + 0.5, + 0.75, + curve: Curves.linear, + ), + ), + ); + + radius = BorderRadiusTween( + begin: BorderRadius.circular(0.0), + end: BorderRadius.circular(100.0), + ).animate( + CurvedAnimation( + parent: _controller, + curve: Interval( + 0.5, + 0.75, + curve: Curves.ease, + ), + ), + ); + + height = Tween<double>( + begin: 100.0, + end: 200.0, + ).animate( + CurvedAnimation( + parent: _controller, + curve: Interval( + 0.375, + 0.6, + curve: Curves.fastOutSlowIn, + ), + ), + ); + + width = Tween<double>( + begin: 100.0, + end: 200.0, + ).animate( + CurvedAnimation( + parent: _controller, + curve: Interval( + 0.375, + 0.6, + curve: Curves.fastOutSlowIn, + ), + ), + ); + } + + Future _startAnimation() async { + try { +// await _controller.repeat(); + await _controller.forward().orCancel; + await _controller.reverse().orCancel; + } on TickerCanceled { + print('Animation Failed'); + } + } + + @override + void initState() { + super.initState(); + _initController(); + _initAni(); + _startAnimation(); + } + + @override + void dispose() { + _controller?.dispose(); + super.dispose(); + } + + Widget _buildAni(BuildContext context, Widget child) { + return new Container( + padding: movement.value, + transform: Matrix4.identity()..rotateZ(rotate.value), + child: new Opacity( + opacity: opacity.value, + child: new Container( + width: width.value, + height: height.value, + decoration: new BoxDecoration( + color: color.value, + border: new Border.all( + color: Colors.black, + width: 3.0, + ), + borderRadius: radius.value, + ), + child: new Center( + child: new Text( + 'staggered', + style: new TextStyle(color: Colors.white, fontSize: 16.0), + ), + ), + ), + ), + ); + } + + @override + Widget build(BuildContext context) { + return new Column( + mainAxisAlignment: MainAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: <Widget>[ + new Padding( + padding: + const EdgeInsets.only(left: 10.0, top: 10.0, right: 10.0), + child: new FlatButton( + textColor: Colors.black, + child: new Text('replay staggered'), + onPressed: () { + _startAnimation(); + }), + ), + new AnimatedBuilder(animation: _controller, builder: _buildAni) + ], + ); + } +} diff --git a/lib/layoutTest.dart b/lib/layoutTest.dart new file mode 100644 index 0000000..4c658c9 --- /dev/null +++ b/lib/layoutTest.dart @@ -0,0 +1,112 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; + +class LayoutTest extends StatefulWidget { + @override + _LayoutTestState createState() => _LayoutTestState(); +} + +class _LayoutTestState extends State<LayoutTest> { + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text('Layout Test'), + ), + body: Container( + padding: EdgeInsets.all(32.0), + child: Center( + child: Column( + children: <Widget>[ + _renderBoxTest(), + _containerTestWidget() + ], + ), + ), + ), + ); + } + +Widget _renderBoxTest(){ + return Container( + color: Colors.greenAccent, + constraints: BoxConstraints( + maxWidth: double.infinity, + minWidth: 200.0, + maxHeight: 200, + minHeight: 100.0), + child: Stingy( + child: Container( + color: Colors.pink[200], + ), + ), + ); +} + +// www.baidu.com/img/bd_logo1.png + Widget _containerTestWidget(){ + return Container( + constraints: BoxConstraints.expand( + height: Theme.of(context).textTheme.display1.fontSize * 1.1 + 200.0, + ), + padding: const EdgeInsets.all(8.0), + color: Colors.greenAccent.shade700, + alignment: Alignment.bottomCenter, + child: Text('Hello World', style: Theme.of(context).textTheme.display1.copyWith(color: Colors.orange[200])), + foregroundDecoration: BoxDecoration( + image: DecorationImage( + image: NetworkImage('https://www.example.com/images/frame.png'), + centerSlice: Rect.fromLTRB(270.0, 180.0, 1360.0, 730.0), + ), + ), + transform: Matrix4.rotationZ(0.1), + ); + } +} + + +class Stingy extends SingleChildRenderObjectWidget { + Stingy({Widget child}) : super(child: child); + + @override + RenderObject createRenderObject(BuildContext context) { + // TODO: implement createRenderObject + return RenderStingy(); + } +} + +class RenderStingy extends RenderShiftedBox { + RenderStingy() : super(null); + + // 绘制方法 + @override + void paint(PaintingContext context, Offset offset) { + // TODO: implement paint + super.paint(context, offset); + } + + // 布局方法 + @override + void performLayout() { + // 布局 child 确定 child çš„ size + child.layout( + BoxConstraints( + minHeight: 0.0, + maxHeight: constraints.minHeight, + minWidth: 0.0, + maxWidth: constraints.minWidth), + parentUsesSize: true); + + print('constraints: $constraints'); + + // child çš„ Offset + final BoxParentData childParentData = child.parentData; + childParentData.offset = Offset(constraints.maxWidth - child.size.width, + constraints.maxHeight - child.size.height); + print('childParentData: $childParentData'); + + // 确定自己(父节点)的大å°ï¼Œå¹¶é‡ç»˜çˆ¶èŠ‚点。ä¸é‡è®¾ï¼Œä¸èƒ½è§¦å‘é‡ç»˜ï¼Œä¾‹å¦‚在çƒé‡è½½çš„情景ä¸ï¼Œé‡è®¾container.maxHeightï¼Œæ— æ•ˆ + size = Size(constraints.maxWidth, constraints.maxHeight); + print('size: $size'); + } +} diff --git a/lib/main.dart b/lib/main.dart index 1581ab3..a919930 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,6 +1,8 @@ import 'package:flutter/material.dart'; import 'battery.dart'; import 'assetsChannel.dart'; +import 'layoutTest.dart'; +import 'animationTest.dart'; void main() => runApp(MyApp()); @@ -16,6 +18,8 @@ class MyApp extends StatelessWidget { routes: { "/channeltest": batteryChannelPage, "/assetschannel": assetsChannelPage, + "/layouttest": layoutTestPage, + "/animationtest": animationTestPage, }, ); } @@ -27,6 +31,14 @@ class MyApp extends StatelessWidget { Widget assetsChannelPage(BuildContext context) { return AssestPlatformChannel(); } + + Widget layoutTestPage(BuildContext context) { + return LayoutTest(); + } + + Widget animationTestPage(BuildContext context) { + return AnimationPage(); + } } class MyHomePage extends StatefulWidget { @@ -66,14 +78,24 @@ class _MyHomePageState extends State<MyHomePage> { ), FlatButton( child: Text('channel test'), - color: Colors.green, + color: Colors.greenAccent, onPressed: (){Navigator.pushNamed(context, "/channeltest");}, ), FlatButton( child: Text('assets test'), - color: Colors.green, + color: Colors.greenAccent, onPressed: (){Navigator.pushNamed(context, "/assetschannel");}, ), + FlatButton( + child: Text('layout test'), + color: Colors.greenAccent, + onPressed: (){Navigator.pushNamed(context, "/layouttest");}, + ), + FlatButton( + child: Text('animation test'), + color: Colors.greenAccent, + onPressed: (){Navigator.pushNamed(context, "/animationtest");}, + ), ], ), ), -- 2.18.0