Skip to content

Commit 8065887

Browse files
saminarpnayeemtbygspencergoog
authored
Add transform flip (#116705)
* Added Transform.flip * Add tests for Transform.flip * fix: failing tests * fix the failing test * fix test according to review * Make z component constant, update doc * Disabled changing alignment * Apply suggested definition Co-authored-by: Greg Spencer <[email protected]> Co-authored-by: nayeemtby <[email protected]> Co-authored-by: Nayeem Hasan <[email protected]> Co-authored-by: Greg Spencer <[email protected]>
1 parent b1f4070 commit 8065887

File tree

2 files changed

+125
-0
lines changed

2 files changed

+125
-0
lines changed

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

+30
Original file line numberDiff line numberDiff line change
@@ -1424,6 +1424,36 @@ class Transform extends SingleChildRenderObjectWidget {
14241424
assert(scale == null || (scaleX == null && scaleY == null), "If 'scale' is non-null then 'scaleX' and 'scaleY' must be left null"),
14251425
transform = Matrix4.diagonal3Values(scale ?? scaleX ?? 1.0, scale ?? scaleY ?? 1.0, 1.0);
14261426

1427+
/// Creates a widget that mirrors its child about the widget's center point.
1428+
///
1429+
/// If `flipX` is true, the child widget will be flipped horizontally. Defaults to false.
1430+
///
1431+
/// If `flipY` is true, the child widget will be flipped vertically. Defaults to false.
1432+
///
1433+
/// If both are true, the child widget will be flipped both vertically and horizontally, equivalent to a 180 degree rotation.
1434+
///
1435+
/// {@tool snippet}
1436+
///
1437+
/// This example flips the text horizontally.
1438+
///
1439+
/// ```dart
1440+
/// Transform.flip(
1441+
/// flipX: true,
1442+
/// child: const Text('Horizontal Flip'),
1443+
/// )
1444+
/// ```
1445+
/// {@end-tool}
1446+
Transform.flip({
1447+
super.key,
1448+
bool flipX = false,
1449+
bool flipY = false,
1450+
this.origin,
1451+
this.transformHitTests = true,
1452+
this.filterQuality,
1453+
super.child,
1454+
}) : alignment = Alignment.center,
1455+
transform = Matrix4.diagonal3Values(flipX ? -1.0 : 1.0, flipY ? -1.0 : 1.0, 1.0);
1456+
14271457
// Computes a rotation matrix for an angle in radians, attempting to keep rotations
14281458
// at integral values for angles of 0, π/2, π, 3π/2.
14291459
static Matrix4 _computeRotation(double radians) {

packages/flutter/test/widgets/transform_test.dart

+95
Original file line numberDiff line numberDiff line change
@@ -787,6 +787,101 @@ void main() {
787787

788788
expect(tester.getBottomRight(find.byType(Container)), target.bottomRight(tester.getTopLeft(find.byType(Container))));
789789
});
790+
791+
testWidgets(
792+
'Transform.flip does flip child correctly',
793+
(WidgetTester tester) async {
794+
const Offset topRight = Offset(60, 20);
795+
const Offset bottomLeft = Offset(20, 60);
796+
const Offset bottomRight = Offset(60, 60);
797+
798+
bool tappedRed = false;
799+
800+
const Widget square = SizedBox.square(dimension: 40);
801+
final Widget child = Column(
802+
mainAxisSize: MainAxisSize.min,
803+
children: <Widget> [
804+
Row(mainAxisSize: MainAxisSize.min, children: <Widget>[
805+
GestureDetector(
806+
onTap: () => tappedRed = true,
807+
child: const ColoredBox(color: Color(0xffff0000), child: square),
808+
),
809+
const ColoredBox(color: Color(0xff00ff00), child: square),
810+
]),
811+
Row(mainAxisSize: MainAxisSize.min, children: const <Widget>[
812+
ColoredBox(color: Color(0xff0000ff), child: square),
813+
ColoredBox(color: Color(0xffeeff00), child: square),
814+
]),
815+
],
816+
);
817+
818+
await tester.pumpWidget(
819+
Directionality(
820+
textDirection: TextDirection.ltr,
821+
child: Align(
822+
alignment: Alignment.topLeft,
823+
child: Transform.flip(
824+
flipX: true,
825+
child: child,
826+
),
827+
),
828+
),
829+
);
830+
831+
await tester.pumpAndSettle();
832+
833+
await tester.tapAt(topRight);
834+
835+
expect(tappedRed, isTrue, reason: 'Transform.flip cannot flipX');
836+
837+
tappedRed = false;
838+
839+
await tester.pumpWidget(
840+
Directionality(
841+
textDirection: TextDirection.ltr,
842+
child: Align(
843+
alignment: Alignment.topLeft,
844+
child: Transform.flip(
845+
flipY: true,
846+
child: child,
847+
),
848+
),
849+
),
850+
);
851+
852+
await tester.pumpAndSettle();
853+
854+
await tester.tapAt(bottomLeft);
855+
856+
expect(tappedRed, isTrue, reason: 'Transform.flip cannot flipY');
857+
858+
tappedRed = false;
859+
860+
await tester.pumpWidget(
861+
Directionality(
862+
textDirection: TextDirection.ltr,
863+
child: Align(
864+
alignment: Alignment.topLeft,
865+
child: Transform.flip(
866+
flipX: true,
867+
flipY: true,
868+
child: child,
869+
),
870+
),
871+
),
872+
);
873+
874+
await tester.pumpAndSettle();
875+
876+
await tester.tapAt(bottomRight);
877+
878+
expect(
879+
tappedRed,
880+
isTrue,
881+
reason: 'Transform.flip cannot flipX and flipY together',
882+
);
883+
},
884+
);
790885
}
791886

792887
class TestRectPainter extends CustomPainter {

0 commit comments

Comments
 (0)