Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
cb67ecd9
Unverified
Commit
cb67ecd9
authored
Feb 24, 2023
by
Mitchell Goodwin
Committed by
GitHub
Feb 24, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add adaptive RefreshIndicator (#121249)
parent
9e6214f8
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
104 additions
and
3 deletions
+104
-3
refresh_indicator.dart
packages/flutter/lib/src/material/refresh_indicator.dart
+61
-3
refresh_indicator_test.dart
packages/flutter/test/material/refresh_indicator_test.dart
+43
-0
No files found.
packages/flutter/lib/src/material/refresh_indicator.dart
View file @
cb67ecd9
...
...
@@ -5,8 +5,8 @@
import
'dart:async'
;
import
'dart:math'
as
math
;
import
'package:flutter/cupertino.dart'
;
import
'package:flutter/foundation.dart'
show
clampDouble
;
import
'package:flutter/widgets.dart'
;
import
'debug.dart'
;
import
'material_localizations.dart'
;
...
...
@@ -59,6 +59,8 @@ enum RefreshIndicatorTriggerMode {
onEdge
,
}
enum
_IndicatorType
{
material
,
adaptive
}
/// A widget that supports the Material "swipe to refresh" idiom.
///
/// {@youtube 560 315 https://www.youtube.com/watch?v=ORApMlzwMdM}
...
...
@@ -138,7 +140,38 @@ class RefreshIndicator extends StatefulWidget {
this
.
semanticsValue
,
this
.
strokeWidth
=
RefreshProgressIndicator
.
defaultStrokeWidth
,
this
.
triggerMode
=
RefreshIndicatorTriggerMode
.
onEdge
,
});
})
:
_indicatorType
=
_IndicatorType
.
material
;
/// Creates an adaptive [RefreshIndicator] based on whether the target
/// platform is iOS or macOS, following Material design's
/// [Cross-platform guidelines](https://material.io/design/platform-guidance/cross-platform-adaptation.html).
///
/// When the descendant overscrolls, a different spinning progress indicator
/// is shown depending on platform. On iOS and macOS,
/// [CupertinoActivityIndicator] is shown, but on all other platforms,
/// [CircularProgressIndicator] appears.
///
/// If a [CupertinoActivityIndicator] is shown, the following parameters are ignored:
/// [backgroundColor], [semanticsLabel], [semanticsValue], [strokeWidth].
///
/// The target platform is based on the current [Theme]: [ThemeData.platform].
///
/// Noteably the scrollable widget itself will have slightly different behavior
/// from [CupertinoSliverRefreshControl], due to a difference in structure.
const
RefreshIndicator
.
adaptive
({
super
.
key
,
required
this
.
child
,
this
.
displacement
=
40.0
,
this
.
edgeOffset
=
0.0
,
required
this
.
onRefresh
,
this
.
color
,
this
.
backgroundColor
,
this
.
notificationPredicate
=
defaultScrollNotificationPredicate
,
this
.
semanticsLabel
,
this
.
semanticsValue
,
this
.
strokeWidth
=
RefreshProgressIndicator
.
defaultStrokeWidth
,
this
.
triggerMode
=
RefreshIndicatorTriggerMode
.
onEdge
,
})
:
_indicatorType
=
_IndicatorType
.
adaptive
;
/// The widget below this widget in the tree.
///
...
...
@@ -207,6 +240,8 @@ class RefreshIndicator extends StatefulWidget {
/// By default, the value of [strokeWidth] is 2.0 pixels.
final
double
strokeWidth
;
final
_IndicatorType
_indicatorType
;
/// Defines how this [RefreshIndicator] can be triggered when users overscroll.
///
/// The [RefreshIndicator] can be pulled out in two cases,
...
...
@@ -555,7 +590,7 @@ class RefreshIndicatorState extends State<RefreshIndicator> with TickerProviderS
child:
AnimatedBuilder
(
animation:
_positionController
,
builder:
(
BuildContext
context
,
Widget
?
child
)
{
return
RefreshProgressIndicator
(
final
Widget
materialIndicator
=
RefreshProgressIndicator
(
semanticsLabel:
widget
.
semanticsLabel
??
MaterialLocalizations
.
of
(
context
).
refreshIndicatorSemanticLabel
,
semanticsValue:
widget
.
semanticsValue
,
value:
showIndeterminateIndicator
?
null
:
_value
.
value
,
...
...
@@ -563,6 +598,29 @@ class RefreshIndicatorState extends State<RefreshIndicator> with TickerProviderS
backgroundColor:
widget
.
backgroundColor
,
strokeWidth:
widget
.
strokeWidth
,
);
final
Widget
cupertinoIndicator
=
CupertinoActivityIndicator
(
color:
widget
.
color
,
);
switch
(
widget
.
_indicatorType
)
{
case
_IndicatorType
.
material
:
return
materialIndicator
;
case
_IndicatorType
.
adaptive
:
{
final
ThemeData
theme
=
Theme
.
of
(
context
);
switch
(
theme
.
platform
)
{
case
TargetPlatform
.
android
:
case
TargetPlatform
.
fuchsia
:
case
TargetPlatform
.
linux
:
case
TargetPlatform
.
windows
:
return
materialIndicator
;
case
TargetPlatform
.
iOS
:
case
TargetPlatform
.
macOS
:
return
cupertinoIndicator
;
}
}
}
},
),
),
...
...
packages/flutter/test/material/refresh_indicator_test.dart
View file @
cb67ecd9
...
...
@@ -4,6 +4,7 @@
import
'dart:async'
;
import
'package:flutter/cupertino.dart'
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter_test/flutter_test.dart'
;
...
...
@@ -792,6 +793,48 @@ void main() {
expect
(
refreshCalled
,
false
);
});
testWidgets
(
'RefreshIndicator.adaptive'
,
(
WidgetTester
tester
)
async
{
Widget
buildFrame
(
TargetPlatform
platform
)
{
return
MaterialApp
(
theme:
ThemeData
(
platform:
platform
),
home:
RefreshIndicator
.
adaptive
(
onRefresh:
refresh
,
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
(),
),
),
);
}
for
(
final
TargetPlatform
platform
in
<
TargetPlatform
>[
TargetPlatform
.
iOS
,
TargetPlatform
.
macOS
])
{
await
tester
.
pumpWidget
(
buildFrame
(
platform
));
await
tester
.
pumpAndSettle
();
// Finish the theme change animation.
await
tester
.
fling
(
find
.
text
(
'A'
),
const
Offset
(
0.0
,
300.0
),
1000.0
);
await
tester
.
pump
();
expect
(
find
.
byType
(
CupertinoActivityIndicator
),
findsOneWidget
);
expect
(
find
.
byType
(
RefreshProgressIndicator
),
findsNothing
);
}
for
(
final
TargetPlatform
platform
in
<
TargetPlatform
>[
TargetPlatform
.
android
,
TargetPlatform
.
fuchsia
,
TargetPlatform
.
linux
,
TargetPlatform
.
windows
])
{
await
tester
.
pumpWidget
(
buildFrame
(
platform
));
await
tester
.
pumpAndSettle
();
// Finish the theme change animation.
await
tester
.
fling
(
find
.
text
(
'A'
),
const
Offset
(
0.0
,
300.0
),
1000.0
);
await
tester
.
pump
();
expect
(
tester
.
getSemantics
(
find
.
byType
(
RefreshProgressIndicator
)),
matchesSemantics
(
label:
'Refresh'
,
));
expect
(
find
.
byType
(
CupertinoActivityIndicator
),
findsNothing
);
}
});
testWidgets
(
'RefreshIndicator color defaults to ColorScheme.primary'
,
(
WidgetTester
tester
)
async
{
const
Color
primaryColor
=
Color
(
0xff4caf50
);
final
ThemeData
theme
=
ThemeData
.
from
(
colorScheme:
const
ColorScheme
.
light
().
copyWith
(
primary:
primaryColor
));
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment