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
ec64f93f
Unverified
Commit
ec64f93f
authored
Mar 02, 2020
by
Pierre-Louis
Committed by
GitHub
Mar 02, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Material Bottom Sheet Reveal/Dismiss animation uses a curved animation (#51122)
parent
f3018c37
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
349 additions
and
10 deletions
+349
-10
curves.dart
packages/flutter/lib/src/animation/curves.dart
+4
-0
bottom_sheet.dart
packages/flutter/lib/src/material/bottom_sheet.dart
+134
-9
curves.dart
packages/flutter/lib/src/material/curves.dart
+36
-0
scaffold.dart
packages/flutter/lib/src/material/scaffold.dart
+78
-1
bottom_sheet_test.dart
packages/flutter/test/material/bottom_sheet_test.dart
+47
-0
persistent_bottom_sheet_test.dart
...s/flutter/test/material/persistent_bottom_sheet_test.dart
+50
-0
No files found.
packages/flutter/lib/src/animation/curves.dart
View file @
ec64f93f
...
...
@@ -1657,6 +1657,10 @@ class Curves {
/// animation to finish, and the negative effects of motion are minimized.
///
/// {@animation 464 192 https://flutter.github.io/assets-for-api-docs/assets/animation/curve_fast_out_slow_in.mp4}
///
/// See also:
///
/// * [standardEasing], the name for this curve in the Material specification.
static
const
Cubic
fastOutSlowIn
=
Cubic
(
0.4
,
0.0
,
0.2
,
1.0
);
/// A cubic animation curve that starts quickly, slows down, and then ends
...
...
packages/flutter/lib/src/material/bottom_sheet.dart
View file @
ec64f93f
...
...
@@ -3,6 +3,7 @@
// found in the LICENSE file.
import
'dart:async'
;
import
'dart:ui'
show
lerpDouble
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/scheduler.dart'
;
...
...
@@ -10,16 +11,25 @@ import 'package:flutter/widgets.dart';
import
'bottom_sheet_theme.dart'
;
import
'colors.dart'
;
import
'curves.dart'
;
import
'debug.dart'
;
import
'material.dart'
;
import
'material_localizations.dart'
;
import
'scaffold.dart'
;
import
'theme.dart'
;
const
Duration
_bottomSheetDuration
=
Duration
(
milliseconds:
200
);
const
Duration
_bottomSheetEnterDuration
=
Duration
(
milliseconds:
250
);
const
Duration
_bottomSheetExitDuration
=
Duration
(
milliseconds:
200
);
const
Curve
_modalBottomSheetCurve
=
decelerateEasing
;
const
double
_minFlingVelocity
=
700.0
;
const
double
_closeProgressThreshold
=
0.5
;
typedef
BottomSheetDragStartHandler
=
void
Function
(
DragStartDetails
details
);
typedef
BottomSheetDragEndHandler
=
void
Function
(
DragEndDetails
details
,
{
bool
isClosing
,
});
/// A material design bottom sheet.
///
/// There are two kinds of bottom sheets in material design:
...
...
@@ -57,6 +67,8 @@ class BottomSheet extends StatefulWidget {
Key
key
,
this
.
animationController
,
this
.
enableDrag
=
true
,
this
.
onDragStart
,
this
.
onDragEnd
,
this
.
backgroundColor
,
this
.
elevation
,
this
.
shape
,
...
...
@@ -95,6 +107,21 @@ class BottomSheet extends StatefulWidget {
/// Default is true.
final
bool
enableDrag
;
/// Called when the user begins dragging the bottom sheet vertically, if
/// [enableDrag] is true.
///
/// Would typically be used to change the bottom sheet animation curve so
/// that it tracks the user's finger accurately.
final
BottomSheetDragStartHandler
onDragStart
;
/// Called when the user stops dragging the bottom sheet, if [enableDrag]
/// is true.
///
/// Would typically be used to reset the bottom sheet animation curve, so
/// that it animates non-linearly. Called before [onClosing] if the bottom
/// sheet is closing.
final
BottomSheetDragEndHandler
onDragEnd
;
/// The bottom sheet's background color.
///
/// Defines the bottom sheet's [Material.color].
...
...
@@ -140,7 +167,8 @@ class BottomSheet extends StatefulWidget {
/// animation controller could be provided.
static
AnimationController
createAnimationController
(
TickerProvider
vsync
)
{
return
AnimationController
(
duration:
_bottomSheetDuration
,
duration:
_bottomSheetEnterDuration
,
reverseDuration:
_bottomSheetExitDuration
,
debugLabel:
'BottomSheet'
,
vsync:
vsync
,
);
...
...
@@ -158,6 +186,12 @@ class _BottomSheetState extends State<BottomSheet> {
bool
get
_dismissUnderway
=>
widget
.
animationController
.
status
==
AnimationStatus
.
reverse
;
void
_handleDragStart
(
DragStartDetails
details
)
{
if
(
widget
.
onDragStart
!=
null
)
{
widget
.
onDragStart
(
details
);
}
}
void
_handleDragUpdate
(
DragUpdateDetails
details
)
{
assert
(
widget
.
enableDrag
);
if
(
_dismissUnderway
)
...
...
@@ -169,21 +203,33 @@ class _BottomSheetState extends State<BottomSheet> {
assert
(
widget
.
enableDrag
);
if
(
_dismissUnderway
)
return
;
bool
isClosing
=
false
;
if
(
details
.
velocity
.
pixelsPerSecond
.
dy
>
_minFlingVelocity
)
{
final
double
flingVelocity
=
-
details
.
velocity
.
pixelsPerSecond
.
dy
/
_childHeight
;
if
(
widget
.
animationController
.
value
>
0.0
)
{
widget
.
animationController
.
fling
(
velocity:
flingVelocity
);
}
if
(
flingVelocity
<
0.0
)
{
widget
.
onClosing
()
;
isClosing
=
true
;
}
}
else
if
(
widget
.
animationController
.
value
<
_closeProgressThreshold
)
{
if
(
widget
.
animationController
.
value
>
0.0
)
widget
.
animationController
.
fling
(
velocity:
-
1.0
);
widget
.
onClosing
()
;
isClosing
=
true
;
}
else
{
widget
.
animationController
.
forward
();
}
}
if
(
widget
.
onDragEnd
!=
null
)
{
widget
.
onDragEnd
(
details
,
isClosing:
isClosing
,
);
}
if
(
isClosing
)
{
widget
.
onClosing
();
}
}
bool
extentChanged
(
DraggableScrollableNotification
notification
)
{
...
...
@@ -213,6 +259,7 @@ class _BottomSheetState extends State<BottomSheet> {
),
);
return
!
widget
.
enableDrag
?
bottomSheet
:
GestureDetector
(
onVerticalDragStart:
_handleDragStart
,
onVerticalDragUpdate:
_handleDragUpdate
,
onVerticalDragEnd:
_handleDragEnd
,
child:
bottomSheet
,
...
...
@@ -283,6 +330,8 @@ class _ModalBottomSheet<T> extends StatefulWidget {
}
class
_ModalBottomSheetState
<
T
>
extends
State
<
_ModalBottomSheet
<
T
>>
{
ParametricCurve
<
double
>
animationCurve
=
_modalBottomSheetCurve
;
String
_getRouteLabel
(
MaterialLocalizations
localizations
)
{
switch
(
Theme
.
of
(
context
).
platform
)
{
case
TargetPlatform
.
iOS
:
...
...
@@ -295,6 +344,19 @@ class _ModalBottomSheetState<T> extends State<_ModalBottomSheet<T>> {
return
null
;
}
void
handleDragStart
(
DragStartDetails
details
)
{
// Allow the bottom sheet to track the user's finger accurately.
animationCurve
=
Curves
.
linear
;
}
void
handleDragEnd
(
DragEndDetails
details
,
{
bool
isClosing
})
{
// Allow the bottom sheet to animate smoothly from its current position.
animationCurve
=
_BottomSheetSuspendedCurve
(
widget
.
route
.
animation
.
value
,
curve:
_modalBottomSheetCurve
,
);
}
@override
Widget
build
(
BuildContext
context
)
{
assert
(
debugCheckHasMediaQuery
(
context
));
...
...
@@ -308,7 +370,9 @@ class _ModalBottomSheetState<T> extends State<_ModalBottomSheet<T>> {
builder:
(
BuildContext
context
,
Widget
child
)
{
// Disable the initial animation when accessible navigation is on so
// that the semantics are added to the tree at the correct time.
final
double
animationValue
=
mediaQuery
.
accessibleNavigation
?
1.0
:
widget
.
route
.
animation
.
value
;
final
double
animationValue
=
animationCurve
.
transform
(
mediaQuery
.
accessibleNavigation
?
1.0
:
widget
.
route
.
animation
.
value
);
return
Semantics
(
scopesRoute:
true
,
namesRoute:
true
,
...
...
@@ -330,6 +394,8 @@ class _ModalBottomSheetState<T> extends State<_ModalBottomSheet<T>> {
shape:
widget
.
shape
,
clipBehavior:
widget
.
clipBehavior
,
enableDrag:
widget
.
enableDrag
,
onDragStart:
handleDragStart
,
onDragEnd:
handleDragEnd
,
),
),
),
...
...
@@ -370,7 +436,10 @@ class _ModalBottomSheetRoute<T> extends PopupRoute<T> {
final
bool
enableDrag
;
@override
Duration
get
transitionDuration
=>
_bottomSheetDuration
;
Duration
get
transitionDuration
=>
_bottomSheetEnterDuration
;
@override
Duration
get
reverseTransitionDuration
=>
_bottomSheetExitDuration
;
@override
bool
get
barrierDismissible
=>
isDismissible
;
...
...
@@ -383,7 +452,6 @@ class _ModalBottomSheetRoute<T> extends PopupRoute<T> {
AnimationController
_animationController
;
@override
AnimationController
createAnimationController
()
{
assert
(
_animationController
==
null
);
...
...
@@ -415,6 +483,63 @@ class _ModalBottomSheetRoute<T> extends PopupRoute<T> {
}
}
// TODO(guidezpl): Look into making this public. A copy of this class is in scaffold.dart, for now.
/// A curve that progresses linearly until a specified [startingPoint], at which
/// point [curve] will begin. Unlike [Interval], [curve] will not start at zero,
/// but will use [startingPoint] as the Y position.
///
/// For example, if [startingPoint] is set to `0.5`, and [curve] is set to
/// [Curves.easeOut], then the bottom-left quarter of the curve will be a
/// straight line, and the top-right quarter will contain the entire contents of
/// [Curves.easeOut].
///
/// This is useful in situations where a widget must track the user's finger
/// (which requires a linear animation), and afterwards can be flung using a
/// curve specified with the [curve] argument, after the finger is released. In
/// such a case, the value of [startingPoint] would be the progress of the
/// animation at the time when the finger was released.
///
/// The [startingPoint] and [curve] arguments must not be null.
class
_BottomSheetSuspendedCurve
extends
ParametricCurve
<
double
>
{
/// Creates a suspended curve.
const
_BottomSheetSuspendedCurve
(
this
.
startingPoint
,
{
this
.
curve
=
Curves
.
easeOutCubic
,
})
:
assert
(
startingPoint
!=
null
),
assert
(
curve
!=
null
);
/// The progress value at which [curve] should begin.
///
/// This defaults to [Curves.easeOutCubic].
final
double
startingPoint
;
/// The curve to use when [startingPoint] is reached.
final
Curve
curve
;
@override
double
transform
(
double
t
)
{
assert
(
t
>=
0.0
&&
t
<=
1.0
);
assert
(
startingPoint
>=
0.0
&&
startingPoint
<=
1.0
);
if
(
t
<
startingPoint
)
{
return
t
;
}
if
(
t
==
1.0
)
{
return
t
;
}
final
double
curveProgress
=
(
t
-
startingPoint
)
/
(
1
-
startingPoint
);
final
double
transformed
=
curve
.
transform
(
curveProgress
);
return
lerpDouble
(
startingPoint
,
1
,
transformed
);
}
@override
String
toString
()
{
return
'
${describeIdentity(this)}
(
$startingPoint
,
$curve
)'
;
}
}
/// Shows a modal material design bottom sheet.
///
/// A modal bottom sheet is an alternative to a menu or a dialog and prevents
...
...
@@ -446,7 +571,7 @@ class _ModalBottomSheetRoute<T> extends PopupRoute<T> {
/// dismissed when user taps on the scrim.
///
/// The [enableDrag] parameter specifies whether the bottom sheet can be
/// dragged up and down and dismissed by swiping downards.
/// dragged up and down and dismissed by swiping down
w
ards.
///
/// The optional [backgroundColor], [elevation], [shape], and [clipBehavior]
/// parameters can be passed in to customize the appearance and behavior of
...
...
packages/flutter/lib/src/material/curves.dart
0 → 100644
View file @
ec64f93f
// 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/animation.dart'
;
// The easing curves of the Material Library
/// The standard easing curve in the Material specification.
///
/// Elements that begin and end at rest use standard easing.
/// They speed up quickly and slow down gradually, in order
/// to emphasize the end of the transition.
///
/// See also:
/// * <https://material.io/design/motion/speed.html#easing>
const
Curve
standardEasing
=
Curves
.
fastOutSlowIn
;
/// The accelerate easing curve in the Material specification.
///
/// Elements exiting a screen use acceleration easing,
/// where they start at rest and end at peak velocity.
///
/// See also:
/// * <https://material.io/design/motion/speed.html#easing>
const
Curve
accelerateEasing
=
Cubic
(
0.4
,
0.0
,
1.0
,
1.0
);
/// The decelerate easing curve in the Material specification.
///
/// Incoming elements are animated using deceleration easing,
/// which starts a transition at peak velocity (the fastest
/// point of an element’s movement) and ends at rest.
///
/// See also:
/// * <https://material.io/design/motion/speed.html#easing>
const
Curve
decelerateEasing
=
Cubic
(
0.0
,
0.0
,
0.2
,
1.0
);
packages/flutter/lib/src/material/scaffold.dart
View file @
ec64f93f
...
...
@@ -9,6 +9,7 @@
import
'dart:async'
;
import
'dart:collection'
;
import
'dart:math'
as
math
;
import
'dart:ui'
show
lerpDouble
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/rendering.dart'
;
...
...
@@ -19,6 +20,7 @@ import 'app_bar.dart';
import
'bottom_sheet.dart'
;
import
'button_bar.dart'
;
import
'colors.dart'
;
import
'curves.dart'
;
import
'divider.dart'
;
import
'drawer.dart'
;
import
'flexible_space_bar.dart'
;
...
...
@@ -40,6 +42,7 @@ import 'theme_data.dart';
const
FloatingActionButtonLocation
_kDefaultFloatingActionButtonLocation
=
FloatingActionButtonLocation
.
endFloat
;
const
FloatingActionButtonAnimator
_kDefaultFloatingActionButtonAnimator
=
FloatingActionButtonAnimator
.
scaling
;
const
Curve
_standardBottomSheetCurve
=
standardEasing
;
// When the top of the BottomSheet crosses this threshold, it will start to
// shrink the FAB and show a scrim.
const
double
_kBottomSheetDominatesPercentage
=
0.3
;
...
...
@@ -2562,6 +2565,63 @@ class ScaffoldFeatureController<T extends Widget, U> {
final
StateSetter
setState
;
}
// TODO(guidezpl): Look into making this public. A copy of this class is in bottom_sheet.dart, for now.
/// A curve that progresses linearly until a specified [startingPoint], at which
/// point [curve] will begin. Unlike [Interval], [curve] will not start at zero,
/// but will use [startingPoint] as the Y position.
///
/// For example, if [startingPoint] is set to `0.5`, and [curve] is set to
/// [Curves.easeOut], then the bottom-left quarter of the curve will be a
/// straight line, and the top-right quarter will contain the entire contents of
/// [Curves.easeOut].
///
/// This is useful in situations where a widget must track the user's finger
/// (which requires a linear animation), and afterwards can be flung using a
/// curve specified with the [curve] argument, after the finger is released. In
/// such a case, the value of [startingPoint] would be the progress of the
/// animation at the time when the finger was released.
///
/// The [startingPoint] and [curve] arguments must not be null.
class
_BottomSheetSuspendedCurve
extends
ParametricCurve
<
double
>
{
/// Creates a suspended curve.
const
_BottomSheetSuspendedCurve
(
this
.
startingPoint
,
{
this
.
curve
=
Curves
.
easeOutCubic
,
})
:
assert
(
startingPoint
!=
null
),
assert
(
curve
!=
null
);
/// The progress value at which [curve] should begin.
///
/// This defaults to [Curves.easeOutCubic].
final
double
startingPoint
;
/// The curve to use when [startingPoint] is reached.
final
Curve
curve
;
@override
double
transform
(
double
t
)
{
assert
(
t
>=
0.0
&&
t
<=
1.0
);
assert
(
startingPoint
>=
0.0
&&
startingPoint
<=
1.0
);
if
(
t
<
startingPoint
)
{
return
t
;
}
if
(
t
==
1.0
)
{
return
t
;
}
final
double
curveProgress
=
(
t
-
startingPoint
)
/
(
1
-
startingPoint
);
final
double
transformed
=
curve
.
transform
(
curveProgress
);
return
lerpDouble
(
startingPoint
,
1
,
transformed
);
}
@override
String
toString
()
{
return
'
${describeIdentity(this)}
(
$startingPoint
,
$curve
)'
;
}
}
class
_StandardBottomSheet
extends
StatefulWidget
{
const
_StandardBottomSheet
({
Key
key
,
...
...
@@ -2593,6 +2653,8 @@ class _StandardBottomSheet extends StatefulWidget {
}
class
_StandardBottomSheetState
extends
State
<
_StandardBottomSheet
>
{
ParametricCurve
<
double
>
animationCurve
=
_standardBottomSheetCurve
;
@override
void
initState
()
{
super
.
initState
();
...
...
@@ -2617,6 +2679,19 @@ class _StandardBottomSheetState extends State<_StandardBottomSheet> {
return
null
;
}
void
_handleDragStart
(
DragStartDetails
details
)
{
// Allow the bottom sheet to track the user's finger accurately.
animationCurve
=
Curves
.
linear
;
}
void
_handleDragEnd
(
DragEndDetails
details
,
{
bool
isClosing
})
{
// Allow the bottom sheet to animate smoothly from its current position.
animationCurve
=
_BottomSheetSuspendedCurve
(
widget
.
animationController
.
value
,
curve:
_standardBottomSheetCurve
,
);
}
void
_handleStatusChange
(
AnimationStatus
status
)
{
if
(
status
==
AnimationStatus
.
dismissed
&&
widget
.
onDismissed
!=
null
)
{
widget
.
onDismissed
();
...
...
@@ -2662,7 +2737,7 @@ class _StandardBottomSheetState extends State<_StandardBottomSheet> {
builder:
(
BuildContext
context
,
Widget
child
)
{
return
Align
(
alignment:
AlignmentDirectional
.
topStart
,
heightFactor:
widget
.
animationController
.
value
,
heightFactor:
animationCurve
.
transform
(
widget
.
animationController
.
value
)
,
child:
child
,
);
},
...
...
@@ -2670,6 +2745,8 @@ class _StandardBottomSheetState extends State<_StandardBottomSheet> {
BottomSheet
(
animationController:
widget
.
animationController
,
enableDrag:
widget
.
enableDrag
,
onDragStart:
_handleDragStart
,
onDragEnd:
_handleDragEnd
,
onClosing:
widget
.
onClosing
,
builder:
widget
.
builder
,
backgroundColor:
widget
.
backgroundColor
,
...
...
packages/flutter/test/material/bottom_sheet_test.dart
View file @
ec64f93f
...
...
@@ -10,6 +10,21 @@ import 'package:flutter/gestures.dart';
import
'../widgets/semantics_tester.dart'
;
void
main
(
)
{
// Pumps and ensures that the BottomSheet animates non-linearly.
Future
<
void
>
_checkNonLinearAnimation
(
WidgetTester
tester
)
async
{
final
Offset
firstPosition
=
tester
.
getCenter
(
find
.
text
(
'BottomSheet'
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
30
));
final
Offset
secondPosition
=
tester
.
getCenter
(
find
.
text
(
'BottomSheet'
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
30
));
final
Offset
thirdPosition
=
tester
.
getCenter
(
find
.
text
(
'BottomSheet'
));
final
double
dyDelta1
=
secondPosition
.
dy
-
firstPosition
.
dy
;
final
double
dyDelta2
=
thirdPosition
.
dy
-
secondPosition
.
dy
;
// If the animation were linear, these two values would be the same.
expect
(
dyDelta1
,
isNot
(
closeTo
(
dyDelta2
,
0.1
)));
}
testWidgets
(
'Tapping on a modal BottomSheet should not dismiss it'
,
(
WidgetTester
tester
)
async
{
BuildContext
savedContext
;
...
...
@@ -115,6 +130,38 @@ void main() {
expect
(
find
.
text
(
'BottomSheet'
),
findsNothing
);
});
testWidgets
(
'Verify that the BottomSheet animates non-linearly'
,
(
WidgetTester
tester
)
async
{
BuildContext
savedContext
;
await
tester
.
pumpWidget
(
MaterialApp
(
home:
Builder
(
builder:
(
BuildContext
context
)
{
savedContext
=
context
;
return
Container
();
},
),
));
await
tester
.
pump
();
expect
(
find
.
text
(
'BottomSheet'
),
findsNothing
);
showModalBottomSheet
<
void
>(
context:
savedContext
,
builder:
(
BuildContext
context
)
=>
const
Text
(
'BottomSheet'
),
);
await
tester
.
pump
();
await
_checkNonLinearAnimation
(
tester
);
await
tester
.
pumpAndSettle
();
// Tap above the bottom sheet to dismiss it.
await
tester
.
tapAt
(
const
Offset
(
20.0
,
20.0
));
await
tester
.
pump
();
await
_checkNonLinearAnimation
(
tester
);
await
tester
.
pumpAndSettle
();
// Bottom sheet dismiss animation.
expect
(
find
.
text
(
'BottomSheet'
),
findsNothing
);
});
testWidgets
(
'Tapping outside a modal BottomSheet should not dismiss it when isDismissible=false'
,
(
WidgetTester
tester
)
async
{
BuildContext
savedContext
;
...
...
packages/flutter/test/material/persistent_bottom_sheet_test.dart
View file @
ec64f93f
...
...
@@ -6,6 +6,21 @@ import 'package:flutter_test/flutter_test.dart';
import
'package:flutter/material.dart'
;
void
main
(
)
{
// Pumps and ensures that the BottomSheet animates non-linearly.
Future
<
void
>
_checkNonLinearAnimation
(
WidgetTester
tester
)
async
{
final
Offset
firstPosition
=
tester
.
getCenter
(
find
.
text
(
'One'
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
30
));
final
Offset
secondPosition
=
tester
.
getCenter
(
find
.
text
(
'One'
));
await
tester
.
pump
(
const
Duration
(
milliseconds:
30
));
final
Offset
thirdPosition
=
tester
.
getCenter
(
find
.
text
(
'One'
));
final
double
dyDelta1
=
secondPosition
.
dy
-
firstPosition
.
dy
;
final
double
dyDelta2
=
thirdPosition
.
dy
-
secondPosition
.
dy
;
// If the animation were linear, these two values would be the same.
expect
(
dyDelta1
,
isNot
(
closeTo
(
dyDelta2
,
0.1
)));
}
testWidgets
(
'Verify that a BottomSheet can be rebuilt with ScaffoldFeatureController.setState()'
,
(
WidgetTester
tester
)
async
{
final
GlobalKey
<
ScaffoldState
>
scaffoldKey
=
GlobalKey
<
ScaffoldState
>();
PersistentBottomSheetController
<
void
>
bottomSheet
;
...
...
@@ -97,6 +112,41 @@ void main() {
expect
(
find
.
text
(
'Two'
),
findsNothing
);
});
testWidgets
(
'Verify that a BottomSheet animates non-linearly'
,
(
WidgetTester
tester
)
async
{
final
GlobalKey
<
ScaffoldState
>
scaffoldKey
=
GlobalKey
<
ScaffoldState
>();
await
tester
.
pumpWidget
(
MaterialApp
(
home:
Scaffold
(
key:
scaffoldKey
,
body:
const
Center
(
child:
Text
(
'body'
)),
),
));
scaffoldKey
.
currentState
.
showBottomSheet
<
void
>((
BuildContext
context
)
{
return
ListView
(
shrinkWrap:
true
,
primary:
false
,
children:
<
Widget
>[
Container
(
height:
100.0
,
child:
const
Text
(
'One'
)),
Container
(
height:
100.0
,
child:
const
Text
(
'Two'
)),
Container
(
height:
100.0
,
child:
const
Text
(
'Three'
)),
],
);
});
await
tester
.
pump
();
await
_checkNonLinearAnimation
(
tester
);
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'Two'
),
findsOneWidget
);
await
tester
.
drag
(
find
.
text
(
'Two'
),
const
Offset
(
0.0
,
200.0
));
await
_checkNonLinearAnimation
(
tester
);
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'Two'
),
findsNothing
);
});
testWidgets
(
'Verify that a scrollControlled BottomSheet can be dismissed'
,
(
WidgetTester
tester
)
async
{
final
GlobalKey
<
ScaffoldState
>
scaffoldKey
=
GlobalKey
<
ScaffoldState
>();
...
...
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