@@ -1906,6 +1906,61 @@ void main() {
19061906 expect (tester.getCenter (find.text ('Item 49' )).dy, equals (585.0 ));
19071907 }, variant: const TargetPlatformVariant (< TargetPlatform > { TargetPlatform .iOS }));
19081908 });
1909+
1910+ // Regression test for https://github.com/flutter/flutter/issues/63978
1911+ testWidgets ('Inner _NestedScrollPosition.applyClampedDragUpdate correctly calculates range when in overscroll' , (WidgetTester tester) async {
1912+ final GlobalKey <NestedScrollViewState > nestedScrollView = GlobalKey ();
1913+ await tester.pumpWidget (MaterialApp (
1914+ home: Scaffold (
1915+ body: NestedScrollView (
1916+ key: nestedScrollView,
1917+ headerSliverBuilder: (BuildContext context, bool boxIsScrolled) {
1918+ return < Widget > [
1919+ const SliverAppBar (
1920+ expandedHeight: 200 ,
1921+ title: Text ('Test' ),
1922+ )
1923+ ];
1924+ },
1925+ body: ListView .builder (
1926+ itemExtent: 100.0 ,
1927+ itemBuilder: (BuildContext context, int index) => Container (
1928+ padding: const EdgeInsets .all (10.0 ),
1929+ child: Material (
1930+ color: index.isEven ? Colors .cyan : Colors .deepOrange,
1931+ child: Center (
1932+ child: Text (index.toString ()),
1933+ ),
1934+ ),
1935+ ),
1936+ ),
1937+ ),
1938+ ),
1939+ ));
1940+
1941+ expect (nestedScrollView.currentState! .outerController.position.pixels, 0.0 );
1942+ expect (nestedScrollView.currentState! .innerController.position.pixels, 0.0 );
1943+ expect (nestedScrollView.currentState! .outerController.position.maxScrollExtent, 200.0 );
1944+ final Offset point = tester.getCenter (find.text ('1' ));
1945+ // Drag slightly into overscroll in the inner position.
1946+ final TestGesture gesture = await tester.startGesture (point);
1947+ await gesture.moveBy (const Offset (0.0 , 5.0 ));
1948+ await tester.pump ();
1949+ expect (nestedScrollView.currentState! .outerController.position.pixels, 0.0 );
1950+ expect (nestedScrollView.currentState! .innerController.position.pixels, - 5.0 );
1951+ // Move by a much larger delta than the amount of over scroll, in a very
1952+ // short period of time.
1953+ await gesture.moveBy (const Offset (0.0 , - 500.0 ));
1954+ await tester.pump ();
1955+ // The overscrolled inner position should have closed, then passed the
1956+ // correct remaining delta to the outer position, and finally any remainder
1957+ // back to the inner position.
1958+ expect (
1959+ nestedScrollView.currentState! .outerController.position.pixels,
1960+ nestedScrollView.currentState! .outerController.position.maxScrollExtent,
1961+ );
1962+ expect (nestedScrollView.currentState! .innerController.position.pixels, 295.0 );
1963+ }, variant: const TargetPlatformVariant (< TargetPlatform > { TargetPlatform .iOS, TargetPlatform .macOS }));
19091964}
19101965
19111966class TestHeader extends SliverPersistentHeaderDelegate {
0 commit comments