Skip to content

Commit bf3f380

Browse files
mono0926Shi-Hao Hong
andauthored
[animations] Set FadeScaleTransitionConfiguration to configuration default value (#136)
* Set showModal configuration default FadeScaleTransitionConfiguration Co-Authored-By: Shi-Hao Hong <[email protected]>
1 parent f5411da commit bf3f380

File tree

3 files changed

+195
-3
lines changed

3 files changed

+195
-3
lines changed

packages/animations/example/lib/fade_scale_transition.dart

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,6 @@ class _FadeScaleTransitionDemoState extends State<FadeScaleTransitionDemo>
8585
onPressed: () {
8686
showModal<void>(
8787
context: context,
88-
configuration: const FadeScaleTransitionConfiguration(),
8988
builder: (BuildContext context) {
9089
return _ExampleAlertDialog();
9190
},

packages/animations/lib/src/modal.dart

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
import 'package:flutter/material.dart';
66

7+
import 'fade_scale_transition.dart';
8+
79
/// Signature for a function that creates a widget that builds a
810
/// transition.
911
///
@@ -26,7 +28,8 @@ typedef _ModalTransitionBuilder = Widget Function(
2628
/// The `configuration` argument is used to determine characteristics of the
2729
/// modal route that will be displayed, such as the enter and exit
2830
/// transitions, the duration of the transitions, and modal barrier
29-
/// properties.
31+
/// properties. By default, `configuration` is
32+
/// [FadeScaleTransitionConfiguration].
3033
///
3134
/// The `useRootNavigator` argument is used to determine whether to push the
3235
/// modal to the [Navigator] furthest from or nearest to the given `context`.
@@ -45,7 +48,7 @@ typedef _ModalTransitionBuilder = Widget Function(
4548
/// the modal's characteristics.
4649
Future<T> showModal<T>({
4750
@required BuildContext context,
48-
@required ModalConfiguration configuration,
51+
ModalConfiguration configuration = const FadeScaleTransitionConfiguration(),
4952
bool useRootNavigator = true,
5053
WidgetBuilder builder,
5154
}) {

packages/animations/test/modal_test.dart

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,185 @@ void main() {
153153
},
154154
);
155155

156+
testWidgets(
157+
'showModal builds a new route with specified barrier properties '
158+
'with default configuration(FadeScaleTransitionConfiguration)',
159+
(WidgetTester tester) async {
160+
await tester.pumpWidget(
161+
MaterialApp(
162+
home: Scaffold(
163+
body: Builder(builder: (BuildContext context) {
164+
return Center(
165+
child: RaisedButton(
166+
onPressed: () {
167+
showModal<void>(
168+
context: context,
169+
builder: (BuildContext context) {
170+
return const _FlutterLogoModal();
171+
},
172+
);
173+
},
174+
child: const Icon(Icons.add),
175+
),
176+
);
177+
}),
178+
),
179+
),
180+
);
181+
await tester.tap(find.byType(RaisedButton));
182+
await tester.pumpAndSettle();
183+
184+
// New route containing _FlutterLogoModal is present.
185+
expect(find.byType(_FlutterLogoModal), findsOneWidget);
186+
final ModalBarrier topModalBarrier = tester.widget<ModalBarrier>(
187+
find.byType(ModalBarrier).at(1),
188+
);
189+
190+
// Verify new route's modal barrier properties are correct.
191+
expect(topModalBarrier.color, Colors.black54);
192+
expect(topModalBarrier.barrierSemanticsDismissible, true);
193+
expect(topModalBarrier.semanticsLabel, 'Dismiss');
194+
},
195+
);
196+
197+
testWidgets(
198+
'showModal forwards animation '
199+
'with default configuration(FadeScaleTransitionConfiguration)',
200+
(WidgetTester tester) async {
201+
final GlobalKey key = GlobalKey();
202+
await tester.pumpWidget(
203+
MaterialApp(
204+
home: Scaffold(
205+
body: Builder(builder: (BuildContext context) {
206+
return Center(
207+
child: RaisedButton(
208+
onPressed: () {
209+
showModal<void>(
210+
context: context,
211+
builder: (BuildContext context) {
212+
return _FlutterLogoModal(key: key);
213+
},
214+
);
215+
},
216+
child: const Icon(Icons.add),
217+
),
218+
);
219+
}),
220+
),
221+
),
222+
);
223+
224+
// Start forwards animation
225+
await tester.tap(find.byType(RaisedButton));
226+
await tester.pump();
227+
228+
// Opacity duration: First 30% of 150ms, linear transition
229+
double topFadeTransitionOpacity = _getOpacity(key, tester);
230+
double topScale = _getScale(key, tester);
231+
expect(topFadeTransitionOpacity, 0.0);
232+
expect(topScale, 0.80);
233+
234+
// 3/10 * 150ms = 45ms (total opacity animation duration)
235+
// 1/2 * 45ms = ~23ms elapsed for halfway point of opacity
236+
// animation
237+
await tester.pump(const Duration(milliseconds: 23));
238+
topFadeTransitionOpacity = _getOpacity(key, tester);
239+
expect(topFadeTransitionOpacity, closeTo(0.5, 0.05));
240+
topScale = _getScale(key, tester);
241+
expect(topScale, greaterThan(0.80));
242+
expect(topScale, lessThan(1.0));
243+
244+
// End of opacity animation.
245+
await tester.pump(const Duration(milliseconds: 22));
246+
topFadeTransitionOpacity = _getOpacity(key, tester);
247+
expect(topFadeTransitionOpacity, 1.0);
248+
topScale = _getScale(key, tester);
249+
expect(topScale, greaterThan(0.80));
250+
expect(topScale, lessThan(1.0));
251+
252+
// 100ms into the animation
253+
await tester.pump(const Duration(milliseconds: 55));
254+
topScale = _getScale(key, tester);
255+
expect(topScale, greaterThan(0.80));
256+
expect(topScale, lessThan(1.0));
257+
258+
// Get to the end of the animation
259+
await tester.pump(const Duration(milliseconds: 50));
260+
topScale = _getScale(key, tester);
261+
expect(topScale, 1.0);
262+
263+
await tester.pump(const Duration(milliseconds: 1));
264+
expect(find.byType(_FlutterLogoModal), findsOneWidget);
265+
},
266+
);
267+
268+
testWidgets(
269+
'showModal reverse animation '
270+
'with default configuration(FadeScaleTransitionConfiguration)',
271+
(WidgetTester tester) async {
272+
final GlobalKey key = GlobalKey();
273+
await tester.pumpWidget(
274+
MaterialApp(
275+
home: Scaffold(
276+
body: Builder(builder: (BuildContext context) {
277+
return Center(
278+
child: RaisedButton(
279+
onPressed: () {
280+
showModal<void>(
281+
context: context,
282+
builder: (BuildContext context) {
283+
return _FlutterLogoModal(key: key);
284+
},
285+
);
286+
},
287+
child: const Icon(Icons.add),
288+
),
289+
);
290+
}),
291+
),
292+
),
293+
);
294+
295+
// Start forwards animation
296+
await tester.tap(find.byType(RaisedButton));
297+
await tester.pumpAndSettle();
298+
expect(find.byType(_FlutterLogoModal), findsOneWidget);
299+
300+
// Tap on modal barrier to start reverse animation.
301+
await tester.tapAt(Offset.zero);
302+
await tester.pump();
303+
304+
// Opacity duration: Linear transition throughout 75ms
305+
// No scale animations on exit transition.
306+
double topFadeTransitionOpacity = _getOpacity(key, tester);
307+
double topScale = _getScale(key, tester);
308+
expect(topFadeTransitionOpacity, 1.0);
309+
expect(topScale, 1.0);
310+
311+
await tester.pump(const Duration(milliseconds: 25));
312+
topFadeTransitionOpacity = _getOpacity(key, tester);
313+
topScale = _getScale(key, tester);
314+
expect(topFadeTransitionOpacity, closeTo(0.66, 0.05));
315+
expect(topScale, 1.0);
316+
317+
await tester.pump(const Duration(milliseconds: 25));
318+
topFadeTransitionOpacity = _getOpacity(key, tester);
319+
topScale = _getScale(key, tester);
320+
expect(topFadeTransitionOpacity, closeTo(0.33, 0.05));
321+
expect(topScale, 1.0);
322+
323+
// End of opacity animation
324+
await tester.pump(const Duration(milliseconds: 25));
325+
topFadeTransitionOpacity = _getOpacity(key, tester);
326+
expect(topFadeTransitionOpacity, 0.0);
327+
topScale = _getScale(key, tester);
328+
expect(topScale, 1.0);
329+
330+
await tester.pump(const Duration(milliseconds: 1));
331+
expect(find.byType(_FlutterLogoModal), findsNothing);
332+
},
333+
);
334+
156335
testWidgets(
157336
'State is not lost when transitioning',
158337
(WidgetTester tester) async {
@@ -290,6 +469,17 @@ double _getOpacity(GlobalKey key, WidgetTester tester) {
290469
});
291470
}
292471

472+
double _getScale(GlobalKey key, WidgetTester tester) {
473+
final Finder finder = find.ancestor(
474+
of: find.byKey(key),
475+
matching: find.byType(ScaleTransition),
476+
);
477+
return tester.widgetList(finder).fold<double>(1.0, (double a, Widget widget) {
478+
final ScaleTransition transition = widget;
479+
return a * transition.scale.value;
480+
});
481+
}
482+
293483
class _FlutterLogoModal extends StatefulWidget {
294484
const _FlutterLogoModal({
295485
Key key,

0 commit comments

Comments
 (0)