blob: 5f78398d9bb37ca55b362f59499295f340b1630a [file] [log] [blame]
// 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' as math;
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter/gestures.dart';
void main() {
testWidgets('Scrollable scaled up', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
await tester.pumpWidget(
MaterialApp(
home: Transform.scale(
scale: 2.0,
child: Center(
child: Container(
width: 200,
child: ListView.builder(
controller: controller,
cacheExtent: 0.0,
itemBuilder: (BuildContext context, int index) {
return Container(
height: 100.0,
color: index % 2 == 0 ? Colors.blue : Colors.red,
child: Text('Tile $index'),
);
},
),
),
),
),
),
);
expect(controller.offset, 0.0);
await tester.drag(find.byType(ListView), const Offset(0.0, -100.0));
await tester.pump();
expect(controller.offset, 50.0); // 100.0 / 2.0
await tester.drag(find.byType(ListView), const Offset(80.0, -70.0));
await tester.pump();
expect(controller.offset, 85.0); // 50.0 + (70.0 / 2)
await tester.drag(find.byType(ListView), const Offset(100.0, 0.0));
await tester.pump();
expect(controller.offset, 85.0);
await tester.drag(find.byType(ListView), const Offset(0.0, 85.0));
await tester.pump();
expect(controller.offset, 42.5); // 85.0 - (85.0 / 2)
});
testWidgets('Scrollable scaled down', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
await tester.pumpWidget(
MaterialApp(
home: Transform.scale(
scale: 0.5,
child: Center(
child: Container(
width: 200,
child: ListView.builder(
controller: controller,
cacheExtent: 0.0,
itemBuilder: (BuildContext context, int index) {
return Container(
height: 100.0,
color: index % 2 == 0 ? Colors.blue : Colors.red,
child: Text('Tile $index'),
);
},
),
),
),
),
),
);
expect(controller.offset, 0.0);
await tester.drag(find.byType(ListView), const Offset(0.0, -100.0));
await tester.pump();
expect(controller.offset, 200.0); // 100.0 * 2.0
await tester.drag(find.byType(ListView), const Offset(80.0, -70.0));
await tester.pump();
expect(controller.offset, 340.0); // 200.0 + (70.0 * 2)
await tester.drag(find.byType(ListView), const Offset(100.0, 0.0));
await tester.pump();
expect(controller.offset, 340.0);
await tester.drag(find.byType(ListView), const Offset(0.0, 170.0));
await tester.pump();
expect(controller.offset, 0.0); // 340.0 - (170.0 * 2)
});
testWidgets('Scrollable rotated 90 degrees', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
await tester.pumpWidget(
MaterialApp(
home: Transform.rotate(
angle: math.pi / 2,
child: Center(
child: Container(
width: 200,
child: ListView.builder(
controller: controller,
cacheExtent: 0.0,
itemBuilder: (BuildContext context, int index) {
return Container(
height: 100.0,
color: index % 2 == 0 ? Colors.blue : Colors.red,
child: Text('Tile $index'),
);
},
),
),
),
),
),
);
expect(controller.offset, 0.0);
await tester.drag(find.byType(ListView), const Offset(100.0, 0.0));
await tester.pump();
expect(controller.offset, 100.0);
await tester.drag(find.byType(ListView), const Offset(0.0, -100.0));
await tester.pump();
expect(controller.offset, 100.0);
await tester.drag(find.byType(ListView), const Offset(-70.0, -50.0));
await tester.pump();
expect(controller.offset, 30.0); // 100.0 - 70.0
});
testWidgets('Perspective transform on scrollable', (WidgetTester tester) async {
final ScrollController controller = ScrollController();
await tester.pumpWidget(
MaterialApp(
home: Transform(
transform: Matrix4.identity()
..setEntry(3, 2, 0.001)
..rotateX(math.pi / 4),
child: Center(
child: Container(
width: 200,
child: ListView.builder(
controller: controller,
cacheExtent: 0.0,
itemBuilder: (BuildContext context, int index) {
return Container(
height: 100.0,
color: index % 2 == 0 ? Colors.blue : Colors.red,
child: Text('Tile $index'),
);
},
),
),
),
),
),
);
expect(controller.offset, 0.0);
// We want to test that the point in the ListView that the finger touches
// on the screen stays under the finger as the finger scrolls the ListView
// in vertical direction. For this, we pick a point in the ListView (here
// the center of Tile 5) and calculate its position in the coordinate space
// of the screen. We then place our finger on that point and drag that
// point up in vertical direction. After the scroll activity is done,
// we verify that - in the coordinate space of the screen (!) - the point
// has moved the same distance as the finger. Due to the perspective
// transform the point will have moved more distance in the *local*
// coordinate system of the ListView.
// Calculate where the center of Tile 5 is located in the coordinate
// space of the screen. We cannot use `tester.getCenter` because it
// does not properly remove the perspective component from the transform
// to give us the place on the screen at which we need to touch the screen
// to have the center of Tile 5 directly under our finger.
final RenderBox tile5 = tester.renderObject(find.text('Tile 5'));
final Offset pointOnScreenStart = MatrixUtils.transformPoint(
PointerEvent.removePerspectiveTransform(tile5.getTransformTo(null)),
tile5.size.center(Offset.zero),
);
// Place the finger on the tracked point and move the finger upwards for
// 50 pixels to scroll the ListView (the ListView's scroll offset will
// move more then 50 pixels due to the perspective transform).
await tester.dragFrom(pointOnScreenStart, const Offset(0.0, -50.0));
await tester.pump();
// Get the new position of the tracked point in the screen's coordinate
// system.
final Offset pointOnScreenEnd = MatrixUtils.transformPoint(
PointerEvent.removePerspectiveTransform(tile5.getTransformTo(null)),
tile5.size.center(Offset.zero),
);
// The tracked point (in the coordinate space of the screen) and the finger
// should have moved the same vertical distance over the screen.
expect(
pointOnScreenStart.dy - pointOnScreenEnd.dy,
within(distance: 0.00001, from: 50.0),
);
// While the point traveled the same distance as the finger in the
// coordinate space of the screen, the scroll view actually moved far more
// pixels in its local coordinate system due to the perspective transform.
expect(controller.offset, greaterThan(100));
});
}