list_view_misc_test.dart 7.21 KB
Newer Older
Ian Hickson's avatar
Ian Hickson committed
1
// Copyright 2014 The Flutter Authors. All rights reserved.
Hixie's avatar
Hixie committed
2 3 4
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5 6
// @dart = 2.8

Adam Barth's avatar
Adam Barth committed
7
import 'package:flutter_test/flutter_test.dart';
8
import 'package:flutter/rendering.dart';
9
import 'package:flutter/widgets.dart';
Hixie's avatar
Hixie committed
10

11
const Key blockKey = Key('test');
Hixie's avatar
Hixie committed
12 13

void main() {
14 15
  testWidgets('Cannot scroll a non-overflowing block', (WidgetTester tester) async {
    await tester.pumpWidget(
16
      Directionality(
17
        textDirection: TextDirection.ltr,
18
        child: ListView(
19 20
          key: blockKey,
          children: <Widget>[
21
            Container(
22 23 24 25 26 27
              height: 200.0, // less than 600, the height of the test area
              child: const Text('Hello'),
            ),
          ],
        ),
      ),
28 29
    );

30 31
    final Offset middleOfContainer = tester.getCenter(find.text('Hello'));
    final Offset target = tester.getCenter(find.byKey(blockKey));
32
    final TestGesture gesture = await tester.startGesture(target);
33
    await gesture.moveBy(const Offset(0.0, -10.0));
34

35
    await tester.pump(const Duration(milliseconds: 1));
36 37 38

    expect(tester.getCenter(find.text('Hello')) == middleOfContainer, isTrue);

39
    await gesture.up();
Hixie's avatar
Hixie committed
40 41
  });

42 43
  testWidgets('Can scroll an overflowing block', (WidgetTester tester) async {
    await tester.pumpWidget(
44
      Directionality(
45
        textDirection: TextDirection.ltr,
46
        child: ListView(
47 48
          key: blockKey,
          children: <Widget>[
49
            Container(
50 51 52 53 54 55
              height: 2000.0, // more than 600, the height of the test area
              child: const Text('Hello'),
            ),
          ],
        ),
      ),
56
    );
57

58 59 60
    final Offset middleOfContainer = tester.getCenter(find.text('Hello'));
    expect(middleOfContainer.dx, equals(400.0));
    expect(middleOfContainer.dy, equals(1000.0));
61

62
    final Offset target = tester.getCenter(find.byKey(blockKey));
63
    final TestGesture gesture = await tester.startGesture(target);
64
    await gesture.moveBy(const Offset(0.0, -10.0));
65

66
    await tester.pump(); // redo layout
67

68
    expect(tester.getCenter(find.text('Hello')), isNot(equals(middleOfContainer)));
69

70
    await gesture.up();
Hixie's avatar
Hixie committed
71
  });
72

73
  testWidgets('ListView reverse', (WidgetTester tester) async {
74 75 76
    int first = 0;
    int second = 0;

77
    Widget buildBlock({ bool reverse = false }) {
78
      return Directionality(
79
        textDirection: TextDirection.ltr,
80 81
        child: ListView(
          key: UniqueKey(),
82 83
          reverse: reverse,
          children: <Widget>[
84
            GestureDetector(
85
              onTap: () { first += 1; },
86
              child: Container(
87 88
                height: 350.0, // more than half the height of the test area
                color: const Color(0xFF00FF00),
89
              ),
90
            ),
91
            GestureDetector(
92
              onTap: () { second += 1; },
93
              child: Container(
94 95 96 97 98 99
                height: 350.0, // more than half the height of the test area
                color: const Color(0xFF0000FF),
              ),
            ),
          ],
        ),
100 101
      );
    }
102

103
    await tester.pumpWidget(buildBlock(reverse: true));
104

105
    const Offset target = Offset(200.0, 200.0);
106
    await tester.tapAt(target);
107 108
    expect(first, equals(0));
    expect(second, equals(1));
109

110
    await tester.pumpWidget(buildBlock(reverse: false));
111

112
    await tester.tapAt(target);
113 114
    expect(first, equals(1));
    expect(second, equals(1));
115
  });
116

117
  testWidgets('ListView controller', (WidgetTester tester) async {
118
    final ScrollController controller = ScrollController();
119

120
    Widget buildBlock() {
121
      return Directionality(
122
        textDirection: TextDirection.ltr,
123
        child: ListView(
124
          controller: controller,
125
          children: const <Widget>[Text('A'), Text('B'), Text('C')],
126
        ),
127 128 129
      );
    }
    await tester.pumpWidget(buildBlock());
130
    expect(controller.offset, equals(0.0));
131
  });
132

133
  testWidgets('SliverBlockChildListDelegate.estimateMaxScrollOffset hits end', (WidgetTester tester) async {
134 135 136 137 138 139
    final SliverChildListDelegate delegate = SliverChildListDelegate(<Widget>[
      Container(),
      Container(),
      Container(),
      Container(),
      Container(),
140 141
    ]);

142
    await tester.pumpWidget(
143
      Directionality(
144
        textDirection: TextDirection.ltr,
145
        child: CustomScrollView(
146
          slivers: <Widget>[
147
            SliverList(
148 149 150
              delegate: delegate,
            ),
          ],
151
        ),
152 153
      ),
    );
154

155
    final SliverMultiBoxAdaptorElement element = tester.element(find.byType(SliverList, skipOffstage: false));
156 157 158 159 160 161

    final double maxScrollOffset = element.estimateMaxScrollOffset(
      null,
      firstIndex: 3,
      lastIndex: 4,
      leadingScrollOffset: 25.0,
162
      trailingScrollOffset: 26.0,
163 164
    );
    expect(maxScrollOffset, equals(26.0));
165
  });
166 167 168

  testWidgets('Resizing a ListView child restores scroll offset', (WidgetTester tester) async {
    // Regression test for https://github.com/flutter/flutter/issues/9221
169
    final AnimationController controller = AnimationController(
170 171 172 173 174 175
      vsync: const TestVSync(),
      duration: const Duration(milliseconds: 200),
    );

    // The overall height of the frame is (as ever) 600
    Widget buildFrame() {
176
      return Directionality(
177
        textDirection: TextDirection.ltr,
178
        child: Column(
179
          children: <Widget>[
180
            Flexible(
181
              // The overall height of the ListView's contents is 500
182
              child: ListView(
183
                children: const <Widget>[
184
                  SizedBox(
185
                    height: 150.0,
186
                    child: Center(
187
                      child: Text('top'),
188
                    ),
189
                  ),
190
                  SizedBox(
191
                    height: 200.0,
192
                    child: Center(
193
                      child: Text('middle'),
194
                    ),
195
                  ),
196
                  SizedBox(
197
                    height: 150.0,
198
                    child: Center(
199
                      child: Text('bottom'),
200
                    ),
201
                  ),
202 203
                ],
              ),
204
            ),
205
            // If this widget's height is > 100 the ListView can scroll.
206
            SizeTransition(
207 208 209
              sizeFactor: controller.view,
              child: const SizedBox(
                height: 300.0,
210
                child: Text('keyboard'),
211
              ),
212
            ),
213 214
          ],
        ),
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243
      );
    }

    await tester.pumpWidget(buildFrame());
    expect(find.text('top'), findsOneWidget);

    final ScrollPosition position = Scrollable.of(tester.element(find.text('middle'))).position;
    expect(position.viewportDimension, 600.0);
    expect(position.pixels, 0.0);

    // Animate the 'keyboard' height from 0 to 300
    controller.forward();
    await tester.pumpAndSettle();
    expect(position.viewportDimension, 300.0);

    // Scroll the ListView upwards
    position.jumpTo(200.0);
    await tester.pumpAndSettle();
    expect(position.pixels, 200.0);
    expect(find.text('top'), findsNothing);

    // Animate the 'keyboard' height back to 0. This causes the scroll
    // offset to return to 0.0
    controller.reverse();
    await tester.pumpAndSettle();
    expect(position.viewportDimension, 600.0);
    expect(position.pixels, 0.0);
    expect(find.text('top'), findsOneWidget);
  });
Hixie's avatar
Hixie committed
244
}