Unverified Commit 2c413842 authored by Noor Dawod's avatar Noor Dawod Committed by GitHub

Feature refresh indicator padding (#72052)

Add ability to control RefreshProgressIndicator's distance from edges.
parent 25571a59
......@@ -113,6 +113,7 @@ class RefreshIndicator extends StatefulWidget {
Key? key,
required this.child,
this.displacement = 40.0,
this.edgeOffset = 0.0,
required this.onRefresh,
this.color,
this.backgroundColor,
......@@ -136,11 +137,31 @@ class RefreshIndicator extends StatefulWidget {
/// Typically a [ListView] or [CustomScrollView].
final Widget child;
/// The distance from the child's top or bottom edge to where the refresh
/// indicator will settle. During the drag that exposes the refresh indicator,
/// its actual displacement may significantly exceed this value.
/// The distance from the child's top or bottom [edgeOffset] where
/// the refresh indicator will settle. During the drag that exposes the refresh
/// indicator, its actual displacement may significantly exceed this value.
///
/// In most cases, [displacement] distance starts counting from the parent's
/// edges. However, if [edgeOffset] is larger than zero then the [displacement]
/// value is calculated from that offset instead of the parent's edge.
final double displacement;
/// The offset where [RefreshProgressIndicator] starts to appear on drag start.
///
/// Depending whether the indicator is showing on the top or bottom, the value
/// of this variable controls how far from the parent's edge the progress
/// indicator starts to appear. This may come in handy when, for example, the
/// UI contains a top [Widget] which covers the parent's edge where the progress
/// indicator would otherwise appear.
///
/// By default, the edge offset is set to 0.
///
/// See also:
///
/// * [displacement], can be used to change the distance from the edge that
/// the indicator settles.
final double edgeOffset;
/// A function that's called when the user has dragged the refresh indicator
/// far enough to demonstrate that they want the app to refresh. The returned
/// [Future] must complete when the refresh operation is finished.
......@@ -500,8 +521,8 @@ class RefreshIndicatorState extends State<RefreshIndicator> with TickerProviderS
children: <Widget>[
child,
if (_mode != null) Positioned(
top: _isIndicatorAtTop! ? 0.0 : null,
bottom: !_isIndicatorAtTop! ? 0.0 : null,
top: _isIndicatorAtTop! ? widget.edgeOffset : null,
bottom: !_isIndicatorAtTop! ? widget.edgeOffset : null,
left: 0.0,
right: 0.0,
child: SizeTransition(
......
......@@ -500,6 +500,83 @@ void main() {
);
});
testWidgets('RefreshIndicator responds to edgeOffset', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
home: RefreshIndicator(
onRefresh: () async {},
child: ListView(
physics: const AlwaysScrollableScrollPhysics(),
children: <String>['A', 'B', 'C', 'D', 'E', 'F'].map<Widget>((String item) {
return SizedBox(
height: 200.0,
child: Text(item),
);
}).toList(),
),
),
)
);
//By default the value of edgeOffset is 0.0
expect(
tester.widget<RefreshIndicator>(find.byType(RefreshIndicator)).edgeOffset,
0.0,
);
await tester.pumpWidget(
MaterialApp(
home: RefreshIndicator(
onRefresh: () async {},
edgeOffset: kToolbarHeight,
child: ListView(
physics: const AlwaysScrollableScrollPhysics(),
children: <String>['A', 'B', 'C', 'D', 'E', 'F'].map<Widget>((String item) {
return SizedBox(
height: 200.0,
child: Text(item),
);
}).toList(),
),
),
)
);
expect(
tester.widget<RefreshIndicator>(find.byType(RefreshIndicator)).edgeOffset,
kToolbarHeight,
);
});
testWidgets('RefreshIndicator appears at edgeOffset', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
home: RefreshIndicator(
edgeOffset: kToolbarHeight,
displacement: kToolbarHeight,
onRefresh: () async {
await Future<void>.delayed(const Duration(seconds: 1), () { });
},
child: ListView(
physics: const AlwaysScrollableScrollPhysics(),
children: <String>['A', 'B', 'C', 'D', 'E', 'F'].map<Widget>((String item) {
return SizedBox(
height: 200.0,
child: Text(item),
);
}).toList(),
),
),
));
await tester.fling(find.byType(ListView), const Offset(0.0, 2.0 * kToolbarHeight), 1000.0);
await tester.pump(const Duration(seconds: 2));
expect(
tester.getTopLeft(find.byType(RefreshProgressIndicator)).dy,
greaterThanOrEqualTo(2.0 * kToolbarHeight),
);
});
testWidgets('Top RefreshIndicator(anywhere mode) should be shown when dragging from non-zero scroll position', (WidgetTester tester) async {
refreshCalled = false;
final ScrollController scrollController = ScrollController();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment