Allow DSS to be dragged when its children do not fill extent (#31832)
* Allow DSS to be dragged when its children do not fill extent * Fix when maxChildSize < 1.0
This commit is contained in:
parent
c0d5fd23ab
commit
4bc35fc87a
@ -262,13 +262,16 @@ class _DraggableSheetExtent {
|
||||
}
|
||||
double get currentExtent => _currentExtent.value;
|
||||
|
||||
double get additionalMinExtent => isAtMin ? 0.0 : 1.0;
|
||||
double get additionalMaxExtent => isAtMax ? 0.0 : 1.0;
|
||||
|
||||
/// The scroll position gets inputs in terms of pixels, but the extent is
|
||||
/// expected to be expressed as a number between 0..1.
|
||||
void addPixelDelta(double delta, BuildContext context) {
|
||||
if (availablePixels == 0) {
|
||||
return;
|
||||
}
|
||||
currentExtent += delta / availablePixels;
|
||||
currentExtent += delta / availablePixels * maxExtent;
|
||||
DraggableScrollableNotification(
|
||||
minExtent: minExtent,
|
||||
maxExtent: maxExtent,
|
||||
@ -426,6 +429,17 @@ class _DraggableScrollableSheetScrollPosition
|
||||
final _DraggableSheetExtent extent;
|
||||
bool get listShouldScroll => pixels > 0.0;
|
||||
|
||||
@override
|
||||
bool applyContentDimensions(double minScrollExtent, double maxScrollExtent) {
|
||||
// We need to provide some extra extent if we haven't yet reached the max or
|
||||
// min extents. Otherwise, a list with fewer children than the extent of
|
||||
// the available space will get stuck.
|
||||
return super.applyContentDimensions(
|
||||
minScrollExtent - extent.additionalMinExtent,
|
||||
maxScrollExtent + extent.additionalMaxExtent,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void applyUserOffset(double delta) {
|
||||
if (!listShouldScroll &&
|
||||
|
@ -297,6 +297,7 @@ void main() {
|
||||
children: <TestSemantics>[
|
||||
TestSemantics(
|
||||
flags: <SemanticsFlag>[SemanticsFlag.hasImplicitScrolling],
|
||||
actions: <SemanticsAction>[SemanticsAction.scrollDown, SemanticsAction.scrollUp],
|
||||
children: <TestSemantics>[
|
||||
TestSemantics(
|
||||
label: 'BottomSheet',
|
||||
|
@ -8,7 +8,14 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
void main() {
|
||||
Widget _boilerplate(VoidCallback onButtonPressed) {
|
||||
Widget _boilerplate(VoidCallback onButtonPressed, {
|
||||
int itemCount = 100,
|
||||
double initialChildSize = .5,
|
||||
double maxChildSize = 1.0,
|
||||
double minChildSize = .25,
|
||||
double itemExtent,
|
||||
Key containerKey,
|
||||
}) {
|
||||
return Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: Stack(
|
||||
@ -18,14 +25,17 @@ void main() {
|
||||
onPressed: onButtonPressed,
|
||||
),
|
||||
DraggableScrollableSheet(
|
||||
maxChildSize: 1.0,
|
||||
minChildSize: .25,
|
||||
maxChildSize: maxChildSize,
|
||||
minChildSize: minChildSize,
|
||||
initialChildSize: initialChildSize,
|
||||
builder: (BuildContext context, ScrollController scrollController) {
|
||||
return Container(
|
||||
key: containerKey,
|
||||
color: const Color(0xFFABCDEF),
|
||||
child: ListView.builder(
|
||||
controller: scrollController,
|
||||
itemCount: 100,
|
||||
itemExtent: itemExtent,
|
||||
itemCount: itemCount,
|
||||
itemBuilder: (BuildContext context, int index) => Text('Item $index'),
|
||||
),
|
||||
);
|
||||
@ -36,6 +46,38 @@ void main() {
|
||||
);
|
||||
}
|
||||
|
||||
testWidgets('Scrolls correct amount when maxChildSize < 1.0', (WidgetTester tester) async {
|
||||
const Key key = ValueKey<String>('container');
|
||||
await tester.pumpWidget(_boilerplate(
|
||||
null,
|
||||
maxChildSize: .6,
|
||||
initialChildSize: .25,
|
||||
itemExtent: 25.0,
|
||||
containerKey: key,
|
||||
));
|
||||
|
||||
expect(tester.getRect(find.byKey(key)), const Rect.fromLTRB(0.0, 450.0, 800.0, 600.0));
|
||||
await tester.drag(find.text('Item 5'), const Offset(0, -125));
|
||||
await tester.pumpAndSettle();
|
||||
expect(tester.getRect(find.byKey(key)), const Rect.fromLTRB(0.0, 325.0, 800.0, 600.0));
|
||||
});
|
||||
|
||||
testWidgets('Scrolls correct amount when maxChildSize == 1.0', (WidgetTester tester) async {
|
||||
const Key key = ValueKey<String>('container');
|
||||
await tester.pumpWidget(_boilerplate(
|
||||
null,
|
||||
maxChildSize: 1.0,
|
||||
initialChildSize: .25,
|
||||
itemExtent: 25.0,
|
||||
containerKey: key,
|
||||
));
|
||||
|
||||
expect(tester.getRect(find.byKey(key)), const Rect.fromLTRB(0.0, 450.0, 800.0, 600.0));
|
||||
await tester.drag(find.text('Item 5'), const Offset(0, -125));
|
||||
await tester.pumpAndSettle();
|
||||
expect(tester.getRect(find.byKey(key)), const Rect.fromLTRB(0.0, 325.0, 800.0, 600.0));
|
||||
});
|
||||
|
||||
for (TargetPlatform platform in TargetPlatform.values) {
|
||||
group('$platform Scroll Physics', () {
|
||||
debugDefaultTargetPlatformOverride = platform;
|
||||
@ -74,6 +116,23 @@ void main() {
|
||||
expect(find.text('Item 36'), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('Can be dragged down when list is shorter than full height', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(_boilerplate(null, itemCount: 30, initialChildSize: .25));
|
||||
|
||||
expect(find.text('Item 1').hitTestable(), findsOneWidget);
|
||||
expect(find.text('Item 29').hitTestable(), findsNothing);
|
||||
|
||||
await tester.drag(find.text('Item 1'), const Offset(0, -325));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('Item 1').hitTestable(), findsOneWidget);
|
||||
expect(find.text('Item 29').hitTestable(), findsOneWidget);
|
||||
|
||||
await tester.drag(find.text('Item 1'), const Offset(0, 325));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('Item 1').hitTestable(), findsOneWidget);
|
||||
expect(find.text('Item 29').hitTestable(), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('Can be dragged up and cover its container and scroll in single motion, and then dragged back down', (WidgetTester tester) async {
|
||||
int taps = 0;
|
||||
await tester.pumpWidget(_boilerplate(() => taps++));
|
||||
|
Loading…
x
Reference in New Issue
Block a user