Reland https://github.com/flutter/flutter/pull/129556/ which had failed an internal test (see Google internal link b/288993600) and was reverted in https://github.com/flutter/flutter/pull/129645. This PR must be landed with G3 Fix cl/543755631
This commit is contained in:
parent
f37a4d05a4
commit
14f1e13edb
@ -6,6 +6,7 @@ import 'package:flutter/foundation.dart';
|
||||
|
||||
import 'basic.dart';
|
||||
import 'framework.dart';
|
||||
import 'media_query.dart';
|
||||
import 'scroll_controller.dart';
|
||||
import 'scroll_delegate.dart';
|
||||
import 'scroll_physics.dart';
|
||||
@ -30,6 +31,35 @@ import 'ticker_provider.dart';
|
||||
/// ** See code in examples/api/lib/widgets/animated_list/animated_list.0.dart **
|
||||
/// {@end-tool}
|
||||
///
|
||||
/// By default, [AnimatedList] will automatically pad the limits of the
|
||||
/// list's scrollable to avoid partial obstructions indicated by
|
||||
/// [MediaQuery]'s padding. To avoid this behavior, override with a
|
||||
/// zero [padding] property.
|
||||
///
|
||||
/// {@tool snippet}
|
||||
/// The following example demonstrates how to override the default top and
|
||||
/// bottom padding using [MediaQuery.removePadding].
|
||||
///
|
||||
/// ```dart
|
||||
/// Widget myWidget(BuildContext context) {
|
||||
/// return MediaQuery.removePadding(
|
||||
/// context: context,
|
||||
/// removeTop: true,
|
||||
/// removeBottom: true,
|
||||
/// child: AnimatedList(
|
||||
/// initialItemCount: 50,
|
||||
/// itemBuilder: (BuildContext context, int index, Animation<double> animation) {
|
||||
/// return Card(
|
||||
/// color: Colors.amber,
|
||||
/// child: Center(child: Text('$index')),
|
||||
/// );
|
||||
/// }
|
||||
/// ),
|
||||
/// );
|
||||
/// }
|
||||
/// ```
|
||||
/// {@end-tool}
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [SliverAnimatedList], a sliver that animates items when they are inserted
|
||||
@ -176,6 +206,7 @@ class AnimatedListState extends _AnimatedScrollViewState<AnimatedList> {
|
||||
itemBuilder: widget.itemBuilder,
|
||||
initialItemCount: widget.initialItemCount,
|
||||
),
|
||||
widget.scrollDirection,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -196,6 +227,38 @@ class AnimatedListState extends _AnimatedScrollViewState<AnimatedList> {
|
||||
/// ** See code in examples/api/lib/widgets/animated_grid/animated_grid.0.dart **
|
||||
/// {@end-tool}
|
||||
///
|
||||
/// By default, [AnimatedGrid] will automatically pad the limits of the
|
||||
/// grid's scrollable to avoid partial obstructions indicated by
|
||||
/// [MediaQuery]'s padding. To avoid this behavior, override with a
|
||||
/// zero [padding] property.
|
||||
///
|
||||
/// {@tool snippet}
|
||||
/// The following example demonstrates how to override the default top and
|
||||
/// bottom padding using [MediaQuery.removePadding].
|
||||
///
|
||||
/// ```dart
|
||||
/// Widget myWidget(BuildContext context) {
|
||||
/// return MediaQuery.removePadding(
|
||||
/// context: context,
|
||||
/// removeTop: true,
|
||||
/// removeBottom: true,
|
||||
/// child: AnimatedGrid(
|
||||
/// gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
/// crossAxisCount: 3,
|
||||
/// ),
|
||||
/// initialItemCount: 50,
|
||||
/// itemBuilder: (BuildContext context, int index, Animation<double> animation) {
|
||||
/// return Card(
|
||||
/// color: Colors.amber,
|
||||
/// child: Center(child: Text('$index')),
|
||||
/// );
|
||||
/// }
|
||||
/// ),
|
||||
/// );
|
||||
/// }
|
||||
/// ```
|
||||
/// {@end-tool}
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [SliverAnimatedGrid], a sliver which animates items when they are inserted
|
||||
@ -353,6 +416,7 @@ class AnimatedGridState extends _AnimatedScrollViewState<AnimatedGrid> {
|
||||
itemBuilder: widget.itemBuilder,
|
||||
initialItemCount: widget.initialItemCount,
|
||||
),
|
||||
widget.scrollDirection,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -529,7 +593,35 @@ abstract class _AnimatedScrollViewState<T extends _AnimatedScrollView> extends S
|
||||
_sliverAnimatedMultiBoxKey.currentState!.removeAllItems(builder, duration: duration);
|
||||
}
|
||||
|
||||
Widget _wrap(Widget sliver) {
|
||||
Widget _wrap(Widget sliver, Axis direction) {
|
||||
EdgeInsetsGeometry? effectivePadding = widget.padding;
|
||||
if (widget.padding == null) {
|
||||
final MediaQueryData? mediaQuery = MediaQuery.maybeOf(context);
|
||||
if (mediaQuery != null) {
|
||||
// Automatically pad sliver with padding from MediaQuery.
|
||||
final EdgeInsets mediaQueryHorizontalPadding =
|
||||
mediaQuery.padding.copyWith(top: 0.0, bottom: 0.0);
|
||||
final EdgeInsets mediaQueryVerticalPadding =
|
||||
mediaQuery.padding.copyWith(left: 0.0, right: 0.0);
|
||||
// Consume the main axis padding with SliverPadding.
|
||||
effectivePadding = direction == Axis.vertical
|
||||
? mediaQueryVerticalPadding
|
||||
: mediaQueryHorizontalPadding;
|
||||
// Leave behind the cross axis padding.
|
||||
sliver = MediaQuery(
|
||||
data: mediaQuery.copyWith(
|
||||
padding: direction == Axis.vertical
|
||||
? mediaQueryHorizontalPadding
|
||||
: mediaQueryVerticalPadding,
|
||||
),
|
||||
child: sliver,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (effectivePadding != null) {
|
||||
sliver = SliverPadding(padding: effectivePadding, sliver: sliver);
|
||||
}
|
||||
return CustomScrollView(
|
||||
scrollDirection: widget.scrollDirection,
|
||||
reverse: widget.reverse,
|
||||
@ -538,12 +630,7 @@ abstract class _AnimatedScrollViewState<T extends _AnimatedScrollView> extends S
|
||||
physics: widget.physics,
|
||||
clipBehavior: widget.clipBehavior,
|
||||
shrinkWrap: widget.shrinkWrap,
|
||||
slivers: <Widget>[
|
||||
SliverPadding(
|
||||
padding: widget.padding ?? EdgeInsets.zero,
|
||||
sliver: sliver,
|
||||
),
|
||||
],
|
||||
slivers: <Widget>[ sliver ],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -646,6 +646,45 @@ void main() {
|
||||
|
||||
expect(tester.widget<CustomScrollView>(find.byType(CustomScrollView)).clipBehavior, clipBehavior);
|
||||
});
|
||||
|
||||
testWidgets('AnimatedGrid applies MediaQuery padding', (WidgetTester tester) async {
|
||||
const EdgeInsets padding = EdgeInsets.all(30.0);
|
||||
EdgeInsets? innerMediaQueryPadding;
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: MediaQuery(
|
||||
data: const MediaQueryData(
|
||||
padding: EdgeInsets.all(30.0),
|
||||
),
|
||||
child: AnimatedGrid(
|
||||
initialItemCount: 6,
|
||||
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
),
|
||||
itemBuilder: (BuildContext context, int index, Animation<double> animation) {
|
||||
innerMediaQueryPadding = MediaQuery.paddingOf(context);
|
||||
return const Placeholder();
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
final Offset topLeft = tester.getTopLeft(find.byType(Placeholder).first);
|
||||
// Automatically apply the top padding into sliver.
|
||||
expect(topLeft, Offset(0.0, padding.top));
|
||||
|
||||
// Scroll to the bottom.
|
||||
await tester.drag(find.byType(AnimatedGrid), const Offset(0.0, -1000.0));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final Offset bottomRight = tester.getBottomRight(find.byType(Placeholder).last);
|
||||
// Automatically apply the bottom padding into sliver.
|
||||
expect(bottomRight, Offset(800.0, 600.0 - padding.bottom));
|
||||
|
||||
// Verify that the left/right padding is not applied.
|
||||
expect(innerMediaQueryPadding, const EdgeInsets.symmetric(horizontal: 30.0));
|
||||
});
|
||||
}
|
||||
|
||||
class _StatefulListItem extends StatefulWidget {
|
||||
|
@ -649,6 +649,42 @@ void main() {
|
||||
|
||||
expect(tester.widget<CustomScrollView>(find.byType(CustomScrollView)).shrinkWrap, true);
|
||||
});
|
||||
|
||||
testWidgets('AnimatedList applies MediaQuery padding', (WidgetTester tester) async {
|
||||
const EdgeInsets padding = EdgeInsets.all(30.0);
|
||||
EdgeInsets? innerMediaQueryPadding;
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: MediaQuery(
|
||||
data: const MediaQueryData(
|
||||
padding: EdgeInsets.all(30.0),
|
||||
),
|
||||
child: AnimatedList(
|
||||
initialItemCount: 3,
|
||||
itemBuilder: (BuildContext context, int index, Animation<double> animation) {
|
||||
innerMediaQueryPadding = MediaQuery.paddingOf(context);
|
||||
return const Placeholder();
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
final Offset topLeft = tester.getTopLeft(find.byType(Placeholder).first);
|
||||
// Automatically apply the top padding into sliver.
|
||||
expect(topLeft, Offset(0.0, padding.top));
|
||||
|
||||
// Scroll to the bottom.
|
||||
await tester.drag(find.byType(AnimatedList), const Offset(0.0, -1000.0));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
final Offset bottomLeft = tester.getBottomLeft(find.byType(Placeholder).last);
|
||||
// Automatically apply the bottom padding into sliver.
|
||||
expect(bottomLeft, Offset(0.0, 600.0 - padding.bottom));
|
||||
|
||||
// Verify that the left/right padding is not applied.
|
||||
expect(innerMediaQueryPadding, const EdgeInsets.symmetric(horizontal: 30.0));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user