Unverified Commit 7d19f97d authored by LongCatIsLooong's avatar LongCatIsLooong Committed by GitHub

Fix refresh control in the gallery demo, update comments (#30129)

- Fixed the bug where CupertinoRefreshControl doesn't work in the gallery demo on Android.
- Updated documentation on CupertinoRefreshControl
- Added comments to the gallery demo
- Added concrete examples to ScrollPhysics
parent e57d0ff7
...@@ -48,6 +48,15 @@ class _CupertinoRefreshControlDemoState extends State<CupertinoRefreshControlDem ...@@ -48,6 +48,15 @@ class _CupertinoRefreshControlDemoState extends State<CupertinoRefreshControlDem
: CupertinoColors.darkBackgroundGray, : CupertinoColors.darkBackgroundGray,
), ),
child: CustomScrollView( child: CustomScrollView(
// If left unspecified, the [CustomScrollView] appends an
// [AlwaysScrollableScrollPhysics]. Behind the scene, the ScrollableState
// will attach that [AlwaysScrollableScrollPhysics] to the output of
// [ScrollConfiguration.of] which will be a [ClampingScrollPhysics]
// on Android.
// To demonstrate the iOS behavior in this demo and to ensure that the list
// always scrolls, we specifically use a [BouncingScrollPhysics] combined
// with a [AlwaysScrollableScrollPhysics]
physics: const BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics()),
slivers: <Widget>[ slivers: <Widget>[
CupertinoSliverNavigationBar( CupertinoSliverNavigationBar(
largeTitle: const Text('Refresh'), largeTitle: const Text('Refresh'),
......
...@@ -82,6 +82,9 @@ Future<void> smokeDemo(WidgetTester tester, GalleryDemo demo) async { ...@@ -82,6 +82,9 @@ Future<void> smokeDemo(WidgetTester tester, GalleryDemo demo) async {
verifyToStringOutput('debugDumpLayerTree', routeName, RendererBinding.instance?.renderView?.debugLayer?.toStringDeep()); verifyToStringOutput('debugDumpLayerTree', routeName, RendererBinding.instance?.renderView?.debugLayer?.toStringDeep());
// Scroll the demo around a bit more. // Scroll the demo around a bit more.
await tester.flingFrom(const Offset(400.0, 300.0), const Offset(0.0, 400.0), 1000.0);
await tester.pump();
await tester.pump(const Duration(milliseconds: 400));
await tester.flingFrom(const Offset(400.0, 300.0), const Offset(-200.0, 0.0), 500.0); await tester.flingFrom(const Offset(400.0, 300.0), const Offset(-200.0, 0.0), 500.0);
await tester.pump(); await tester.pump();
await tester.pump(const Duration(milliseconds: 50)); await tester.pump(const Duration(milliseconds: 50));
...@@ -90,9 +93,6 @@ Future<void> smokeDemo(WidgetTester tester, GalleryDemo demo) async { ...@@ -90,9 +93,6 @@ Future<void> smokeDemo(WidgetTester tester, GalleryDemo demo) async {
await tester.flingFrom(const Offset(400.0, 300.0), const Offset(100.0, 0.0), 500.0); await tester.flingFrom(const Offset(400.0, 300.0), const Offset(100.0, 0.0), 500.0);
await tester.pump(); await tester.pump();
await tester.pump(const Duration(milliseconds: 400)); await tester.pump(const Duration(milliseconds: 400));
await tester.flingFrom(const Offset(400.0, 300.0), const Offset(0.0, 400.0), 1000.0);
await tester.pump();
await tester.pump(const Duration(milliseconds: 400));
// Go back // Go back
await tester.pageBack(); await tester.pageBack();
......
...@@ -248,8 +248,17 @@ typedef RefreshCallback = Future<void> Function(); ...@@ -248,8 +248,17 @@ typedef RefreshCallback = Future<void> Function();
/// and the indicator sliver has retracted at least 90% of the way back. /// and the indicator sliver has retracted at least 90% of the way back.
/// ///
/// Can only be used in downward-scrolling vertical lists that overscrolls. In /// Can only be used in downward-scrolling vertical lists that overscrolls. In
/// other words, refreshes can't be triggered with lists using /// other words, refreshes can't be triggered with [Scrollable]s using
/// [ClampingScrollPhysics]. /// [ClampingScrollPhysics] which is the default on Android. To allow overscroll
/// on Android, use an overscrolling physics such as [BouncingScrollPhysics].
/// This can be done via:
///
/// * Providing a [BouncingScrollPhysics] (possibly in combination with a
/// [AlwaysScrollableScrollPhysics]) while constructing the scrollable.
/// * By inserting a [ScrollConfiguration] with [BouncingScrollPhysics] above
/// the scrollable.
/// * By using [CupertinoApp], which always uses a [ScrollConfiguration]
/// with [BouncingScrollPhysics] regardless of platform.
/// ///
/// In a typical application, this sliver should be inserted between the app bar /// In a typical application, this sliver should be inserted between the app bar
/// sliver such as [CupertinoSliverNavigationBar] and your main scrollable /// sliver such as [CupertinoSliverNavigationBar] and your main scrollable
......
...@@ -15,6 +15,14 @@ import 'scroll_simulation.dart'; ...@@ -15,6 +15,14 @@ import 'scroll_simulation.dart';
export 'package:flutter/physics.dart' show Simulation, ScrollSpringSimulation, Tolerance; export 'package:flutter/physics.dart' show Simulation, ScrollSpringSimulation, Tolerance;
// Examples can assume:
// class FooScrollPhysics extends ScrollPhysics {
// const FooScrollPhysics({ ScrollPhysics parent }): super(parent: parent);
// }
// class BarScrollPhysics extends ScrollPhysics {
// const BarScrollPhysics({ ScrollPhysics parent }): super(parent: parent);
// }
/// Determines the physics of a [Scrollable] widget. /// Determines the physics of a [Scrollable] widget.
/// ///
/// For example, determines how the [Scrollable] will behave when the user /// For example, determines how the [Scrollable] will behave when the user
...@@ -24,6 +32,9 @@ export 'package:flutter/physics.dart' show Simulation, ScrollSpringSimulation, T ...@@ -24,6 +32,9 @@ export 'package:flutter/physics.dart' show Simulation, ScrollSpringSimulation, T
/// velocity are used as the initial conditions for the particle in the /// velocity are used as the initial conditions for the particle in the
/// simulation. The movement of the particle in the simulation is then used to /// simulation. The movement of the particle in the simulation is then used to
/// determine the scroll position for the widget. /// determine the scroll position for the widget.
///
/// Instead of creating your own subclasses, [parent] can be used to combine
/// [ScrollPhysics] objects of different types to get the desired scroll physics.
@immutable @immutable
class ScrollPhysics { class ScrollPhysics {
/// Creates an object with the default scroll physics. /// Creates an object with the default scroll physics.
...@@ -34,7 +45,16 @@ class ScrollPhysics { ...@@ -34,7 +45,16 @@ class ScrollPhysics {
/// If a subclass of [ScrollPhysics] does not override a method, that subclass /// If a subclass of [ScrollPhysics] does not override a method, that subclass
/// will inherit an implementation from this base class that defers to /// will inherit an implementation from this base class that defers to
/// [parent]. This mechanism lets you assemble novel combinations of /// [parent]. This mechanism lets you assemble novel combinations of
/// [ScrollPhysics] subclasses at runtime. /// [ScrollPhysics] subclasses at runtime. For example:
///
/// ```dart
/// BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics())
///
/// ```
/// will result in a [ScrollPhysics] that has the combined behavior
/// of [BouncingScrollPhysics] and [AlwaysScrollableScrollPhysics]:
/// behaviors that are not specified in [BouncingScrollPhysics]
/// (e.g. [shouldAcceptUserOffset]) will defer to [AlwaysScrollableScrollPhysics].
final ScrollPhysics parent; final ScrollPhysics parent;
/// If [parent] is null then return ancestor, otherwise recursively build a /// If [parent] is null then return ancestor, otherwise recursively build a
...@@ -60,6 +80,18 @@ class ScrollPhysics { ...@@ -60,6 +80,18 @@ class ScrollPhysics {
/// The returned object will combine some of the behaviors from this /// The returned object will combine some of the behaviors from this
/// [ScrollPhysics] instance and some of the behaviors from [ancestor]. /// [ScrollPhysics] instance and some of the behaviors from [ancestor].
/// ///
/// {@tool sample}
///
/// In the following example, the [applyTo] method is used to combine the
/// scroll physics of two [ScrollPhysics] objects, the resulting [ScrollPhysics]
/// `x` has the same behavior as `y`:
///
/// ```dart
/// final FooScrollPhysics x = FooScrollPhysics().applyTo(BarScrollPhysics());
/// const FooScrollPhysics y = FooScrollPhysics(parent: BarScrollPhysics());
/// ```
/// {@end-tool}
///
/// See also: /// See also:
/// ///
/// * [buildParent], a utility method that's often used to define [applyTo] /// * [buildParent], a utility method that's often used to define [applyTo]
......
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