mirror of
https://github.com/flutter/flutter
synced 2024-10-13 19:52:53 +00:00
Make AnimatedCrossFade's alignment configurable (#9973)
The default is topCenter, which is sensible, but someone might want to use a bottomCenter alignment, for example.
This commit is contained in:
parent
7160ecfb07
commit
b9f4e5dac7
|
@ -297,7 +297,7 @@ class RenderStack extends RenderBox
|
|||
/// top left corners.
|
||||
RenderStack({
|
||||
List<RenderBox> children,
|
||||
FractionalOffset alignment: FractionalOffset.center,
|
||||
FractionalOffset alignment: FractionalOffset.topLeft,
|
||||
StackFit fit: StackFit.loose,
|
||||
Overflow overflow: Overflow.clip
|
||||
}) : _alignment = alignment,
|
||||
|
|
|
@ -51,6 +51,7 @@ class AnimatedCrossFade extends StatefulWidget {
|
|||
this.firstCurve: Curves.linear,
|
||||
this.secondCurve: Curves.linear,
|
||||
this.sizeCurve: Curves.linear,
|
||||
this.alignment: FractionalOffset.topCenter,
|
||||
@required this.crossFadeState,
|
||||
@required this.duration
|
||||
}) : assert(firstCurve != null),
|
||||
|
@ -77,14 +78,25 @@ class AnimatedCrossFade extends StatefulWidget {
|
|||
final Duration duration;
|
||||
|
||||
/// The fade curve of the first child.
|
||||
///
|
||||
/// Defaults to [Curves.linear].
|
||||
final Curve firstCurve;
|
||||
|
||||
/// The fade curve of the second child.
|
||||
///
|
||||
/// Defaults to [Curves.linear].
|
||||
final Curve secondCurve;
|
||||
|
||||
/// The curve of the animation between the two children's sizes.
|
||||
///
|
||||
/// Defaults to [Curves.linear].
|
||||
final Curve sizeCurve;
|
||||
|
||||
/// How the children should be aligned while the size is animating.
|
||||
///
|
||||
/// Defaults to [FractionalOffset.topCenter].
|
||||
final FractionalOffset alignment;
|
||||
|
||||
@override
|
||||
_AnimatedCrossFadeState createState() => new _AnimatedCrossFadeState();
|
||||
}
|
||||
|
@ -152,7 +164,7 @@ class _AnimatedCrossFadeState extends State<AnimatedCrossFade> with TickerProvid
|
|||
children = <Widget>[
|
||||
new FadeTransition(
|
||||
opacity: _secondAnimation,
|
||||
child: widget.secondChild
|
||||
child: widget.secondChild,
|
||||
),
|
||||
new Positioned(
|
||||
// TODO(dragostis): Add a way to crop from top right for
|
||||
|
@ -162,15 +174,15 @@ class _AnimatedCrossFadeState extends State<AnimatedCrossFade> with TickerProvid
|
|||
right: 0.0,
|
||||
child: new FadeTransition(
|
||||
opacity: _firstAnimation,
|
||||
child: widget.firstChild
|
||||
)
|
||||
)
|
||||
child: widget.firstChild,
|
||||
),
|
||||
),
|
||||
];
|
||||
} else {
|
||||
children = <Widget>[
|
||||
new FadeTransition(
|
||||
opacity: _firstAnimation,
|
||||
child: widget.firstChild
|
||||
child: widget.firstChild,
|
||||
),
|
||||
new Positioned(
|
||||
// TODO(dragostis): Add a way to crop from top right for
|
||||
|
@ -180,24 +192,24 @@ class _AnimatedCrossFadeState extends State<AnimatedCrossFade> with TickerProvid
|
|||
right: 0.0,
|
||||
child: new FadeTransition(
|
||||
opacity: _secondAnimation,
|
||||
child: widget.secondChild
|
||||
)
|
||||
)
|
||||
child: widget.secondChild,
|
||||
),
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
return new ClipRect(
|
||||
child: new AnimatedSize(
|
||||
key: new ValueKey<Key>(widget.key),
|
||||
alignment: FractionalOffset.topCenter,
|
||||
alignment: widget.alignment,
|
||||
duration: widget.duration,
|
||||
curve: widget.sizeCurve,
|
||||
vsync: this,
|
||||
child: new Stack(
|
||||
overflow: Overflow.visible,
|
||||
children: children
|
||||
)
|
||||
)
|
||||
children: children,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,4 +78,57 @@ void main() {
|
|||
expect(box.size.width, equals(200.0));
|
||||
expect(box.size.height, equals(200.0));
|
||||
});
|
||||
|
||||
testWidgets('AnimatedCrossFade alignment', (WidgetTester tester) async {
|
||||
final Key firstKey = new UniqueKey();
|
||||
final Key secondKey = new UniqueKey();
|
||||
|
||||
await tester.pumpWidget(
|
||||
new Center(
|
||||
child: new AnimatedCrossFade(
|
||||
alignment: FractionalOffset.bottomRight,
|
||||
firstChild: new SizedBox(
|
||||
key: firstKey,
|
||||
width: 100.0,
|
||||
height: 100.0
|
||||
),
|
||||
secondChild: new SizedBox(
|
||||
key: secondKey,
|
||||
width: 200.0,
|
||||
height: 200.0
|
||||
),
|
||||
duration: const Duration(milliseconds: 200),
|
||||
crossFadeState: CrossFadeState.showFirst
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
await tester.pumpWidget(
|
||||
new Center(
|
||||
child: new AnimatedCrossFade(
|
||||
alignment: FractionalOffset.bottomRight,
|
||||
firstChild: new SizedBox(
|
||||
key: firstKey,
|
||||
width: 100.0,
|
||||
height: 100.0
|
||||
),
|
||||
secondChild: new SizedBox(
|
||||
key: secondKey,
|
||||
width: 200.0,
|
||||
height: 200.0
|
||||
),
|
||||
duration: const Duration(milliseconds: 200),
|
||||
crossFadeState: CrossFadeState.showSecond
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
await tester.pump(const Duration(milliseconds: 100));
|
||||
|
||||
final RenderBox box1 = tester.renderObject(find.byKey(firstKey));
|
||||
final RenderBox box2 = tester.renderObject(find.byKey(secondKey));
|
||||
expect(box1.localToGlobal(Offset.zero), const Offset(275.0, 175.0));
|
||||
expect(box2.localToGlobal(Offset.zero), const Offset(275.0, 175.0));
|
||||
});
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue