Skip to content

Commit b9f4e5d

Browse files
authored
Make AnimatedCrossFade's alignment configurable (flutter#9973)
The default is topCenter, which is sensible, but someone might want to use a bottomCenter alignment, for example.
1 parent 7160ecf commit b9f4e5d

File tree

3 files changed

+78
-13
lines changed

3 files changed

+78
-13
lines changed

packages/flutter/lib/src/rendering/stack.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ class RenderStack extends RenderBox
297297
/// top left corners.
298298
RenderStack({
299299
List<RenderBox> children,
300-
FractionalOffset alignment: FractionalOffset.center,
300+
FractionalOffset alignment: FractionalOffset.topLeft,
301301
StackFit fit: StackFit.loose,
302302
Overflow overflow: Overflow.clip
303303
}) : _alignment = alignment,

packages/flutter/lib/src/widgets/animated_cross_fade.dart

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ class AnimatedCrossFade extends StatefulWidget {
5151
this.firstCurve: Curves.linear,
5252
this.secondCurve: Curves.linear,
5353
this.sizeCurve: Curves.linear,
54+
this.alignment: FractionalOffset.topCenter,
5455
@required this.crossFadeState,
5556
@required this.duration
5657
}) : assert(firstCurve != null),
@@ -77,14 +78,25 @@ class AnimatedCrossFade extends StatefulWidget {
7778
final Duration duration;
7879

7980
/// The fade curve of the first child.
81+
///
82+
/// Defaults to [Curves.linear].
8083
final Curve firstCurve;
8184

8285
/// The fade curve of the second child.
86+
///
87+
/// Defaults to [Curves.linear].
8388
final Curve secondCurve;
8489

8590
/// The curve of the animation between the two children's sizes.
91+
///
92+
/// Defaults to [Curves.linear].
8693
final Curve sizeCurve;
8794

95+
/// How the children should be aligned while the size is animating.
96+
///
97+
/// Defaults to [FractionalOffset.topCenter].
98+
final FractionalOffset alignment;
99+
88100
@override
89101
_AnimatedCrossFadeState createState() => new _AnimatedCrossFadeState();
90102
}
@@ -152,7 +164,7 @@ class _AnimatedCrossFadeState extends State<AnimatedCrossFade> with TickerProvid
152164
children = <Widget>[
153165
new FadeTransition(
154166
opacity: _secondAnimation,
155-
child: widget.secondChild
167+
child: widget.secondChild,
156168
),
157169
new Positioned(
158170
// TODO(dragostis): Add a way to crop from top right for
@@ -162,15 +174,15 @@ class _AnimatedCrossFadeState extends State<AnimatedCrossFade> with TickerProvid
162174
right: 0.0,
163175
child: new FadeTransition(
164176
opacity: _firstAnimation,
165-
child: widget.firstChild
166-
)
167-
)
177+
child: widget.firstChild,
178+
),
179+
),
168180
];
169181
} else {
170182
children = <Widget>[
171183
new FadeTransition(
172184
opacity: _firstAnimation,
173-
child: widget.firstChild
185+
child: widget.firstChild,
174186
),
175187
new Positioned(
176188
// TODO(dragostis): Add a way to crop from top right for
@@ -180,24 +192,24 @@ class _AnimatedCrossFadeState extends State<AnimatedCrossFade> with TickerProvid
180192
right: 0.0,
181193
child: new FadeTransition(
182194
opacity: _secondAnimation,
183-
child: widget.secondChild
184-
)
185-
)
195+
child: widget.secondChild,
196+
),
197+
),
186198
];
187199
}
188200

189201
return new ClipRect(
190202
child: new AnimatedSize(
191203
key: new ValueKey<Key>(widget.key),
192-
alignment: FractionalOffset.topCenter,
204+
alignment: widget.alignment,
193205
duration: widget.duration,
194206
curve: widget.sizeCurve,
195207
vsync: this,
196208
child: new Stack(
197209
overflow: Overflow.visible,
198-
children: children
199-
)
200-
)
210+
children: children,
211+
),
212+
),
201213
);
202214
}
203215
}

packages/flutter/test/widgets/animated_cross_fade_test.dart

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,4 +78,57 @@ void main() {
7878
expect(box.size.width, equals(200.0));
7979
expect(box.size.height, equals(200.0));
8080
});
81+
82+
testWidgets('AnimatedCrossFade alignment', (WidgetTester tester) async {
83+
final Key firstKey = new UniqueKey();
84+
final Key secondKey = new UniqueKey();
85+
86+
await tester.pumpWidget(
87+
new Center(
88+
child: new AnimatedCrossFade(
89+
alignment: FractionalOffset.bottomRight,
90+
firstChild: new SizedBox(
91+
key: firstKey,
92+
width: 100.0,
93+
height: 100.0
94+
),
95+
secondChild: new SizedBox(
96+
key: secondKey,
97+
width: 200.0,
98+
height: 200.0
99+
),
100+
duration: const Duration(milliseconds: 200),
101+
crossFadeState: CrossFadeState.showFirst
102+
)
103+
)
104+
);
105+
106+
await tester.pumpWidget(
107+
new Center(
108+
child: new AnimatedCrossFade(
109+
alignment: FractionalOffset.bottomRight,
110+
firstChild: new SizedBox(
111+
key: firstKey,
112+
width: 100.0,
113+
height: 100.0
114+
),
115+
secondChild: new SizedBox(
116+
key: secondKey,
117+
width: 200.0,
118+
height: 200.0
119+
),
120+
duration: const Duration(milliseconds: 200),
121+
crossFadeState: CrossFadeState.showSecond
122+
)
123+
)
124+
);
125+
126+
await tester.pump(const Duration(milliseconds: 100));
127+
128+
final RenderBox box1 = tester.renderObject(find.byKey(firstKey));
129+
final RenderBox box2 = tester.renderObject(find.byKey(secondKey));
130+
expect(box1.localToGlobal(Offset.zero), const Offset(275.0, 175.0));
131+
expect(box2.localToGlobal(Offset.zero), const Offset(275.0, 175.0));
132+
});
133+
81134
}

0 commit comments

Comments
 (0)