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
fd7a72ee
Unverified
Commit
fd7a72ee
authored
Jun 26, 2020
by
Kate Lovett
Committed by
GitHub
Jun 26, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Ensure FloatingActionButtonLocations are always within safe interactive areas (#60248)
parent
a4fa61b4
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
788 additions
and
8 deletions
+788
-8
floating_action_button_location.dart
...ter/lib/src/material/floating_action_button_location.dart
+25
-7
scaffold.dart
packages/flutter/lib/src/material/scaffold.dart
+21
-0
floating_action_button_location_test.dart
...r/test/material/floating_action_button_location_test.dart
+742
-1
No files found.
packages/flutter/lib/src/material/floating_action_button_location.dart
View file @
fd7a72ee
...
...
@@ -413,14 +413,26 @@ abstract class StandardFabLocation extends FloatingActionButtonLocation {
}
/// Mixin for a "top" floating action button location, such as [FloatingActionButtonLocation.startTop].
/// Mixin for a "top" floating action button location, such as
/// [FloatingActionButtonLocation.startTop].
///
/// The [adjustment], typically [kMiniButtonOffsetAdjustment], is ignored in the
/// Y axis of "top" positions. For "top" positions, the X offset is adjusted to
/// move closer to the edge of the screen. This is so that a minified floating
/// action button appears to align with [CircleAvatar]s in the
/// [ListTile.leading] slot of a [ListTile] in a [ListView] in the
/// [Scaffold.body].
mixin
FabTopOffsetY
on
StandardFabLocation
{
/// Calculates y-offset for [FloatingActionButtonLocation]s floating over
/// the transition between the [Scaffold.appBar] and the [Scaffold.body].
@override
double
getOffsetY
(
ScaffoldPrelayoutGeometry
scaffoldGeometry
,
double
adjustment
)
{
final
double
fabHalfHeight
=
scaffoldGeometry
.
floatingActionButtonSize
.
height
/
2.0
;
return
scaffoldGeometry
.
contentTop
-
fabHalfHeight
;
if
(
scaffoldGeometry
.
contentTop
>
scaffoldGeometry
.
minViewPadding
.
top
)
{
final
double
fabHalfHeight
=
scaffoldGeometry
.
floatingActionButtonSize
.
height
/
2.0
;
return
scaffoldGeometry
.
contentTop
-
fabHalfHeight
;
}
// Otherwise, ensure we are placed within the bounds of a safe area.
return
scaffoldGeometry
.
minViewPadding
.
top
;
}
}
...
...
@@ -434,8 +446,12 @@ mixin FabFloatOffsetY on StandardFabLocation {
final
double
bottomSheetHeight
=
scaffoldGeometry
.
bottomSheetSize
.
height
;
final
double
fabHeight
=
scaffoldGeometry
.
floatingActionButtonSize
.
height
;
final
double
snackBarHeight
=
scaffoldGeometry
.
snackBarSize
.
height
;
final
double
safeMargin
=
math
.
max
(
kFloatingActionButtonMargin
,
scaffoldGeometry
.
minViewPadding
.
bottom
,
);
double
fabY
=
contentBottom
-
fabHeight
-
kFloatingActionButton
Margin
;
double
fabY
=
contentBottom
-
fabHeight
-
safe
Margin
;
if
(
snackBarHeight
>
0.0
)
fabY
=
math
.
min
(
fabY
,
contentBottom
-
snackBarHeight
-
fabHeight
-
kFloatingActionButtonMargin
);
if
(
bottomSheetHeight
>
0.0
)
...
...
@@ -453,19 +469,21 @@ mixin FabDockedOffsetY on StandardFabLocation {
@override
double
getOffsetY
(
ScaffoldPrelayoutGeometry
scaffoldGeometry
,
double
adjustment
)
{
final
double
contentBottom
=
scaffoldGeometry
.
contentBottom
;
final
double
contentMargin
=
scaffoldGeometry
.
scaffoldSize
.
height
-
contentBottom
;
final
double
bottomViewPadding
=
scaffoldGeometry
.
minViewPadding
.
bottom
;
final
double
bottomSheetHeight
=
scaffoldGeometry
.
bottomSheetSize
.
height
;
final
double
fabHeight
=
scaffoldGeometry
.
floatingActionButtonSize
.
height
;
final
double
snackBarHeight
=
scaffoldGeometry
.
snackBarSize
.
height
;
final
double
safeMargin
=
bottomViewPadding
>
contentMargin
?
bottomViewPadding
:
0.0
;
double
fabY
=
contentBottom
-
fabHeight
/
2.0
;
double
fabY
=
contentBottom
-
fabHeight
/
2.0
-
safeMargin
;
// The FAB should sit with a margin between it and the snack bar.
if
(
snackBarHeight
>
0.0
)
fabY
=
math
.
min
(
fabY
,
contentBottom
-
snackBarHeight
-
fabHeight
-
kFloatingActionButtonMargin
);
// The FAB should sit with its center in front of the top of the bottom sheet.
if
(
bottomSheetHeight
>
0.0
)
fabY
=
math
.
min
(
fabY
,
contentBottom
-
bottomSheetHeight
-
fabHeight
/
2.0
);
final
double
maxFabY
=
scaffoldGeometry
.
scaffoldSize
.
height
-
fabHeight
;
final
double
maxFabY
=
scaffoldGeometry
.
scaffoldSize
.
height
-
fabHeight
-
safeMargin
;
return
math
.
min
(
maxFabY
,
fabY
);
}
}
...
...
packages/flutter/lib/src/material/scaffold.dart
View file @
fd7a72ee
...
...
@@ -80,6 +80,7 @@ class ScaffoldPrelayoutGeometry {
@required
this
.
contentTop
,
@required
this
.
floatingActionButtonSize
,
@required
this
.
minInsets
,
@required
this
.
minViewPadding
,
@required
this
.
scaffoldSize
,
@required
this
.
snackBarSize
,
@required
this
.
textDirection
,
...
...
@@ -134,6 +135,16 @@ class ScaffoldPrelayoutGeometry {
/// will be 0.0.
final
EdgeInsets
minInsets
;
/// The minimum padding to inset interactive elements to be within a safe,
/// un-obscured space.
///
/// This value reflects the [MediaQuery.viewPadding] of the [Scaffold]'s
/// [BuildContext] when [Scaffold.resizeToAvoidBottomInset] is false or and
/// the [MediaQuery.viewInsets] > 0.0. This helps distinguish between
/// different types of obstructions on the screen, such as software keyboards
/// and physical device notches.
final
EdgeInsets
minViewPadding
;
/// The [Size] of the whole [Scaffold].
///
/// If the [Size] of the [Scaffold]'s contents is modified by values such as
...
...
@@ -389,6 +400,7 @@ class _BodyBuilder extends StatelessWidget {
class
_ScaffoldLayout
extends
MultiChildLayoutDelegate
{
_ScaffoldLayout
({
@required
this
.
minInsets
,
@required
this
.
minViewPadding
,
@required
this
.
textDirection
,
@required
this
.
geometryNotifier
,
// for floating action button
...
...
@@ -410,6 +422,7 @@ class _ScaffoldLayout extends MultiChildLayoutDelegate {
final
bool
extendBody
;
final
bool
extendBodyBehindAppBar
;
final
EdgeInsets
minInsets
;
final
EdgeInsets
minViewPadding
;
final
TextDirection
textDirection
;
final
_ScaffoldGeometryNotifier
geometryNotifier
;
...
...
@@ -536,6 +549,7 @@ class _ScaffoldLayout extends MultiChildLayoutDelegate {
scaffoldSize:
size
,
snackBarSize:
snackBarSize
,
textDirection:
textDirection
,
minViewPadding:
minViewPadding
,
);
final
Offset
currentFabOffset
=
currentFloatingActionButtonLocation
.
getOffset
(
currentGeometry
);
final
Offset
previousFabOffset
=
previousFloatingActionButtonLocation
.
getOffset
(
currentGeometry
);
...
...
@@ -2497,6 +2511,12 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
bottom:
_resizeToAvoidBottomInset
?
mediaQuery
.
viewInsets
.
bottom
:
0.0
,
);
// The minimum viewPadding for interactive elements positioned by the
// Scaffold to keep within safe interactive areas.
final
EdgeInsets
minViewPadding
=
mediaQuery
.
viewPadding
.
copyWith
(
bottom:
_resizeToAvoidBottomInset
&&
mediaQuery
.
viewInsets
.
bottom
!=
0.0
?
0.0
:
null
,
);
// extendBody locked when keyboard is open
final
bool
_extendBody
=
minInsets
.
bottom
<=
0
&&
widget
.
extendBody
;
...
...
@@ -2514,6 +2534,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
extendBody:
_extendBody
,
extendBodyBehindAppBar:
widget
.
extendBodyBehindAppBar
,
minInsets:
minInsets
,
minViewPadding:
minViewPadding
,
currentFloatingActionButtonLocation:
_floatingActionButtonLocation
,
floatingActionButtonMoveAnimationProgress:
_floatingActionButtonMoveController
.
value
,
floatingActionButtonMotionAnimator:
_floatingActionButtonAnimator
,
...
...
packages/flutter/test/material/floating_action_button_location_test.dart
View file @
fd7a72ee
...
...
@@ -609,8 +609,749 @@ void main() {
expect
(
tester
.
binding
.
transientCallbackCount
,
0
);
});
});
}
group
(
'Locations account for safe interactive areas'
,
()
{
Widget
_buildTest
(
FloatingActionButtonLocation
location
,
MediaQueryData
data
,
Key
key
,
{
bool
mini
=
false
,
bool
appBar
=
false
,
bool
bottomNavigationBar
=
false
,
bool
bottomSheet
=
false
,
bool
resizeToAvoidBottomInset
=
true
,
})
{
return
MaterialApp
(
home:
MediaQuery
(
data:
data
,
child:
Scaffold
(
resizeToAvoidBottomInset:
resizeToAvoidBottomInset
,
bottomSheet:
bottomSheet
?
Container
(
height:
100
,
child:
const
Center
(
child:
Text
(
'BottomSheet'
)),
)
:
null
,
appBar:
appBar
?
AppBar
(
title:
const
Text
(
'Demo'
))
:
null
,
bottomNavigationBar:
bottomNavigationBar
?
BottomNavigationBar
(
items:
const
<
BottomNavigationBarItem
>[
BottomNavigationBarItem
(
icon:
Icon
(
Icons
.
star
),
title:
Text
(
'0'
),
),
BottomNavigationBarItem
(
icon:
Icon
(
Icons
.
star_border
),
title:
Text
(
'1'
),
),
],
currentIndex:
0
,
)
:
null
,
floatingActionButtonLocation:
location
,
floatingActionButton:
Builder
(
builder:
(
BuildContext
context
)
{
return
FloatingActionButton
(
onPressed:
()
{
Scaffold
.
of
(
context
).
showSnackBar
(
const
SnackBar
(
content:
Text
(
'Snacky!'
)),
);
},
child:
const
Text
(
'FAB'
),
mini:
mini
,
key:
key
,
);
}
),
)
)
);
}
// Test float locations, for each (6), keyboard presented or not:
// - Default
// - with resizeToAvoidBottomInset: false
// - with BottomSheet
// - with BottomSheet and resizeToAvoidBottomInset: false
// - with SnackBar
Future
<
void
>
_runFloatTests
(
WidgetTester
tester
,
FloatingActionButtonLocation
location
,
Rect
defaultRect
,
Rect
bottomSheetRect
,
Rect
snackBarRect
,
{
bool
mini
=
false
,
})
async
{
const
double
keyboardHeight
=
200.0
;
const
double
viewPadding
=
50.0
;
final
Key
floatingActionButton
=
UniqueKey
();
// Default
await
tester
.
pumpWidget
(
_buildTest
(
location
,
const
MediaQueryData
(
viewPadding:
EdgeInsets
.
only
(
bottom:
viewPadding
)),
floatingActionButton
,
mini:
mini
,
));
expect
(
tester
.
getRect
(
find
.
byKey
(
floatingActionButton
)),
rectMoreOrLessEquals
(
defaultRect
),
);
// Present keyboard and check position, should change
await
tester
.
pumpWidget
(
_buildTest
(
location
,
const
MediaQueryData
(
viewPadding:
EdgeInsets
.
only
(
bottom:
viewPadding
),
viewInsets:
EdgeInsets
.
only
(
bottom:
keyboardHeight
),
),
floatingActionButton
,
mini:
mini
,
));
expect
(
tester
.
getRect
(
find
.
byKey
(
floatingActionButton
)),
rectMoreOrLessEquals
(
defaultRect
.
translate
(
0.0
,
viewPadding
-
keyboardHeight
-
kFloatingActionButtonMargin
,
)),
);
// With resizeToAvoidBottomInset: false
// With keyboard presented, should maintain default position
await
tester
.
pumpWidget
(
_buildTest
(
location
,
const
MediaQueryData
(
viewPadding:
EdgeInsets
.
only
(
bottom:
viewPadding
),
viewInsets:
EdgeInsets
.
only
(
bottom:
keyboardHeight
),
),
floatingActionButton
,
resizeToAvoidBottomInset:
false
,
mini:
mini
,
));
expect
(
tester
.
getRect
(
find
.
byKey
(
floatingActionButton
)),
rectMoreOrLessEquals
(
defaultRect
),
);
// BottomSheet default
await
tester
.
pumpWidget
(
_buildTest
(
location
,
const
MediaQueryData
(
viewPadding:
EdgeInsets
.
only
(
bottom:
viewPadding
)),
floatingActionButton
,
bottomSheet:
true
,
mini:
mini
,
));
expect
(
tester
.
getRect
(
find
.
byKey
(
floatingActionButton
)),
rectMoreOrLessEquals
(
bottomSheetRect
),
);
// Present keyboard and check position, bottomSheet and FAB both resize
await
tester
.
pumpWidget
(
_buildTest
(
location
,
const
MediaQueryData
(
viewPadding:
EdgeInsets
.
only
(
bottom:
viewPadding
),
viewInsets:
EdgeInsets
.
only
(
bottom:
keyboardHeight
),
),
floatingActionButton
,
bottomSheet:
true
,
mini:
mini
,
));
expect
(
tester
.
getRect
(
find
.
byKey
(
floatingActionButton
)),
rectMoreOrLessEquals
(
bottomSheetRect
.
translate
(
0.0
,
-
keyboardHeight
)),
);
// bottomSheet with resizeToAvoidBottomInset: false
// With keyboard presented, should maintain default bottomSheet position
await
tester
.
pumpWidget
(
_buildTest
(
location
,
const
MediaQueryData
(
viewPadding:
EdgeInsets
.
only
(
bottom:
viewPadding
),
viewInsets:
EdgeInsets
.
only
(
bottom:
keyboardHeight
)
),
floatingActionButton
,
bottomSheet:
true
,
resizeToAvoidBottomInset:
false
,
mini:
mini
,
));
expect
(
tester
.
getRect
(
find
.
byKey
(
floatingActionButton
)),
rectMoreOrLessEquals
(
bottomSheetRect
),
);
// SnackBar default
await
tester
.
pumpWidget
(
_buildTest
(
location
,
const
MediaQueryData
(
viewPadding:
EdgeInsets
.
only
(
bottom:
viewPadding
)),
floatingActionButton
,
mini:
mini
,
));
await
tester
.
tap
(
find
.
byKey
(
floatingActionButton
));
await
tester
.
pumpAndSettle
();
// Show SnackBar
expect
(
tester
.
getRect
(
find
.
byKey
(
floatingActionButton
)),
rectMoreOrLessEquals
(
snackBarRect
),
);
// SnackBar when resized for presented keyboard
await
tester
.
pumpWidget
(
_buildTest
(
location
,
const
MediaQueryData
(
viewPadding:
EdgeInsets
.
only
(
bottom:
viewPadding
),
viewInsets:
EdgeInsets
.
only
(
bottom:
keyboardHeight
)
),
floatingActionButton
,
mini:
mini
,
));
await
tester
.
tap
(
find
.
byKey
(
floatingActionButton
));
await
tester
.
pumpAndSettle
();
// Show SnackBar
expect
(
tester
.
getRect
(
find
.
byKey
(
floatingActionButton
)),
rectMoreOrLessEquals
(
snackBarRect
.
translate
(
0.0
,
-
keyboardHeight
)),
);
}
testWidgets
(
'startFloat'
,
(
WidgetTester
tester
)
async
{
const
Rect
defaultRect
=
Rect
.
fromLTRB
(
16.0
,
494.0
,
72.0
,
550.0
);
// Position relative to BottomSheet
const
Rect
bottomSheetRect
=
Rect
.
fromLTRB
(
16.0
,
472.0
,
72.0
,
528.0
);
// Positioned relative to SnackBar
const
Rect
snackBarRect
=
Rect
.
fromLTRB
(
16.0
,
486.0
,
72.0
,
542.0
);
await
_runFloatTests
(
tester
,
FloatingActionButtonLocation
.
startFloat
,
defaultRect
,
bottomSheetRect
,
snackBarRect
,
);
});
testWidgets
(
'miniStartFloat'
,
(
WidgetTester
tester
)
async
{
const
Rect
defaultRect
=
Rect
.
fromLTRB
(
12.0
,
506.0
,
60.0
,
554.0
);
// Positioned relative to BottomSheet
const
Rect
bottomSheetRect
=
Rect
.
fromLTRB
(
12.0
,
480.0
,
60.0
,
528.0
);
// Positioned relative to SnackBar
const
Rect
snackBarRect
=
Rect
.
fromLTRB
(
12.0
,
498.0
,
60.0
,
546.0
);
await
_runFloatTests
(
tester
,
FloatingActionButtonLocation
.
miniStartFloat
,
defaultRect
,
bottomSheetRect
,
snackBarRect
,
mini:
true
,
);
});
testWidgets
(
'centerFloat'
,
(
WidgetTester
tester
)
async
{
const
Rect
defaultRect
=
Rect
.
fromLTRB
(
372.0
,
494.0
,
428.0
,
550.0
);
// Positioned relative to BottomSheet
const
Rect
bottomSheetRect
=
Rect
.
fromLTRB
(
372.0
,
472.0
,
428.0
,
528.0
);
// Positioned relative to SnackBar
const
Rect
snackBarRect
=
Rect
.
fromLTRB
(
372.0
,
486.0
,
428.0
,
542.0
);
await
_runFloatTests
(
tester
,
FloatingActionButtonLocation
.
centerFloat
,
defaultRect
,
bottomSheetRect
,
snackBarRect
,
);
});
testWidgets
(
'miniCenterFloat'
,
(
WidgetTester
tester
)
async
{
const
Rect
defaultRect
=
Rect
.
fromLTRB
(
376.0
,
506.0
,
424.0
,
554.0
);
// Positioned relative to BottomSheet
const
Rect
bottomSheetRect
=
Rect
.
fromLTRB
(
376.0
,
480.0
,
424.0
,
528.0
);
// Positioned relative to SnackBar
const
Rect
snackBarRect
=
Rect
.
fromLTRB
(
376.0
,
498.0
,
424.0
,
546.0
);
await
_runFloatTests
(
tester
,
FloatingActionButtonLocation
.
miniCenterFloat
,
defaultRect
,
bottomSheetRect
,
snackBarRect
,
mini:
true
,
);
});
testWidgets
(
'endFloat'
,
(
WidgetTester
tester
)
async
{
const
Rect
defaultRect
=
Rect
.
fromLTRB
(
728.0
,
494.0
,
784.0
,
550.0
);
// Positioned relative to BottomSheet
const
Rect
bottomSheetRect
=
Rect
.
fromLTRB
(
728.0
,
472.0
,
784.0
,
528.0
);
// Positioned relative to SnackBar
const
Rect
snackBarRect
=
Rect
.
fromLTRB
(
728.0
,
486.0
,
784.0
,
542.0
);
await
_runFloatTests
(
tester
,
FloatingActionButtonLocation
.
endFloat
,
defaultRect
,
bottomSheetRect
,
snackBarRect
,
);
});
testWidgets
(
'miniEndFloat'
,
(
WidgetTester
tester
)
async
{
const
Rect
defaultRect
=
Rect
.
fromLTRB
(
740.0
,
506.0
,
788.0
,
554.0
);
// Positioned relative to BottomSheet
const
Rect
bottomSheetRect
=
Rect
.
fromLTRB
(
740.0
,
480.0
,
788.0
,
528.0
);
// Positioned relative to SnackBar
const
Rect
snackBarRect
=
Rect
.
fromLTRB
(
740.0
,
498.0
,
788.0
,
546.0
);
await
_runFloatTests
(
tester
,
FloatingActionButtonLocation
.
miniEndFloat
,
defaultRect
,
bottomSheetRect
,
snackBarRect
,
mini:
true
,
);
});
// Test docked locations, for each (6), keyboard presented or not:
// - Default
// - Default with resizeToAvoidBottomInset: false
// - docked with BottomNavigationBar
// - docked with BottomNavigationBar and resizeToAvoidBottomInset: false
// - docked with BottomNavigationBar & BottomSheet
// - docked with BottomNavigationBar & BottomSheet, resizeToAvoidBottomInset: false
// - with SnackBar
Future
<
void
>
_runDockedTests
(
WidgetTester
tester
,
FloatingActionButtonLocation
location
,
Rect
defaultRect
,
Rect
bottomNavigationBarRect
,
Rect
bottomSheetRect
,
Rect
snackBarRect
,
{
bool
mini
=
false
,
})
async
{
const
double
keyboardHeight
=
200.0
;
const
double
viewPadding
=
50.0
;
const
double
bottomNavHeight
=
99.0
;
final
Key
floatingActionButton
=
UniqueKey
();
final
double
fabHeight
=
mini
?
48.0
:
56.0
;
// Default
await
tester
.
pumpWidget
(
_buildTest
(
location
,
const
MediaQueryData
(
viewPadding:
EdgeInsets
.
only
(
bottom:
viewPadding
)),
floatingActionButton
,
mini:
mini
,
));
expect
(
tester
.
getRect
(
find
.
byKey
(
floatingActionButton
)),
rectMoreOrLessEquals
(
defaultRect
),
);
// Present keyboard and check position, should change
await
tester
.
pumpWidget
(
_buildTest
(
location
,
const
MediaQueryData
(
viewPadding:
EdgeInsets
.
only
(
bottom:
viewPadding
),
viewInsets:
EdgeInsets
.
only
(
bottom:
keyboardHeight
),
),
floatingActionButton
,
mini:
mini
,
));
expect
(
tester
.
getRect
(
find
.
byKey
(
floatingActionButton
)),
rectMoreOrLessEquals
(
defaultRect
.
translate
(
0.0
,
viewPadding
-
keyboardHeight
+
fabHeight
/
2.0
,
)),
);
// With resizeToAvoidBottomInset: false
// With keyboard presented, should maintain default position
await
tester
.
pumpWidget
(
_buildTest
(
location
,
const
MediaQueryData
(
viewPadding:
EdgeInsets
.
only
(
bottom:
viewPadding
),
viewInsets:
EdgeInsets
.
only
(
bottom:
keyboardHeight
),
),
floatingActionButton
,
resizeToAvoidBottomInset:
false
,
mini:
mini
,
));
expect
(
tester
.
getRect
(
find
.
byKey
(
floatingActionButton
)),
rectMoreOrLessEquals
(
defaultRect
),
);
// BottomNavigationBar default
await
tester
.
pumpWidget
(
_buildTest
(
location
,
const
MediaQueryData
(
padding:
EdgeInsets
.
only
(
bottom:
viewPadding
),
viewPadding:
EdgeInsets
.
only
(
bottom:
viewPadding
),
),
floatingActionButton
,
bottomNavigationBar:
true
,
mini:
mini
,
));
expect
(
tester
.
getRect
(
find
.
byKey
(
floatingActionButton
)),
rectMoreOrLessEquals
(
bottomNavigationBarRect
),
);
// Present keyboard and check position, FAB position changes
await
tester
.
pumpWidget
(
_buildTest
(
location
,
const
MediaQueryData
(
padding:
EdgeInsets
.
only
(
bottom:
viewPadding
),
viewPadding:
EdgeInsets
.
only
(
bottom:
viewPadding
),
viewInsets:
EdgeInsets
.
only
(
bottom:
keyboardHeight
),
),
floatingActionButton
,
bottomNavigationBar:
true
,
mini:
mini
,
));
expect
(
tester
.
getRect
(
find
.
byKey
(
floatingActionButton
)),
rectMoreOrLessEquals
(
bottomNavigationBarRect
.
translate
(
0.0
,
-
keyboardHeight
+
bottomNavHeight
,
)),
);
// BottomNavigationBar with resizeToAvoidBottomInset: false
// With keyboard presented, should maintain default position
await
tester
.
pumpWidget
(
_buildTest
(
location
,
const
MediaQueryData
(
padding:
EdgeInsets
.
only
(
bottom:
viewPadding
),
viewPadding:
EdgeInsets
.
only
(
bottom:
viewPadding
),
viewInsets:
EdgeInsets
.
only
(
bottom:
keyboardHeight
)
),
floatingActionButton
,
bottomNavigationBar:
true
,
resizeToAvoidBottomInset:
false
,
mini:
mini
,
));
expect
(
tester
.
getRect
(
find
.
byKey
(
floatingActionButton
)),
rectMoreOrLessEquals
(
bottomNavigationBarRect
),
);
// BottomNavigationBar + BottomSheet default
await
tester
.
pumpWidget
(
_buildTest
(
location
,
const
MediaQueryData
(
padding:
EdgeInsets
.
only
(
bottom:
viewPadding
),
viewPadding:
EdgeInsets
.
only
(
bottom:
viewPadding
),
),
floatingActionButton
,
bottomNavigationBar:
true
,
bottomSheet:
true
,
mini:
mini
,
));
expect
(
tester
.
getRect
(
find
.
byKey
(
floatingActionButton
)),
rectMoreOrLessEquals
(
bottomSheetRect
),
);
// Present keyboard and check position, FAB position changes
await
tester
.
pumpWidget
(
_buildTest
(
location
,
const
MediaQueryData
(
padding:
EdgeInsets
.
only
(
bottom:
viewPadding
),
viewPadding:
EdgeInsets
.
only
(
bottom:
viewPadding
),
viewInsets:
EdgeInsets
.
only
(
bottom:
keyboardHeight
),
),
floatingActionButton
,
bottomNavigationBar:
true
,
bottomSheet:
true
,
mini:
mini
,
));
expect
(
tester
.
getRect
(
find
.
byKey
(
floatingActionButton
)),
rectMoreOrLessEquals
(
bottomSheetRect
.
translate
(
0.0
,
-
keyboardHeight
+
bottomNavHeight
,
)),
);
// BottomNavigationBar + BottomSheet with resizeToAvoidBottomInset: false
// With keyboard presented, should maintain default position
await
tester
.
pumpWidget
(
_buildTest
(
location
,
const
MediaQueryData
(
padding:
EdgeInsets
.
only
(
bottom:
viewPadding
),
viewPadding:
EdgeInsets
.
only
(
bottom:
viewPadding
),
viewInsets:
EdgeInsets
.
only
(
bottom:
keyboardHeight
)
),
floatingActionButton
,
bottomNavigationBar:
true
,
bottomSheet:
true
,
resizeToAvoidBottomInset:
false
,
mini:
mini
,
));
expect
(
tester
.
getRect
(
find
.
byKey
(
floatingActionButton
)),
rectMoreOrLessEquals
(
bottomSheetRect
),
);
// SnackBar default
await
tester
.
pumpWidget
(
_buildTest
(
location
,
const
MediaQueryData
(
viewPadding:
EdgeInsets
.
only
(
bottom:
viewPadding
)),
floatingActionButton
,
mini:
mini
,
));
await
tester
.
tap
(
find
.
byKey
(
floatingActionButton
));
await
tester
.
pumpAndSettle
();
// Show SnackBar
expect
(
tester
.
getRect
(
find
.
byKey
(
floatingActionButton
)),
rectMoreOrLessEquals
(
snackBarRect
),
);
// SnackBar with BottomNavigationBar
await
tester
.
pumpWidget
(
_buildTest
(
location
,
const
MediaQueryData
(
padding:
EdgeInsets
.
only
(
bottom:
viewPadding
),
viewPadding:
EdgeInsets
.
only
(
bottom:
viewPadding
),
),
floatingActionButton
,
bottomNavigationBar:
true
,
mini:
mini
,
));
await
tester
.
tap
(
find
.
byKey
(
floatingActionButton
));
await
tester
.
pumpAndSettle
();
// Show SnackBar
expect
(
tester
.
getRect
(
find
.
byKey
(
floatingActionButton
)),
rectMoreOrLessEquals
(
snackBarRect
.
translate
(
0.0
,
-
bottomNavHeight
)),
);
// SnackBar when resized for presented keyboard
await
tester
.
pumpWidget
(
_buildTest
(
location
,
const
MediaQueryData
(
viewPadding:
EdgeInsets
.
only
(
bottom:
viewPadding
),
viewInsets:
EdgeInsets
.
only
(
bottom:
keyboardHeight
)
),
floatingActionButton
,
mini:
mini
,
));
await
tester
.
tap
(
find
.
byKey
(
floatingActionButton
));
await
tester
.
pumpAndSettle
();
// Show SnackBar
expect
(
tester
.
getRect
(
find
.
byKey
(
floatingActionButton
)),
rectMoreOrLessEquals
(
snackBarRect
.
translate
(
0.0
,
-
keyboardHeight
)),
);
}
testWidgets
(
'startDocked'
,
(
WidgetTester
tester
)
async
{
const
Rect
defaultRect
=
Rect
.
fromLTRB
(
16.0
,
494.0
,
72.0
,
550.0
);
// Positioned relative to BottomNavigationBar
const
Rect
bottomNavRect
=
Rect
.
fromLTRB
(
16.0
,
473.0
,
72.0
,
529.0
);
// Positioned relative to BottomNavigationBar & BottomSheet
const
Rect
bottomSheetRect
=
Rect
.
fromLTRB
(
16.0
,
373.0
,
72.0
,
429.0
);
// Positioned relative to SnackBar
const
Rect
snackBarRect
=
Rect
.
fromLTRB
(
16.0
,
486.0
,
72.0
,
542.0
);
await
_runDockedTests
(
tester
,
FloatingActionButtonLocation
.
startDocked
,
defaultRect
,
bottomNavRect
,
bottomSheetRect
,
snackBarRect
,
);
});
testWidgets
(
'miniStartDocked'
,
(
WidgetTester
tester
)
async
{
const
Rect
defaultRect
=
Rect
.
fromLTRB
(
12.0
,
502.0
,
60.0
,
550.0
);
// Positioned relative to BottomNavigationBar
const
Rect
bottomNavRect
=
Rect
.
fromLTRB
(
12.0
,
477.0
,
60.0
,
525.0
);
// Positioned relative to BottomNavigationBar & BottomSheet
const
Rect
bottomSheetRect
=
Rect
.
fromLTRB
(
12.0
,
377.0
,
60.0
,
425.0
);
// Positioned relative to SnackBar
const
Rect
snackBarRect
=
Rect
.
fromLTRB
(
12.0
,
494.0
,
60.0
,
542.0
);
await
_runDockedTests
(
tester
,
FloatingActionButtonLocation
.
miniStartDocked
,
defaultRect
,
bottomNavRect
,
bottomSheetRect
,
snackBarRect
,
mini:
true
,
);
});
testWidgets
(
'centerDocked'
,
(
WidgetTester
tester
)
async
{
const
Rect
defaultRect
=
Rect
.
fromLTRB
(
372.0
,
494.0
,
428.0
,
550.0
);
// Positioned relative to BottomNavigationBar
const
Rect
bottomNavRect
=
Rect
.
fromLTRB
(
372.0
,
473.0
,
428.0
,
529.0
);
// Positioned relative to BottomNavigationBar & BottomSheet
const
Rect
bottomSheetRect
=
Rect
.
fromLTRB
(
372.0
,
373.0
,
428.0
,
429.0
);
// Positioned relative to SnackBar
const
Rect
snackBarRect
=
Rect
.
fromLTRB
(
372.0
,
486.0
,
428.0
,
542.0
);
await
_runDockedTests
(
tester
,
FloatingActionButtonLocation
.
centerDocked
,
defaultRect
,
bottomNavRect
,
bottomSheetRect
,
snackBarRect
,
);
});
testWidgets
(
'miniCenterDocked'
,
(
WidgetTester
tester
)
async
{
const
Rect
defaultRect
=
Rect
.
fromLTRB
(
376.0
,
502.0
,
424.0
,
550.0
);
// Positioned relative to BottomNavigationBar
const
Rect
bottomNavRect
=
Rect
.
fromLTRB
(
376.0
,
477.0
,
424.0
,
525.0
);
// Positioned relative to BottomNavigationBar & BottomSheet
const
Rect
bottomSheetRect
=
Rect
.
fromLTRB
(
376.0
,
377.0
,
424.0
,
425.0
);
// Positioned relative to SnackBar
const
Rect
snackBarRect
=
Rect
.
fromLTRB
(
376.0
,
494.0
,
424.0
,
542.0
);
await
_runDockedTests
(
tester
,
FloatingActionButtonLocation
.
miniCenterDocked
,
defaultRect
,
bottomNavRect
,
bottomSheetRect
,
snackBarRect
,
mini:
true
,
);
});
testWidgets
(
'endDocked'
,
(
WidgetTester
tester
)
async
{
const
Rect
defaultRect
=
Rect
.
fromLTRB
(
728.0
,
494.0
,
784.0
,
550.0
);
// Positioned relative to BottomNavigationBar
const
Rect
bottomNavRect
=
Rect
.
fromLTRB
(
728.0
,
473.0
,
784.0
,
529.0
);
// Positioned relative to BottomNavigationBar & BottomSheet
const
Rect
bottomSheetRect
=
Rect
.
fromLTRB
(
728.0
,
373.0
,
784.0
,
429.0
);
// Positioned relative to SnackBar
const
Rect
snackBarRect
=
Rect
.
fromLTRB
(
728.0
,
486.0
,
784.0
,
542.0
);
await
_runDockedTests
(
tester
,
FloatingActionButtonLocation
.
endDocked
,
defaultRect
,
bottomNavRect
,
bottomSheetRect
,
snackBarRect
,
);
});
testWidgets
(
'miniEndDocked'
,
(
WidgetTester
tester
)
async
{
const
Rect
defaultRect
=
Rect
.
fromLTRB
(
740.0
,
502.0
,
788.0
,
550.0
);
// Positioned relative to BottomNavigationBar
const
Rect
bottomNavRect
=
Rect
.
fromLTRB
(
740.0
,
477.0
,
788.0
,
525.0
);
// Positioned relative to BottomNavigationBar & BottomSheet
const
Rect
bottomSheetRect
=
Rect
.
fromLTRB
(
740.0
,
377.0
,
788.0
,
425.0
);
// Positioned relative to SnackBar
const
Rect
snackBarRect
=
Rect
.
fromLTRB
(
740.0
,
494.0
,
788.0
,
542.0
);
await
_runDockedTests
(
tester
,
FloatingActionButtonLocation
.
miniEndDocked
,
defaultRect
,
bottomNavRect
,
bottomSheetRect
,
snackBarRect
,
mini:
true
,
);
});
// Test top locations, for each (6):
// - Default
// - with an AppBar
Future
<
void
>
_runTopTests
(
WidgetTester
tester
,
FloatingActionButtonLocation
location
,
Rect
defaultRect
,
Rect
appBarRect
,
{
bool
mini
=
false
,
})
async
{
const
double
viewPadding
=
50.0
;
final
Key
floatingActionButton
=
UniqueKey
();
// Default
await
tester
.
pumpWidget
(
_buildTest
(
location
,
const
MediaQueryData
(
viewPadding:
EdgeInsets
.
only
(
top:
viewPadding
)),
floatingActionButton
,
mini:
mini
,
));
expect
(
tester
.
getRect
(
find
.
byKey
(
floatingActionButton
)),
rectMoreOrLessEquals
(
defaultRect
),
);
// AppBar default
await
tester
.
pumpWidget
(
_buildTest
(
location
,
const
MediaQueryData
(
viewPadding:
EdgeInsets
.
only
(
top:
viewPadding
)),
floatingActionButton
,
appBar:
true
,
mini:
mini
,
));
expect
(
tester
.
getRect
(
find
.
byKey
(
floatingActionButton
)),
rectMoreOrLessEquals
(
appBarRect
),
);
}
testWidgets
(
'startTop'
,
(
WidgetTester
tester
)
async
{
const
Rect
defaultRect
=
Rect
.
fromLTRB
(
16.0
,
50.0
,
72.0
,
106.0
);
// Positioned relative to AppBar
const
Rect
appBarRect
=
Rect
.
fromLTRB
(
16.0
,
28.0
,
72.0
,
84.0
);
await
_runTopTests
(
tester
,
FloatingActionButtonLocation
.
startTop
,
defaultRect
,
appBarRect
,
);
});
testWidgets
(
'miniStartTop'
,
(
WidgetTester
tester
)
async
{
const
Rect
defaultRect
=
Rect
.
fromLTRB
(
12.0
,
50.0
,
60.0
,
98.0
);
// Positioned relative to AppBar
const
Rect
appBarRect
=
Rect
.
fromLTRB
(
12.0
,
32.0
,
60.0
,
80.0
);
await
_runTopTests
(
tester
,
FloatingActionButtonLocation
.
miniStartTop
,
defaultRect
,
appBarRect
,
mini:
true
,
);
});
testWidgets
(
'centerTop'
,
(
WidgetTester
tester
)
async
{
const
Rect
defaultRect
=
Rect
.
fromLTRB
(
372.0
,
50.0
,
428.0
,
106.0
);
// Positioned relative to AppBar
const
Rect
appBarRect
=
Rect
.
fromLTRB
(
372.0
,
28.0
,
428.0
,
84.0
);
await
_runTopTests
(
tester
,
FloatingActionButtonLocation
.
centerTop
,
defaultRect
,
appBarRect
,
);
});
testWidgets
(
'miniCenterTop'
,
(
WidgetTester
tester
)
async
{
const
Rect
defaultRect
=
Rect
.
fromLTRB
(
376.0
,
50.0
,
424.0
,
98.0
);
// Positioned relative to AppBar
const
Rect
appBarRect
=
Rect
.
fromLTRB
(
376.0
,
32.0
,
424.0
,
80.0
);
await
_runTopTests
(
tester
,
FloatingActionButtonLocation
.
miniCenterTop
,
defaultRect
,
appBarRect
,
mini:
true
,
);
});
testWidgets
(
'endTop'
,
(
WidgetTester
tester
)
async
{
const
Rect
defaultRect
=
Rect
.
fromLTRB
(
728.0
,
50.0
,
784.0
,
106.0
);
// Positioned relative to AppBar
const
Rect
appBarRect
=
Rect
.
fromLTRB
(
728.0
,
28.0
,
784.0
,
84.0
);
await
_runTopTests
(
tester
,
FloatingActionButtonLocation
.
endTop
,
defaultRect
,
appBarRect
,
);
});
testWidgets
(
'miniEndTop'
,
(
WidgetTester
tester
)
async
{
const
Rect
defaultRect
=
Rect
.
fromLTRB
(
740.0
,
50.0
,
788.0
,
98.0
);
// Positioned relative to AppBar
const
Rect
appBarRect
=
Rect
.
fromLTRB
(
740.0
,
32.0
,
788.0
,
80.0
);
await
_runTopTests
(
tester
,
FloatingActionButtonLocation
.
miniEndTop
,
defaultRect
,
appBarRect
,
mini:
true
,
);
});
});
}
class
_GeometryListener
extends
StatefulWidget
{
@override
...
...
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