From 40af7db6bbac150987116f88c79075018b2b484b Mon Sep 17 00:00:00 2001 From: gmilou <139406084+gmilou@users.noreply.github.com> Date: Fri, 25 Aug 2023 13:09:58 -0700 Subject: [PATCH] Add an example showing how to use a MatrixTransition. (#132874) --- .../transitions/matrix_transition.0.dart | 75 +++++++++++++++++++ .../transitions/matrix_transition.0_test.dart | 56 ++++++++++++++ .../flutter/lib/src/widgets/transitions.dart | 9 ++- 3 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 examples/api/lib/widgets/transitions/matrix_transition.0.dart create mode 100644 examples/api/test/widgets/transitions/matrix_transition.0_test.dart diff --git a/examples/api/lib/widgets/transitions/matrix_transition.0.dart b/examples/api/lib/widgets/transitions/matrix_transition.0.dart new file mode 100644 index 0000000000..2d687a31e7 --- /dev/null +++ b/examples/api/lib/widgets/transitions/matrix_transition.0.dart @@ -0,0 +1,75 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:math'; + +import 'package:flutter/material.dart'; + +/// Flutter code sample for [MatrixTransition]. + +void main() => runApp(const MatrixTransitionExampleApp()); + +class MatrixTransitionExampleApp extends StatelessWidget { + const MatrixTransitionExampleApp({super.key}); + + @override + Widget build(BuildContext context) { + return const MaterialApp( + home: MatrixTransitionExample(), + ); + } +} + +class MatrixTransitionExample extends StatefulWidget { + const MatrixTransitionExample({super.key}); + + @override + State createState() => _MatrixTransitionExampleState(); +} + +/// [AnimationController]s can be created with `vsync: this` because of +/// [TickerProviderStateMixin]. +class _MatrixTransitionExampleState extends State with TickerProviderStateMixin { + late AnimationController _controller; + late Animation _animation; + + @override + void initState() { + super.initState(); + _controller = AnimationController( + duration: const Duration(seconds: 2), + vsync: this, + )..repeat(); + _animation = CurvedAnimation( + parent: _controller, + curve: Curves.linear, + ); + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Center( + child: MatrixTransition( + animation: _animation, + child: const Padding( + padding: EdgeInsets.all(8.0), + child: FlutterLogo(size: 150.0), + ), + onTransform: (double value) { + return Matrix4.identity() + ..setEntry(3, 2, 0.004) + ..rotateY(pi * 2.0 * value); + }, + ), + ), + ); + } +} diff --git a/examples/api/test/widgets/transitions/matrix_transition.0_test.dart b/examples/api/test/widgets/transitions/matrix_transition.0_test.dart new file mode 100644 index 0000000000..afa0ddabf6 --- /dev/null +++ b/examples/api/test/widgets/transitions/matrix_transition.0_test.dart @@ -0,0 +1,56 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter/material.dart'; +import 'package:flutter_api_samples/widgets/transitions/matrix_transition.0.dart' as example; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + testWidgets('Shows Flutter logo inside a MatrixTransition', (WidgetTester tester) async { + await tester.pumpWidget( + const example.MatrixTransitionExampleApp(), + ); + + final Finder transformFinder = find.ancestor( + of: find.byType(FlutterLogo), + matching: find.byType(MatrixTransition), + ); + expect(transformFinder, findsOneWidget); + }); + + testWidgets('MatrixTransition animates', (WidgetTester tester) async { + await tester.pumpWidget( + const example.MatrixTransitionExampleApp(), + ); + + final Finder transformFinder = find.ancestor( + of: find.byType(FlutterLogo), + matching: find.byType(Transform), + ); + + Transform transformBox = tester.widget(transformFinder); + Matrix4 actualTransform = transformBox.transform; + + // Check initial transform. + expect(actualTransform, Matrix4.fromList([ + 1.0, 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.004, 1.0, + ])..transpose()); + + // Animate half way. + await tester.pump(const Duration(seconds: 1)); + transformBox = tester.widget(transformFinder); + actualTransform = transformBox.transform; + + // The transform should be updated. + expect(actualTransform, isNot(Matrix4.fromList([ + 1.0, 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.004, 1.0, + ])..transpose())); + }); +} diff --git a/packages/flutter/lib/src/widgets/transitions.dart b/packages/flutter/lib/src/widgets/transitions.dart index b91f4fb2ad..f16100b086 100644 --- a/packages/flutter/lib/src/widgets/transitions.dart +++ b/packages/flutter/lib/src/widgets/transitions.dart @@ -236,6 +236,13 @@ typedef TransformCallback = Matrix4 Function(double animationValue); /// The [onTransform] callback computes a [Matrix4] from the animated value, it /// is called every time the [animation] changes its value. /// +/// {@tool dartpad} +/// The following example implements a [MatrixTransition] with a rotation around +/// the Y axis, with a 3D perspective skew. +/// +/// ** See code in examples/api/lib/widgets/transitions/matrix_transition.0.dart ** +/// {@end-tool} +/// /// See also: /// /// * [ScaleTransition], which animates the scale of a widget, by providing a @@ -311,7 +318,7 @@ class MatrixTransition extends AnimatedWidget { /// Animates the scale of a transformed widget. /// -/// Here's an illustration of the [ScaleTransition] widget, with it's [alignment] +/// Here's an illustration of the [ScaleTransition] widget, with it's [scale] /// animated by a [CurvedAnimation] set to [Curves.fastOutSlowIn]: /// {@animation 300 378 https://flutter.github.io/assets-for-api-docs/assets/widgets/scale_transition.mp4} ///