From 5739bf4fabb8340ced93eecc0d15072498d3a7ac Mon Sep 17 00:00:00 2001 From: Taha Tesser Date: Tue, 24 May 2022 14:58:06 +0300 Subject: [PATCH] `RefreshIndicator`: Add `notificationPredicate` example (#103894) --- .../refresh_indicator.0.dart | 11 +-- .../refresh_indicator.1.dart | 87 +++++++++++++++++++ .../refresh_indicator.1_test.dart | 27 ++++++ .../lib/src/material/refresh_indicator.dart | 7 ++ 4 files changed, 124 insertions(+), 8 deletions(-) create mode 100644 examples/api/lib/material/refresh_indicator/refresh_indicator.1.dart create mode 100644 examples/api/test/material/refresh_indicator/refresh_indicator.1_test.dart diff --git a/examples/api/lib/material/refresh_indicator/refresh_indicator.0.dart b/examples/api/lib/material/refresh_indicator/refresh_indicator.0.dart index ac9db74ae13..f5119b51860 100644 --- a/examples/api/lib/material/refresh_indicator/refresh_indicator.0.dart +++ b/examples/api/lib/material/refresh_indicator/refresh_indicator.0.dart @@ -11,21 +11,16 @@ void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({super.key}); - static const String _title = 'RefreshIndicator Sample'; - @override Widget build(BuildContext context) { return const MaterialApp( - title: _title, - home: RefreshIndicatorExample(title: _title), + home: RefreshIndicatorExample(), ); } } class RefreshIndicatorExample extends StatefulWidget { - const RefreshIndicatorExample({super.key, required this.title}); - - final String title; + const RefreshIndicatorExample({super.key}); @override State createState() => _RefreshIndicatorExampleState(); @@ -39,7 +34,7 @@ class _RefreshIndicatorExampleState extends State { Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: Text(widget.title), + title: const Text('RefreshIndicator Sample'), ), body: RefreshIndicator( key: _refreshIndicatorKey, diff --git a/examples/api/lib/material/refresh_indicator/refresh_indicator.1.dart b/examples/api/lib/material/refresh_indicator/refresh_indicator.1.dart new file mode 100644 index 00000000000..c0fd0969884 --- /dev/null +++ b/examples/api/lib/material/refresh_indicator/refresh_indicator.1.dart @@ -0,0 +1,87 @@ +// 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. + +// Flutter code sample for RefreshIndicator + +import 'package:flutter/material.dart'; + +void main() => runApp(const MyApp()); + +class MyApp extends StatelessWidget { + const MyApp({super.key}); + + @override + Widget build(BuildContext context) { + return const MaterialApp( + home: RefreshIndicatorExample(), + ); + } +} + +class RefreshIndicatorExample extends StatelessWidget { + const RefreshIndicatorExample({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('RefreshIndicator Sample'), + ), + body: RefreshIndicator( + color: Colors.white, + backgroundColor: Colors.blue, + onRefresh: () async { + // Replace this delay with the code to be executed during refresh + // and return asynchronous code + return Future.delayed(const Duration(seconds: 3)); + }, + // This check is used to customize listening to scroll notifications + // from the widget's children. + // + // By default this is set to `notification.depth == 0`, which ensures + // the only the scroll notifications from the first child are listened to. + // + // Here setting `notification.depth == 1` triggers the refresh indicator + // when overscrolling the nested scroll view. + notificationPredicate: (ScrollNotification notification) { + return notification.depth == 1; + }, + child: SingleChildScrollView( + child: Column( + children: [ + Container( + height: 100, + alignment: Alignment.center, + color: Colors.pink[100], + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'Pull down here', + style: Theme.of(context).textTheme.headlineMedium, + ), + const Text("RefreshIndicator won't trigger"), + ], + ), + ), + Container( + color: Colors.green[100], + child: ListView.builder( + shrinkWrap: true, + itemCount: 25, + itemBuilder: (BuildContext context, int index) { + return const ListTile( + title: Text('Pull down here'), + subtitle: Text('RefreshIndicator will trigger'), + ); + }, + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/examples/api/test/material/refresh_indicator/refresh_indicator.1_test.dart b/examples/api/test/material/refresh_indicator/refresh_indicator.1_test.dart new file mode 100644 index 00000000000..452c3db6ad0 --- /dev/null +++ b/examples/api/test/material/refresh_indicator/refresh_indicator.1_test.dart @@ -0,0 +1,27 @@ +// 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/material/refresh_indicator/refresh_indicator.1.dart' as example; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + testWidgets('Pulling from nested scroll view triggers refresh indicator', (WidgetTester tester) async { + await tester.pumpWidget( + const example.MyApp(), + ); + + // Pull from the upper scroll view. + await tester.fling(find.text('Pull down here').first, const Offset(0.0, 300.0), 1000.0); + await tester.pump(); + expect(find.byType(RefreshProgressIndicator), findsNothing); + await tester.pumpAndSettle(); // Advance pending time + + // Pull from the nested scroll view. + await tester.fling(find.text('Pull down here').at(3), const Offset(0.0, 300.0), 1000.0); + await tester.pump(); + expect(find.byType(RefreshProgressIndicator), findsOneWidget); + await tester.pumpAndSettle(); // Advance pending time + }); +} diff --git a/packages/flutter/lib/src/material/refresh_indicator.dart b/packages/flutter/lib/src/material/refresh_indicator.dart index 01fff3623ba..34b19ebc56e 100644 --- a/packages/flutter/lib/src/material/refresh_indicator.dart +++ b/packages/flutter/lib/src/material/refresh_indicator.dart @@ -78,6 +78,13 @@ enum RefreshIndicatorTriggerMode { /// ** See code in examples/api/lib/material/refresh_indicator/refresh_indicator.0.dart ** /// {@end-tool} /// +/// {@tool dartpad} +/// This example shows how to trigger [RefreshIndicator] in a nested scroll view using +/// the [notificationPredicate] property. +/// +/// ** See code in examples/api/lib/material/refresh_indicator/refresh_indicator.1.dart ** +/// {@end-tool} +/// /// ## Troubleshooting /// /// ### Refresh indicator does not show up