Fix GlowingOverscrollIndicator
examples (#155203)
Part of https://github.com/flutter/flutter/issues/130459 This pull request adds tests for the example files shown in the [GlowingOverscrollIndicator](https://api.flutter.dev/flutter/widgets/GlowingOverscrollIndicator-class.html) Flutter API reference documentation.
This commit is contained in:
parent
bb08ec9a03
commit
2d2ebbe263
@ -321,6 +321,4 @@ final Set<String> _knownMissingTests = <String>{
|
|||||||
'examples/api/test/widgets/interactive_viewer/interactive_viewer.constrained.0_test.dart',
|
'examples/api/test/widgets/interactive_viewer/interactive_viewer.constrained.0_test.dart',
|
||||||
'examples/api/test/widgets/interactive_viewer/interactive_viewer.transformation_controller.0_test.dart',
|
'examples/api/test/widgets/interactive_viewer/interactive_viewer.transformation_controller.0_test.dart',
|
||||||
'examples/api/test/widgets/notification_listener/notification.0_test.dart',
|
'examples/api/test/widgets/notification_listener/notification.0_test.dart',
|
||||||
'examples/api/test/widgets/overscroll_indicator/glowing_overscroll_indicator.1_test.dart',
|
|
||||||
'examples/api/test/widgets/overscroll_indicator/glowing_overscroll_indicator.0_test.dart',
|
|
||||||
};
|
};
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
import 'package:flutter/gestures.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
/// Flutter code sample for [GlowingOverscrollIndicator].
|
/// Flutter code sample for [GlowingOverscrollIndicator].
|
||||||
@ -14,6 +15,8 @@ class GlowingOverscrollIndicatorExampleApp extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
|
scrollBehavior: const AlwaysGlow(),
|
||||||
|
theme: ThemeData(colorSchemeSeed: Colors.amber),
|
||||||
home: Scaffold(
|
home: Scaffold(
|
||||||
appBar: AppBar(title: const Text('GlowingOverscrollIndicator Sample')),
|
appBar: AppBar(title: const Text('GlowingOverscrollIndicator Sample')),
|
||||||
body: const GlowingOverscrollIndicatorExample(),
|
body: const GlowingOverscrollIndicatorExample(),
|
||||||
@ -22,12 +25,37 @@ class GlowingOverscrollIndicatorExampleApp extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Set<PointerDeviceKind> allPointers = <PointerDeviceKind>{...PointerDeviceKind.values};
|
||||||
|
|
||||||
|
// Passing this class into the MaterialApp constructor ensures that a
|
||||||
|
// GlowingOverscrollIndicator is created, regardless of the target platform.
|
||||||
|
class AlwaysGlow extends MaterialScrollBehavior {
|
||||||
|
const AlwaysGlow();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Set<PointerDeviceKind> get dragDevices => allPointers;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget buildOverscrollIndicator(
|
||||||
|
BuildContext context,
|
||||||
|
Widget child,
|
||||||
|
ScrollableDetails details,
|
||||||
|
) {
|
||||||
|
return GlowingOverscrollIndicator(
|
||||||
|
axisDirection: details.direction,
|
||||||
|
color: Colors.amberAccent,
|
||||||
|
child: child,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class GlowingOverscrollIndicatorExample extends StatelessWidget {
|
class GlowingOverscrollIndicatorExample extends StatelessWidget {
|
||||||
const GlowingOverscrollIndicatorExample({super.key});
|
const GlowingOverscrollIndicatorExample({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final double leadingPaintOffset = MediaQuery.of(context).padding.top + AppBar().preferredSize.height;
|
final double leadingPaintOffset = MediaQuery.paddingOf(context).top + kToolbarHeight;
|
||||||
|
|
||||||
return NotificationListener<OverscrollIndicatorNotification>(
|
return NotificationListener<OverscrollIndicatorNotification>(
|
||||||
onNotification: (OverscrollIndicatorNotification notification) {
|
onNotification: (OverscrollIndicatorNotification notification) {
|
||||||
if (notification.leading) {
|
if (notification.leading) {
|
||||||
@ -35,17 +63,33 @@ class GlowingOverscrollIndicatorExample extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
child: CustomScrollView(
|
child: const CustomScrollView(
|
||||||
slivers: <Widget>[
|
slivers: <Widget>[
|
||||||
const SliverAppBar(title: Text('Custom PaintOffset')),
|
SliverAppBar(title: Text('Custom PaintOffset')),
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: Container(
|
child: DefaultTextStyle(
|
||||||
|
style: TextStyle(
|
||||||
color: Colors.amberAccent,
|
color: Colors.amberAccent,
|
||||||
height: 100,
|
fontSize: 24,
|
||||||
child: const Center(child: Text('Glow all day!')),
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
child: ColoredBox(
|
||||||
|
color: Colors.grey,
|
||||||
|
child: SizedBox(
|
||||||
|
width: double.infinity,
|
||||||
|
height: 80,
|
||||||
|
child: Center(child: Text('Glow all day!')),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SliverFillRemaining(
|
||||||
|
child: Icon(
|
||||||
|
Icons.sunny,
|
||||||
|
color: Colors.amberAccent,
|
||||||
|
size: 128,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SliverFillRemaining(child: FlutterLogo()),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
import 'package:flutter/gestures.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
/// Flutter code sample for [GlowingOverscrollIndicator].
|
/// Flutter code sample for [GlowingOverscrollIndicator].
|
||||||
@ -14,6 +15,8 @@ class GlowingOverscrollIndicatorExampleApp extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
|
scrollBehavior: const AlwaysGlow(),
|
||||||
|
theme: ThemeData(colorSchemeSeed: Colors.amber),
|
||||||
home: Scaffold(
|
home: Scaffold(
|
||||||
appBar: AppBar(title: const Text('GlowingOverscrollIndicator Sample')),
|
appBar: AppBar(title: const Text('GlowingOverscrollIndicator Sample')),
|
||||||
body: const GlowingOverscrollIndicatorExample(),
|
body: const GlowingOverscrollIndicatorExample(),
|
||||||
@ -22,6 +25,31 @@ class GlowingOverscrollIndicatorExampleApp extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Set<PointerDeviceKind> allPointers = <PointerDeviceKind>{...PointerDeviceKind.values};
|
||||||
|
|
||||||
|
// Passing this class into the MaterialApp constructor ensures that a
|
||||||
|
// GlowingOverscrollIndicator is created, regardless of the target platform.
|
||||||
|
class AlwaysGlow extends MaterialScrollBehavior {
|
||||||
|
const AlwaysGlow();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Set<PointerDeviceKind> get dragDevices => allPointers;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget buildOverscrollIndicator(
|
||||||
|
BuildContext context,
|
||||||
|
Widget child,
|
||||||
|
ScrollableDetails details,
|
||||||
|
) {
|
||||||
|
return GlowingOverscrollIndicator(
|
||||||
|
axisDirection: details.direction,
|
||||||
|
color: Colors.amberAccent,
|
||||||
|
child: child,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class GlowingOverscrollIndicatorExample extends StatelessWidget {
|
class GlowingOverscrollIndicatorExample extends StatelessWidget {
|
||||||
const GlowingOverscrollIndicatorExample({super.key});
|
const GlowingOverscrollIndicatorExample({super.key});
|
||||||
|
|
||||||
@ -33,16 +61,32 @@ class GlowingOverscrollIndicatorExample extends StatelessWidget {
|
|||||||
SliverAppBar(title: Text('Custom NestedScrollViews')),
|
SliverAppBar(title: Text('Custom NestedScrollViews')),
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
body: CustomScrollView(
|
body: const CustomScrollView(
|
||||||
slivers: <Widget>[
|
slivers: <Widget>[
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: Container(
|
child: DefaultTextStyle(
|
||||||
|
style: TextStyle(
|
||||||
color: Colors.amberAccent,
|
color: Colors.amberAccent,
|
||||||
height: 100,
|
fontSize: 24,
|
||||||
child: const Center(child: Text('Glow all day!')),
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
child: ColoredBox(
|
||||||
|
color: Colors.grey,
|
||||||
|
child: SizedBox(
|
||||||
|
width: double.infinity,
|
||||||
|
height: 80,
|
||||||
|
child: Center(child: Text('Glow all day!')),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SliverFillRemaining(
|
||||||
|
child: Icon(
|
||||||
|
Icons.sunny,
|
||||||
|
color: Colors.amberAccent,
|
||||||
|
size: 128,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SliverFillRemaining(child: FlutterLogo()),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -0,0 +1,85 @@
|
|||||||
|
// 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/rendering.dart';
|
||||||
|
import 'package:flutter_api_samples/widgets/overscroll_indicator/glowing_overscroll_indicator.0.dart' as example;
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
testWidgets('Displays widget tree when the example app is run', (WidgetTester tester) async {
|
||||||
|
await tester.pumpWidget(const example.GlowingOverscrollIndicatorExampleApp());
|
||||||
|
|
||||||
|
expect(find.descendant(
|
||||||
|
of: find.byType(Scaffold),
|
||||||
|
matching: find.widgetWithText(AppBar, 'GlowingOverscrollIndicator Sample'),
|
||||||
|
), findsOne);
|
||||||
|
|
||||||
|
final Finder customScrollViewFinder = find.byType(CustomScrollView);
|
||||||
|
final Finder sliverAppBarFinder = find.descendant(
|
||||||
|
of: customScrollViewFinder,
|
||||||
|
matching: find.widgetWithText(SliverAppBar, 'Custom PaintOffset'),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(sliverAppBarFinder, findsOne);
|
||||||
|
|
||||||
|
expect(find.descendant(
|
||||||
|
of: customScrollViewFinder,
|
||||||
|
matching: find.widgetWithText(Center, 'Glow all day!'),
|
||||||
|
), findsOne);
|
||||||
|
|
||||||
|
expect(find.descendant(
|
||||||
|
of: customScrollViewFinder,
|
||||||
|
matching: find.byType(SliverToBoxAdapter),
|
||||||
|
), findsOne);
|
||||||
|
|
||||||
|
expect(find.descendant(
|
||||||
|
of: customScrollViewFinder,
|
||||||
|
matching: find.widgetWithIcon(SliverFillRemaining, Icons.sunny),
|
||||||
|
), findsOne);
|
||||||
|
|
||||||
|
expect(find.descendant(
|
||||||
|
of: customScrollViewFinder,
|
||||||
|
matching: find.byType(GlowingOverscrollIndicator),
|
||||||
|
), findsOne);
|
||||||
|
|
||||||
|
// Check if GlowingOverscrollIndicator overlays the SliverAppBar.
|
||||||
|
final RenderBox overscrollIndicator = tester.renderObject<RenderBox>(
|
||||||
|
find.descendant(
|
||||||
|
of: customScrollViewFinder,
|
||||||
|
matching: find.byType(GlowingOverscrollIndicator),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
final RenderSliver sliverAppBar = tester.renderObject<RenderSliver>(sliverAppBarFinder);
|
||||||
|
final Matrix4 transform = overscrollIndicator.getTransformTo(sliverAppBar);
|
||||||
|
final Offset? offset = MatrixUtils.getAsTranslation(transform);
|
||||||
|
expect(offset?.dy, 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('Triggers a notification listener when the screen is dragged', (WidgetTester tester) async {
|
||||||
|
bool overscrollNotified = false;
|
||||||
|
double leadingPaintOffset = 0.0;
|
||||||
|
|
||||||
|
await tester.pumpWidget(
|
||||||
|
NotificationListener<OverscrollIndicatorNotification>(
|
||||||
|
onNotification: (OverscrollIndicatorNotification notification) {
|
||||||
|
overscrollNotified = true;
|
||||||
|
leadingPaintOffset = notification.paintOffset;
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
child: const example.GlowingOverscrollIndicatorExampleApp(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(leadingPaintOffset, 0);
|
||||||
|
expect(overscrollNotified, isFalse);
|
||||||
|
final BuildContext context = tester.element(find.byType(MaterialApp));
|
||||||
|
|
||||||
|
await tester.drag(find.byType(CustomScrollView), const Offset(0, 500));
|
||||||
|
await tester.pump();
|
||||||
|
|
||||||
|
expect(leadingPaintOffset, MediaQuery.paddingOf(context).top + kToolbarHeight);
|
||||||
|
expect(overscrollNotified, isTrue);
|
||||||
|
});
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
// 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/rendering.dart';
|
||||||
|
import 'package:flutter_api_samples/widgets/overscroll_indicator/glowing_overscroll_indicator.1.dart' as example;
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
testWidgets('Displays widget tree when the example app is run', (WidgetTester tester) async {
|
||||||
|
await tester.pumpWidget(const example.GlowingOverscrollIndicatorExampleApp());
|
||||||
|
|
||||||
|
expect(find.descendant(
|
||||||
|
of: find.byType(Scaffold),
|
||||||
|
matching: find.widgetWithText(AppBar, 'GlowingOverscrollIndicator Sample'),
|
||||||
|
), findsOne);
|
||||||
|
|
||||||
|
expect(find.descendant(
|
||||||
|
of: find.byType(NestedScrollView),
|
||||||
|
matching: find.widgetWithText(SliverAppBar, 'Custom NestedScrollViews'),
|
||||||
|
), findsOne);
|
||||||
|
|
||||||
|
expect(find.descendant(
|
||||||
|
of: find.byType(NestedScrollView),
|
||||||
|
matching: find.widgetWithText(Center, 'Glow all day!'),
|
||||||
|
), findsOne);
|
||||||
|
|
||||||
|
final Finder customScrollViewFinder = find.byType(CustomScrollView);
|
||||||
|
|
||||||
|
expect(find.descendant(
|
||||||
|
of: customScrollViewFinder,
|
||||||
|
matching: find.byType(SliverToBoxAdapter),
|
||||||
|
), findsOne);
|
||||||
|
|
||||||
|
expect(find.descendant(
|
||||||
|
of: customScrollViewFinder,
|
||||||
|
matching: find.widgetWithIcon(SliverFillRemaining, Icons.sunny),
|
||||||
|
), findsOne);
|
||||||
|
|
||||||
|
expect(find.descendant(
|
||||||
|
of: customScrollViewFinder,
|
||||||
|
matching: find.byType(GlowingOverscrollIndicator),
|
||||||
|
), findsOne);
|
||||||
|
|
||||||
|
// Check if GlowingOverscrollIndicator starts just after the SliverAppBar.
|
||||||
|
final RenderBox overscrollIndicator = tester.renderObject<RenderBox>(
|
||||||
|
find.descendant(
|
||||||
|
of: customScrollViewFinder,
|
||||||
|
matching: find.byType(GlowingOverscrollIndicator),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
final RenderSliver sliverAppBar = tester.renderObject<RenderSliver>(
|
||||||
|
find.widgetWithText(SliverAppBar, 'Custom NestedScrollViews'),
|
||||||
|
);
|
||||||
|
final Matrix4 transform = overscrollIndicator.getTransformTo(sliverAppBar);
|
||||||
|
final Offset? offset = MatrixUtils.getAsTranslation(transform);
|
||||||
|
expect(offset?.dy, sliverAppBar.geometry?.paintExtent);
|
||||||
|
});
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user