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
989a2f24
Unverified
Commit
989a2f24
authored
Apr 13, 2021
by
Hans Muller
Committed by
GitHub
Apr 13, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Revert "Added MaterialState.scrolledUnder and support in AppBar.backgroundColor (#79999)" (#80380)
This reverts commit
17870d5d
.
parent
c0c231be
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
29 additions
and
583 deletions
+29
-583
app_bar.dart
packages/flutter/lib/src/material/app_bar.dart
+4
-56
flexible_space_bar.dart
packages/flutter/lib/src/material/flexible_space_bar.dart
+3
-19
material_state.dart
packages/flutter/lib/src/material/material_state.dart
+1
-7
scaffold.dart
packages/flutter/lib/src/material/scaffold.dart
+21
-23
scroll_notification_observer.dart
...flutter/lib/src/widgets/scroll_notification_observer.dart
+0
-174
widgets.dart
packages/flutter/lib/widgets.dart
+0
-1
app_bar_test.dart
packages/flutter/test/material/app_bar_test.dart
+0
-235
scaffold_test.dart
packages/flutter/test/material/scaffold_test.dart
+0
-3
scroll_notification_test.dart
packages/flutter/test/widgets/scroll_notification_test.dart
+0
-65
No files found.
packages/flutter/lib/src/material/app_bar.dart
View file @
989a2f24
...
...
@@ -19,7 +19,6 @@ import 'icon_button.dart';
import
'icons.dart'
;
import
'material.dart'
;
import
'material_localizations.dart'
;
import
'material_state.dart'
;
import
'scaffold.dart'
;
import
'tabs.dart'
;
import
'text_theme.dart'
;
...
...
@@ -703,28 +702,6 @@ class _AppBarState extends State<AppBar> {
static
const
double
_defaultElevation
=
4.0
;
static
const
Color
_defaultShadowColor
=
Color
(
0xFF000000
);
ScrollNotificationObserverState
?
_scrollNotificationObserver
;
bool
_scrolledUnder
=
false
;
@override
void
didChangeDependencies
()
{
super
.
didChangeDependencies
();
if
(
_scrollNotificationObserver
!=
null
)
_scrollNotificationObserver
!.
removeListener
(
_handleScrollNotification
);
_scrollNotificationObserver
=
ScrollNotificationObserver
.
of
(
context
);
if
(
_scrollNotificationObserver
!=
null
)
_scrollNotificationObserver
!.
addListener
(
_handleScrollNotification
);
}
@override
void
dispose
()
{
if
(
_scrollNotificationObserver
!=
null
)
{
_scrollNotificationObserver
!.
removeListener
(
_handleScrollNotification
);
_scrollNotificationObserver
=
null
;
}
super
.
dispose
();
}
void
_handleDrawerButton
()
{
Scaffold
.
of
(
context
).
openDrawer
();
}
...
...
@@ -733,22 +710,6 @@ class _AppBarState extends State<AppBar> {
Scaffold
.
of
(
context
).
openEndDrawer
();
}
void
_handleScrollNotification
(
ScrollNotification
notification
)
{
final
bool
oldScrolledUnder
=
_scrolledUnder
;
_scrolledUnder
=
notification
.
depth
==
0
&&
notification
.
metrics
.
extentBefore
>
0
;
if
(
_scrolledUnder
!=
oldScrolledUnder
)
{
setState
(()
{
// React to a change in MaterialState.scrolledUnder
});
}
}
Color
_resolveColor
(
Set
<
MaterialState
>
states
,
Color
?
widgetColor
,
Color
?
themeColor
,
Color
defaultColor
)
{
return
MaterialStateProperty
.
resolveAs
<
Color
?>(
widgetColor
,
states
)
??
MaterialStateProperty
.
resolveAs
<
Color
?>(
themeColor
,
states
)
??
MaterialStateProperty
.
resolveAs
<
Color
>(
defaultColor
,
states
);
}
@override
Widget
build
(
BuildContext
context
)
{
assert
(!
widget
.
primary
||
debugCheckHasMediaQuery
(
context
));
...
...
@@ -759,11 +720,6 @@ class _AppBarState extends State<AppBar> {
final
ScaffoldState
?
scaffold
=
Scaffold
.
maybeOf
(
context
);
final
ModalRoute
<
dynamic
>?
parentRoute
=
ModalRoute
.
of
(
context
);
final
FlexibleSpaceBarSettings
?
settings
=
context
.
dependOnInheritedWidgetOfExactType
<
FlexibleSpaceBarSettings
>();
final
Set
<
MaterialState
>
states
=
<
MaterialState
>{
if
(
settings
?.
isScrolledUnder
??
_scrolledUnder
)
MaterialState
.
scrolledUnder
,
};
final
bool
hasDrawer
=
scaffold
?.
hasDrawer
??
false
;
final
bool
hasEndDrawer
=
scaffold
?.
hasEndDrawer
??
false
;
final
bool
canPop
=
parentRoute
?.
canPop
??
false
;
...
...
@@ -776,11 +732,9 @@ class _AppBarState extends State<AppBar> {
?
widget
.
backgroundColor
??
appBarTheme
.
backgroundColor
??
theme
.
primaryColor
:
_resolveColor
(
states
,
widget
.
backgroundColor
,
appBarTheme
.
backgroundColor
,
colorScheme
.
brightness
==
Brightness
.
dark
?
colorScheme
.
surface
:
colorScheme
.
primary
);
:
widget
.
backgroundColor
??
appBarTheme
.
backgroundColor
??
(
colorScheme
.
brightness
==
Brightness
.
dark
?
colorScheme
.
surface
:
colorScheme
.
primary
);
final
Color
foregroundColor
=
widget
.
foregroundColor
??
appBarTheme
.
foregroundColor
...
...
@@ -1182,7 +1136,6 @@ class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
final
double
extraToolbarHeight
=
math
.
max
(
minExtent
-
_bottomHeight
-
topPadding
-
(
toolbarHeight
??
kToolbarHeight
),
0.0
);
final
double
visibleToolbarHeight
=
visibleMainHeight
-
_bottomHeight
-
extraToolbarHeight
;
final
bool
isScrolledUnder
=
overlapsContent
||
(
pinned
&&
shrinkOffset
>
maxExtent
-
minExtent
);
final
bool
isPinnedWithOpacityFade
=
pinned
&&
floating
&&
bottom
!=
null
&&
extraToolbarHeight
==
0.0
;
final
double
toolbarOpacity
=
!
pinned
||
isPinnedWithOpacityFade
?
(
visibleToolbarHeight
/
(
toolbarHeight
??
kToolbarHeight
)).
clamp
(
0.0
,
1.0
)
...
...
@@ -1193,7 +1146,6 @@ class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
maxExtent:
maxExtent
,
currentExtent:
math
.
max
(
minExtent
,
maxExtent
-
shrinkOffset
),
toolbarOpacity:
toolbarOpacity
,
isScrolledUnder:
isScrolledUnder
,
child:
AppBar
(
leading:
leading
,
automaticallyImplyLeading:
automaticallyImplyLeading
,
...
...
@@ -1203,7 +1155,7 @@ class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
?
Semantics
(
child:
flexibleSpace
,
header:
true
)
:
flexibleSpace
,
bottom:
bottom
,
elevation:
forceElevated
||
isScrolledUnder
?
elevation
:
0.0
,
elevation:
forceElevated
||
overlapsContent
||
(
pinned
&&
shrinkOffset
>
maxExtent
-
minExtent
)
?
elevation
:
0.0
,
shadowColor:
shadowColor
,
backgroundColor:
backgroundColor
,
foregroundColor:
foregroundColor
,
...
...
@@ -1562,10 +1514,6 @@ class SliverAppBar extends StatefulWidget {
/// {@macro flutter.material.appbar.backgroundColor}
///
/// This property is used to configure an [AppBar].
///
/// If this color is a [MaterialStateColor] it will be resolved against
/// [MaterialState.scrolledUnder] when the content of the app's
/// primary scrollable overlaps the app bar.
final
Color
?
backgroundColor
;
/// {@macro flutter.material.appbar.foregroundColor}
...
...
packages/flutter/lib/src/material/flexible_space_bar.dart
View file @
989a2f24
...
...
@@ -210,9 +210,8 @@ class FlexibleSpaceBar extends StatefulWidget {
/// height of the resulting [FlexibleSpaceBar] when fully expanded.
/// `currentExtent` sets the scale of the [FlexibleSpaceBar.background] and
/// [FlexibleSpaceBar.title] widgets of [FlexibleSpaceBar] upon
/// initialization. `scrolledUnder` is true if the the [FlexibleSpaceBar]
/// overlaps the app's primary scrollable, false if it does not, and null
/// if the caller has not determined as much.
/// initialization.
///
/// See also:
///
/// * [FlexibleSpaceBarSettings] which creates a settings object that can be
...
...
@@ -221,7 +220,6 @@ class FlexibleSpaceBar extends StatefulWidget {
double
?
toolbarOpacity
,
double
?
minExtent
,
double
?
maxExtent
,
bool
?
isScrolledUnder
,
required
double
currentExtent
,
required
Widget
child
,
})
{
...
...
@@ -230,7 +228,6 @@ class FlexibleSpaceBar extends StatefulWidget {
toolbarOpacity:
toolbarOpacity
??
1.0
,
minExtent:
minExtent
??
currentExtent
,
maxExtent:
maxExtent
??
currentExtent
,
isScrolledUnder:
isScrolledUnder
,
currentExtent:
currentExtent
,
child:
child
,
);
...
...
@@ -444,7 +441,6 @@ class FlexibleSpaceBarSettings extends InheritedWidget {
required
this
.
maxExtent
,
required
this
.
currentExtent
,
required
Widget
child
,
this
.
isScrolledUnder
,
})
:
assert
(
toolbarOpacity
!=
null
),
assert
(
minExtent
!=
null
&&
minExtent
>=
0
),
assert
(
maxExtent
!=
null
&&
maxExtent
>=
0
),
...
...
@@ -469,23 +465,11 @@ class FlexibleSpaceBarSettings extends InheritedWidget {
/// these elements upon initialization.
final
double
currentExtent
;
/// True if the FlexibleSpaceBar overlaps the primary scrollable's contents.
///
/// This value is used by the [AppBar] to resolve
/// [AppBar.backgroundColor] against [MaterialState.scrolledUnder],
/// i.e. to enable apps to specify different colors when content
/// has been scrolled up and behind the app bar.
///
/// Null if the caller hasn't determined if the FlexibleSpaceBar
/// overlaps the primary scrollable's contents.
final
bool
?
isScrolledUnder
;
@override
bool
updateShouldNotify
(
FlexibleSpaceBarSettings
oldWidget
)
{
return
toolbarOpacity
!=
oldWidget
.
toolbarOpacity
||
minExtent
!=
oldWidget
.
minExtent
||
maxExtent
!=
oldWidget
.
maxExtent
||
currentExtent
!=
oldWidget
.
currentExtent
||
isScrolledUnder
!=
oldWidget
.
isScrolledUnder
;
||
currentExtent
!=
oldWidget
.
currentExtent
;
}
}
packages/flutter/lib/src/material/material_state.dart
View file @
989a2f24
...
...
@@ -63,13 +63,7 @@ enum MaterialState {
/// See: https://material.io/design/interaction/states.html#selected.
selected
,
/// The state when this widget overlaps the content of a scrollable below.
///
/// Used by [AppBar] to indicate that the primary scrollable's
/// content has scrolled up and behind the app bar.
scrolledUnder
,
/// The state when this widget is disabled and cannot be interacted with.
/// The state when this widget disabled and can not be interacted with.
///
/// Disabled widgets should not respond to hover, focus, press, or drag
/// interactions.
...
...
packages/flutter/lib/src/material/scaffold.dart
View file @
989a2f24
...
...
@@ -3238,29 +3238,27 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin, Resto
return
_ScaffoldScope
(
hasDrawer:
hasDrawer
,
geometryNotifier:
_geometryNotifier
,
child:
ScrollNotificationObserver
(
child:
Material
(
color:
widget
.
backgroundColor
??
themeData
.
scaffoldBackgroundColor
,
child:
AnimatedBuilder
(
animation:
_floatingActionButtonMoveController
,
builder:
(
BuildContext
context
,
Widget
?
child
)
{
return
CustomMultiChildLayout
(
children:
children
,
delegate:
_ScaffoldLayout
(
extendBody:
_extendBody
,
extendBodyBehindAppBar:
widget
.
extendBodyBehindAppBar
,
minInsets:
minInsets
,
minViewPadding:
minViewPadding
,
currentFloatingActionButtonLocation:
_floatingActionButtonLocation
!,
floatingActionButtonMoveAnimationProgress:
_floatingActionButtonMoveController
.
value
,
floatingActionButtonMotionAnimator:
_floatingActionButtonAnimator
,
geometryNotifier:
_geometryNotifier
,
previousFloatingActionButtonLocation:
_previousFloatingActionButtonLocation
!,
textDirection:
textDirection
,
isSnackBarFloating:
isSnackBarFloating
,
snackBarWidth:
snackBarWidth
,
),
);
}),
),
child:
Material
(
color:
widget
.
backgroundColor
??
themeData
.
scaffoldBackgroundColor
,
child:
AnimatedBuilder
(
animation:
_floatingActionButtonMoveController
,
builder:
(
BuildContext
context
,
Widget
?
child
)
{
return
CustomMultiChildLayout
(
children:
children
,
delegate:
_ScaffoldLayout
(
extendBody:
_extendBody
,
extendBodyBehindAppBar:
widget
.
extendBodyBehindAppBar
,
minInsets:
minInsets
,
minViewPadding:
minViewPadding
,
currentFloatingActionButtonLocation:
_floatingActionButtonLocation
!,
floatingActionButtonMoveAnimationProgress:
_floatingActionButtonMoveController
.
value
,
floatingActionButtonMotionAnimator:
_floatingActionButtonAnimator
,
geometryNotifier:
_geometryNotifier
,
previousFloatingActionButtonLocation:
_previousFloatingActionButtonLocation
!,
textDirection:
textDirection
,
isSnackBarFloating:
isSnackBarFloating
,
snackBarWidth:
snackBarWidth
,
),
);
}),
),
);
}
...
...
packages/flutter/lib/src/widgets/scroll_notification_observer.dart
deleted
100644 → 0
View file @
c0c231be
// 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
'dart:collection'
;
import
'package:flutter/foundation.dart'
;
import
'framework.dart'
;
import
'notification_listener.dart'
;
import
'scroll_notification.dart'
;
/// A [ScrollNotification] listener for [ScrollNotificationObserver].
///
/// [ScrollNotificationObserver] is similar to
/// [NotificationListener]. It supports a listener list instead of
/// just a single listener and its listeners run unconditionally, they
/// do not require a gating boolean return value.
typedef
ScrollNotificationCallback
=
void
Function
(
ScrollNotification
notification
);
class
_ScrollNotificationObserverScope
extends
InheritedWidget
{
const
_ScrollNotificationObserverScope
({
Key
?
key
,
required
Widget
child
,
required
ScrollNotificationObserverState
scrollNotificationObserverState
,
})
:
_scrollNotificationObserverState
=
scrollNotificationObserverState
,
super
(
key:
key
,
child:
child
);
final
ScrollNotificationObserverState
_scrollNotificationObserverState
;
@override
bool
updateShouldNotify
(
_ScrollNotificationObserverScope
old
)
=>
_scrollNotificationObserverState
!=
old
.
_scrollNotificationObserverState
;
}
class
_ListenerEntry
extends
LinkedListEntry
<
_ListenerEntry
>
{
_ListenerEntry
(
this
.
listener
);
final
ScrollNotificationCallback
listener
;
}
/// Notifies its listeners when a descendant scrolls.
///
/// To add a listener to a [ScrollNotificationObserver] ancestor:
/// ```dart
/// void listener(ScrollNotification notification) {
/// // Do something, maybe setState()
/// }
/// ScrollNotificationObserver.of(context).addListener(listener)
/// ```
///
/// To remove the listener from a [ScrollNotificationObserver] ancestor:
/// ```dart
/// ScrollNotificationObserver.of(context).removeListener(listener);
///```
///
/// Stateful widgets that share an ancestor [ScrollNotificationObserver] typically
/// add a listener in [State.didChangeDependencies] (removing the old one
/// if necessary) and remove the listener in their [State.dispose] method.
///
/// This widget is similar to [NotificationListener]. It supports
/// a listener list instead of just a single listener and its listeners
/// run unconditionally, they do not require a gating boolean return value.
class
ScrollNotificationObserver
extends
StatefulWidget
{
/// Create a [ScrollNotificationObserver].
///
/// The [child] parameter must not be null.
const
ScrollNotificationObserver
({
Key
?
key
,
required
this
.
child
,
})
:
assert
(
child
!=
null
),
super
(
key:
key
);
/// The subtree below this widget.
final
Widget
child
;
/// The closest instance of this class that encloses the given context.
///
/// If there is no enclosing [ScrollNotificationObserver] widget, then null is returned.
static
ScrollNotificationObserverState
?
of
(
BuildContext
context
)
{
return
context
.
dependOnInheritedWidgetOfExactType
<
_ScrollNotificationObserverScope
>()?.
_scrollNotificationObserverState
;
}
@override
ScrollNotificationObserverState
createState
()
=>
ScrollNotificationObserverState
();
}
/// The listener list state for a [ScrollNotificationObserver] returned by
/// [ScrollNotificationObserver.of].
///
/// [ScrollNotificationObserver] is similar to
/// [NotificationListener]. It supports a listener list instead of
/// just a single listener and its listeners run unconditionally, they
/// do not require a gating boolean return value.
class
ScrollNotificationObserverState
extends
State
<
ScrollNotificationObserver
>
{
LinkedList
<
_ListenerEntry
>?
_listeners
=
LinkedList
<
_ListenerEntry
>();
bool
_debugAssertNotDisposed
()
{
assert
(()
{
if
(
_listeners
==
null
)
{
throw
FlutterError
(
'A
$runtimeType
was used after being disposed.
\n
'
'Once you have called dispose() on a
$runtimeType
, it can no longer be used.'
,
);
}
return
true
;
}());
return
true
;
}
/// Add a [ScrollNotificationCallback] that will be called each time
/// a descendant scrolls.
void
addListener
(
ScrollNotificationCallback
listener
)
{
assert
(
_debugAssertNotDisposed
());
_listeners
!.
add
(
_ListenerEntry
(
listener
));
}
/// Remove the specified [ScrollNotificationCallback].
void
removeListener
(
ScrollNotificationCallback
listener
)
{
assert
(
_debugAssertNotDisposed
());
for
(
final
_ListenerEntry
entry
in
_listeners
!)
{
if
(
entry
.
listener
==
listener
)
{
entry
.
unlink
();
return
;
}
}
}
void
_notifyListeners
(
ScrollNotification
notification
)
{
assert
(
_debugAssertNotDisposed
());
if
(
_listeners
!.
isEmpty
)
return
;
final
List
<
_ListenerEntry
>
localListeners
=
List
<
_ListenerEntry
>.
from
(
_listeners
!);
for
(
final
_ListenerEntry
entry
in
localListeners
)
{
try
{
if
(
entry
.
list
!=
null
)
entry
.
listener
(
notification
);
}
catch
(
exception
,
stack
)
{
FlutterError
.
reportError
(
FlutterErrorDetails
(
exception:
exception
,
stack:
stack
,
library
:
'widget library'
,
context:
ErrorDescription
(
'while dispatching notifications for
$runtimeType
'
),
informationCollector:
()
sync
*
{
yield
DiagnosticsProperty
<
ScrollNotificationObserverState
>(
'The
$runtimeType
sending notification was'
,
this
,
style:
DiagnosticsTreeStyle
.
errorProperty
,
);
},
));
}
}
}
@override
Widget
build
(
BuildContext
context
)
{
return
NotificationListener
<
ScrollNotification
>(
onNotification:
(
ScrollNotification
notification
)
{
_notifyListeners
(
notification
);
return
false
;
},
child:
_ScrollNotificationObserverScope
(
scrollNotificationObserverState:
this
,
child:
widget
.
child
,
),
);
}
@override
void
dispose
()
{
assert
(
_debugAssertNotDisposed
());
_listeners
=
null
;
super
.
dispose
();
}
}
packages/flutter/lib/widgets.dart
View file @
989a2f24
...
...
@@ -98,7 +98,6 @@ export 'src/widgets/scroll_context.dart';
export
'src/widgets/scroll_controller.dart'
;
export
'src/widgets/scroll_metrics.dart'
;
export
'src/widgets/scroll_notification.dart'
;
export
'src/widgets/scroll_notification_observer.dart'
;
export
'src/widgets/scroll_physics.dart'
;
export
'src/widgets/scroll_position.dart'
;
export
'src/widgets/scroll_position_with_single_context.dart'
;
...
...
packages/flutter/test/material/app_bar_test.dart
View file @
989a2f24
...
...
@@ -2518,239 +2518,4 @@ void main() {
expect
(
actionIconTheme
.
color
,
foregroundColor
);
});
testWidgets
(
'SliverAppBar.backgroundColor MaterialStateColor scrolledUnder'
,
(
WidgetTester
tester
)
async
{
const
double
collapsedHeight
=
kToolbarHeight
;
const
double
expandedHeight
=
200.0
;
const
Color
scrolledColor
=
Color
(
0xff00ff00
);
const
Color
defaultColor
=
Color
(
0xff0000ff
);
await
tester
.
pumpWidget
(
MaterialApp
(
home:
Scaffold
(
body:
CustomScrollView
(
slivers:
<
Widget
>[
SliverAppBar
(
backwardsCompatibility:
false
,
elevation:
0
,
backgroundColor:
MaterialStateColor
.
resolveWith
((
Set
<
MaterialState
>
states
)
{
return
states
.
contains
(
MaterialState
.
scrolledUnder
)
?
scrolledColor
:
defaultColor
;
}),
expandedHeight:
expandedHeight
,
pinned:
true
,
),
SliverList
(
delegate:
SliverChildListDelegate
(
<
Widget
>[
Container
(
height:
1200.0
,
color:
Colors
.
teal
),
],
),
),
],
),
),
),
);
Finder
findAppBarMaterial
()
{
return
find
.
descendant
(
of:
find
.
byType
(
AppBar
),
matching:
find
.
byType
(
Material
));
}
Color
?
getAppBarBackgroundColor
()
{
return
tester
.
widget
<
Material
>(
findAppBarMaterial
()).
color
;
}
expect
(
getAppBarBackgroundColor
(),
defaultColor
);
expect
(
tester
.
getSize
(
findAppBarMaterial
()).
height
,
expandedHeight
);
TestGesture
gesture
=
await
tester
.
startGesture
(
const
Offset
(
50.0
,
400.0
));
await
gesture
.
moveBy
(
const
Offset
(
0.0
,
-
expandedHeight
));
await
gesture
.
up
();
await
tester
.
pumpAndSettle
();
expect
(
getAppBarBackgroundColor
(),
scrolledColor
);
expect
(
tester
.
getSize
(
findAppBarMaterial
()).
height
,
collapsedHeight
);
gesture
=
await
tester
.
startGesture
(
const
Offset
(
50.0
,
300.0
));
await
gesture
.
moveBy
(
const
Offset
(
0.0
,
expandedHeight
));
await
gesture
.
up
();
await
tester
.
pumpAndSettle
();
expect
(
getAppBarBackgroundColor
(),
defaultColor
);
expect
(
tester
.
getSize
(
findAppBarMaterial
()).
height
,
expandedHeight
);
});
testWidgets
(
'SliverAppBar.backgroundColor with FlexibleSpace MaterialStateColor scrolledUnder'
,
(
WidgetTester
tester
)
async
{
const
double
collapsedHeight
=
kToolbarHeight
;
const
double
expandedHeight
=
200.0
;
const
Color
scrolledColor
=
Color
(
0xff00ff00
);
const
Color
defaultColor
=
Color
(
0xff0000ff
);
await
tester
.
pumpWidget
(
MaterialApp
(
home:
Scaffold
(
body:
CustomScrollView
(
slivers:
<
Widget
>[
SliverAppBar
(
backwardsCompatibility:
false
,
elevation:
0
,
backgroundColor:
MaterialStateColor
.
resolveWith
((
Set
<
MaterialState
>
states
)
{
return
states
.
contains
(
MaterialState
.
scrolledUnder
)
?
scrolledColor
:
defaultColor
;
}),
expandedHeight:
expandedHeight
,
pinned:
true
,
flexibleSpace:
const
FlexibleSpaceBar
(
title:
Text
(
'SliverAppBar'
),
),
),
SliverList
(
delegate:
SliverChildListDelegate
(
<
Widget
>[
Container
(
height:
1200.0
,
color:
Colors
.
teal
),
],
),
),
],
),
),
),
);
Finder
findAppBarMaterial
()
{
// There are 2 Material widgets below AppBar. The second is only added if
// flexibleSpace is non-null.
return
find
.
descendant
(
of:
find
.
byType
(
AppBar
),
matching:
find
.
byType
(
Material
)).
first
;
}
Color
?
getAppBarBackgroundColor
()
{
return
tester
.
widget
<
Material
>(
findAppBarMaterial
()).
color
;
}
expect
(
getAppBarBackgroundColor
(),
defaultColor
);
expect
(
tester
.
getSize
(
findAppBarMaterial
()).
height
,
expandedHeight
);
TestGesture
gesture
=
await
tester
.
startGesture
(
const
Offset
(
50.0
,
400.0
));
await
gesture
.
moveBy
(
const
Offset
(
0.0
,
-
expandedHeight
));
await
gesture
.
up
();
await
tester
.
pumpAndSettle
();
expect
(
getAppBarBackgroundColor
(),
scrolledColor
);
expect
(
tester
.
getSize
(
findAppBarMaterial
()).
height
,
collapsedHeight
);
gesture
=
await
tester
.
startGesture
(
const
Offset
(
50.0
,
300.0
));
await
gesture
.
moveBy
(
const
Offset
(
0.0
,
expandedHeight
));
await
gesture
.
up
();
await
tester
.
pumpAndSettle
();
expect
(
getAppBarBackgroundColor
(),
defaultColor
);
expect
(
tester
.
getSize
(
findAppBarMaterial
()).
height
,
expandedHeight
);
});
testWidgets
(
'AppBar.backgroundColor MaterialStateColor scrolledUnder'
,
(
WidgetTester
tester
)
async
{
const
Color
scrolledColor
=
Color
(
0xff00ff00
);
const
Color
defaultColor
=
Color
(
0xff0000ff
);
await
tester
.
pumpWidget
(
MaterialApp
(
home:
Scaffold
(
appBar:
AppBar
(
backwardsCompatibility:
false
,
elevation:
0
,
backgroundColor:
MaterialStateColor
.
resolveWith
((
Set
<
MaterialState
>
states
)
{
return
states
.
contains
(
MaterialState
.
scrolledUnder
)
?
scrolledColor
:
defaultColor
;
}),
title:
const
Text
(
'AppBar'
),
),
body:
ListView
(
children:
<
Widget
>[
Container
(
height:
1200.0
,
color:
Colors
.
teal
),
],
),
),
),
);
Finder
findAppBarMaterial
()
{
return
find
.
descendant
(
of:
find
.
byType
(
AppBar
),
matching:
find
.
byType
(
Material
));
}
Color
?
getAppBarBackgroundColor
()
{
return
tester
.
widget
<
Material
>(
findAppBarMaterial
()).
color
;
}
expect
(
getAppBarBackgroundColor
(),
defaultColor
);
expect
(
tester
.
getSize
(
findAppBarMaterial
()).
height
,
kToolbarHeight
);
TestGesture
gesture
=
await
tester
.
startGesture
(
const
Offset
(
50.0
,
400.0
));
await
gesture
.
moveBy
(
const
Offset
(
0.0
,
-
kToolbarHeight
));
await
gesture
.
up
();
await
tester
.
pumpAndSettle
();
expect
(
getAppBarBackgroundColor
(),
scrolledColor
);
expect
(
tester
.
getSize
(
findAppBarMaterial
()).
height
,
kToolbarHeight
);
gesture
=
await
tester
.
startGesture
(
const
Offset
(
50.0
,
300.0
));
await
gesture
.
moveBy
(
const
Offset
(
0.0
,
kToolbarHeight
));
await
gesture
.
up
();
await
tester
.
pumpAndSettle
();
expect
(
getAppBarBackgroundColor
(),
defaultColor
);
expect
(
tester
.
getSize
(
findAppBarMaterial
()).
height
,
kToolbarHeight
);
});
testWidgets
(
'AppBar.backgroundColor with FlexibleSpace MaterialStateColor scrolledUnder'
,
(
WidgetTester
tester
)
async
{
const
Color
scrolledColor
=
Color
(
0xff00ff00
);
const
Color
defaultColor
=
Color
(
0xff0000ff
);
await
tester
.
pumpWidget
(
MaterialApp
(
home:
Scaffold
(
appBar:
AppBar
(
backwardsCompatibility:
false
,
elevation:
0
,
backgroundColor:
MaterialStateColor
.
resolveWith
((
Set
<
MaterialState
>
states
)
{
return
states
.
contains
(
MaterialState
.
scrolledUnder
)
?
scrolledColor
:
defaultColor
;
}),
title:
const
Text
(
'AppBar'
),
flexibleSpace:
const
FlexibleSpaceBar
(
title:
Text
(
'FlexibleSpace'
),
),
),
body:
ListView
(
children:
<
Widget
>[
Container
(
height:
1200.0
,
color:
Colors
.
teal
),
],
),
),
),
);
Finder
findAppBarMaterial
()
{
// There are 2 Material widgets below AppBar. The second is only added if
// flexibleSpace is non-null.
return
find
.
descendant
(
of:
find
.
byType
(
AppBar
),
matching:
find
.
byType
(
Material
)).
first
;
}
Color
?
getAppBarBackgroundColor
()
{
return
tester
.
widget
<
Material
>(
findAppBarMaterial
()).
color
;
}
expect
(
getAppBarBackgroundColor
(),
defaultColor
);
expect
(
tester
.
getSize
(
findAppBarMaterial
()).
height
,
kToolbarHeight
);
TestGesture
gesture
=
await
tester
.
startGesture
(
const
Offset
(
50.0
,
400.0
));
await
gesture
.
moveBy
(
const
Offset
(
0.0
,
-
kToolbarHeight
));
await
gesture
.
up
();
await
tester
.
pumpAndSettle
();
expect
(
getAppBarBackgroundColor
(),
scrolledColor
);
expect
(
tester
.
getSize
(
findAppBarMaterial
()).
height
,
kToolbarHeight
);
gesture
=
await
tester
.
startGesture
(
const
Offset
(
50.0
,
300.0
));
await
gesture
.
moveBy
(
const
Offset
(
0.0
,
kToolbarHeight
));
await
gesture
.
up
();
await
tester
.
pumpAndSettle
();
expect
(
getAppBarBackgroundColor
(),
defaultColor
);
expect
(
tester
.
getSize
(
findAppBarMaterial
()).
height
,
kToolbarHeight
);
});
}
packages/flutter/test/material/scaffold_test.dart
View file @
989a2f24
...
...
@@ -2190,9 +2190,6 @@ void main() {
' PhysicalModel
\n
'
' AnimatedPhysicalModel
\n
'
' Material
\n
'
' _ScrollNotificationObserverScope
\n
'
' NotificationListener<ScrollNotification>
\n
'
' ScrollNotificationObserver
\n
'
' _ScaffoldScope
\n
'
' Scaffold
\n
'
' MediaQuery
\n
'
...
...
packages/flutter/test/widgets/scroll_notification_test.dart
View file @
989a2f24
...
...
@@ -150,69 +150,4 @@ void main() {
expect
(
notificationTypes
,
equals
(
types
));
});
testWidgets
(
'ScrollNotificationObserver'
,
(
WidgetTester
tester
)
async
{
late
ScrollNotificationObserverState
observer
;
ScrollNotification
?
notification
;
void
handleNotification
(
ScrollNotification
value
)
{
if
(
value
is
ScrollStartNotification
||
value
is
ScrollUpdateNotification
||
value
is
ScrollEndNotification
)
notification
=
value
;
}
await
tester
.
pumpWidget
(
ScrollNotificationObserver
(
child:
Builder
(
builder:
(
BuildContext
context
)
{
observer
=
ScrollNotificationObserver
.
of
(
context
)!;
return
const
SingleChildScrollView
(
child:
SizedBox
(
height:
1200.0
),
);
},
),
),
);
observer
.
addListener
(
handleNotification
);
TestGesture
gesture
=
await
tester
.
startGesture
(
const
Offset
(
100.0
,
100.0
));
await
tester
.
pumpAndSettle
();
expect
(
notification
,
isA
<
ScrollStartNotification
>());
expect
(
notification
!.
depth
,
equals
(
0
));
final
ScrollStartNotification
start
=
notification
!
as
ScrollStartNotification
;
expect
(
start
.
dragDetails
,
isNotNull
);
expect
(
start
.
dragDetails
!.
globalPosition
,
equals
(
const
Offset
(
100.0
,
100.0
)));
await
gesture
.
moveBy
(
const
Offset
(-
10.0
,
-
10.0
));
await
tester
.
pumpAndSettle
();
expect
(
notification
,
isA
<
ScrollUpdateNotification
>());
expect
(
notification
!.
depth
,
equals
(
0
));
final
ScrollUpdateNotification
update
=
notification
!
as
ScrollUpdateNotification
;
expect
(
update
.
dragDetails
,
isNotNull
);
expect
(
update
.
dragDetails
!.
globalPosition
,
equals
(
const
Offset
(
90.0
,
90.0
)));
expect
(
update
.
dragDetails
!.
delta
,
equals
(
const
Offset
(
0.0
,
-
10.0
)));
await
gesture
.
up
();
await
tester
.
pumpAndSettle
();
expect
(
notification
,
isA
<
ScrollEndNotification
>());
expect
(
notification
!.
depth
,
equals
(
0
));
final
ScrollEndNotification
end
=
notification
!
as
ScrollEndNotification
;
expect
(
end
.
dragDetails
,
isNotNull
);
expect
(
end
.
dragDetails
!.
velocity
,
equals
(
Velocity
.
zero
));
observer
.
removeListener
(
handleNotification
);
notification
=
null
;
gesture
=
await
tester
.
startGesture
(
const
Offset
(
100.0
,
100.0
));
await
tester
.
pumpAndSettle
();
expect
(
notification
,
isNull
);
await
gesture
.
moveBy
(
const
Offset
(-
10.0
,
-
10.0
));
await
tester
.
pumpAndSettle
();
expect
(
notification
,
isNull
);
await
gesture
.
up
();
await
tester
.
pumpAndSettle
();
expect
(
notification
,
isNull
);
});
}
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