来自Flutter issue发布的Yueh Chou:
不确定事件是否会冒泡到父窗口小部件并触发 包含所有嵌套小部件和回调的动画。
在原始文件中
按下BackWidget的孙子小部件(例如FlatButton) 将触发ModalDialog调用并按下按钮将进行调用 异步调用。翻转效果将在成功结束时发生 异步呼叫。
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
void main() {
runApp(new MaterialApp(
home: new Container(color: Colors.white, child: new RootWidget())));
}
class RootWidget extends StatelessWidget {
FlipWidget mainFlipWidget;
@override
Widget build(BuildContext context) {
mainFlipWidget = new FlipWidget(
frontWidget: frontWidget,
backWidget: new BackWidget(
onPressedButton: () {
_flipMainButton();
},
),
);
return new Center(child:mainFlipWidget);
}
_flipMainButton() {
mainFlipWidget.doTheFlip();
}
}
class BackWidget extends StatefulWidget {
BackWidget({
this.onPressedButton,
});
final VoidCallback onPressedButton;
Widget buttonFlipWidget;
_BackWidgetState createState() => new _BackWidgetState();
}
class _BackWidgetState extends State<BackWidget> {
@override
Widget build(BuildContext context) {
widget.buttonFlipWidget = new Container(
height: 180.0,
color: Colors.grey[200],
child:new FlatButton(
onPressed: () {
triggerCb();
},
child: new Text('Press me'),
),
);
return widget.buttonFlipWidget;
}
triggerCb() {
widget.onPressedButton();
}
}
class FlipWidget extends StatefulWidget {
FlipWidget({
@required this.frontWidget,
@required this.backWidget,
});
final Widget frontWidget;
final Widget backWidget;
final _FlipWidgetState _state = new _FlipWidgetState();
doTheFlip () {
_state.doTheFlip();
}
_FlipWidgetState createState() => _state;
}
class _FlipWidgetState extends State<FlipWidget> with TickerProviderStateMixin {
AnimationController _controller;
Animation<double> _frontScale;
Animation<double> _backScale;
void initState() {
super.initState();
_controller = new AnimationController(vsync: this, duration: const Duration(milliseconds: 1500),);
_frontScale = new Tween(
begin: 1.0,
end: 0.0,
).animate(new CurvedAnimation(parent: _controller, curve: new Interval(0.0, 0.5, curve: Curves.easeIn),
));
_backScale = new CurvedAnimation(
parent: _controller,
curve: new Interval(0.5, 1.0, curve: Curves.easeOut),
);
}
@override
Widget build(BuildContext context) {
// ThemeData theme = Theme.of(context);
return new Scaffold(
body: new Center(
child: new Stack(
children: [
new AnimatedBuilder(
child: widget.frontWidget,
animation: _backScale,
builder: (BuildContext context, Widget child) {
final Matrix4 transform = new Matrix4.identity()
..scale(_backScale.value, 1.0, 1.0);
return new Transform(
transform: transform,
alignment: FractionalOffset.center,
child: child,
);
},
),
new AnimatedBuilder(
child: widget.backWidget,
animation: _frontScale,
builder: (BuildContext context, Widget child) {
final Matrix4 transform = new Matrix4.identity()
..scale(_frontScale.value, 1.0, 1.0);
return new Transform(
transform: transform,
alignment: FractionalOffset.center,
child: child,
);
}
),
],
),
),
);
}
doTheFlip() {
setState(() {
if (_controller.isCompleted || _controller.velocity > 0)
_controller.reverse();
else
_controller.forward();
});
}
}
final Widget frontWidget = new Container(
color: Colors.white,
height: 180.0,
child: new Column(
children: [
new Text("Front Side of the card")
],
),
);
答案 0 :(得分:8)
您应对此代码进行一些更改。
RootWidget
应该是有状态的。将flipped
州存储在那里。BackWidget
应该是无国籍的。它所要做的就是通知RootWidget
按下按钮。FlipWidget
应使用flipped
检测didUpdateWidget
的更改。State
存储到Widget
的成员变量中,如果可以避免,请避免在您的State
上添加mutator方法...这通常是表示您需要在窗口小部件树中将状态存储得更高,并使用构造函数参数将其传递下来。详细了解Widget Framework Tour和interactivity tutorial中的StatefulWidget
和StatelessWidget
。
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
void main() {
runApp(new MaterialApp(
home: new Container(
color: Colors.white,
child: new RootWidget(),
),
));
}
class RootWidget extends StatefulWidget {
@override
_RootWidgetState createState() => new _RootWidgetState();
}
class _RootWidgetState extends State<RootWidget> {
bool _flipped = false;
@override
Widget build(BuildContext context) {
return new Center(
child: new FlipWidget(
flipped: _flipped,
frontWidget: new Container(
color: Colors.white,
height: 180.0,
child: new Column(
children: [
new Text("Front Side of the card")
],
),
),
backWidget: new BackWidget(
onPressedButton: () {
setState(() {
_flipped = !_flipped;
});
},
),
),
);
}
}
class BackWidget extends StatelessWidget {
BackWidget({
this.onPressedButton,
});
final VoidCallback onPressedButton;
@override
Widget build(BuildContext context) {
return new Container(
height: 180.0,
color: Colors.grey[200],
child:new FlatButton(
onPressed: onPressedButton,
child: new Text('Press me'),
),
);
}
}
class FlipWidget extends StatefulWidget {
FlipWidget({
@required this.frontWidget,
@required this.backWidget,
@required this.flipped,
});
final Widget frontWidget;
final Widget backWidget;
final bool flipped;
@override
_FlipWidgetState createState() => new _FlipWidgetState();
}
class _FlipWidgetState extends State<FlipWidget> with TickerProviderStateMixin {
AnimationController _controller;
Animation<double> _frontScale;
Animation<double> _backScale;
@override
void initState() {
super.initState();
_controller = new AnimationController(
vsync: this,
duration: const Duration(milliseconds: 1500)
)..value = widget.flipped ? 1.0 : 0.0;
_frontScale = new Tween(
begin: 1.0,
end: 0.0,
).animate(new CurvedAnimation(parent: _controller, curve: new Interval(0.0, 0.5, curve: Curves.easeIn),
));
_backScale = new CurvedAnimation(
parent: _controller,
curve: new Interval(0.5, 1.0, curve: Curves.easeOut),
);
}
@override
void didUpdateWidget(FlipWidget oldWidget) {
if (widget.flipped != oldWidget.flipped) {
if (widget.flipped) {
_controller.forward();
} else {
_controller.reverse();
}
}
super.didUpdateWidget(oldWidget);
}
@override
Widget build(BuildContext context) {
return new Scaffold(
body: new Center(
child: new Stack(
children: [
new AnimatedBuilder(
child: widget.frontWidget,
animation: _backScale,
builder: (BuildContext context, Widget child) {
final Matrix4 transform = new Matrix4.identity()
..scale(_backScale.value, 1.0, 1.0);
return new Transform(
transform: transform,
alignment: FractionalOffset.center,
child: child,
);
},
),
new AnimatedBuilder(
child: widget.backWidget,
animation: _frontScale,
builder: (BuildContext context, Widget child) {
final Matrix4 transform = new Matrix4.identity()
..scale(_frontScale.value, 1.0, 1.0);
return new Transform(
transform: transform,
alignment: FractionalOffset.center,
child: child,
);
}
),
],
),
),
);
}
}