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
637bd0fb
Unverified
Commit
637bd0fb
authored
Aug 25, 2022
by
Jonah Williams
Committed by
GitHub
Aug 25, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[framework] simplify raster widget, rename, combine painters (#109485)
parent
7f260672
Changes
15
Show whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
1050 additions
and
173 deletions
+1050
-173
route.dart
packages/flutter/lib/src/cupertino/route.dart
+6
-6
page.dart
packages/flutter/lib/src/material/page.dart
+6
-6
page_transitions_theme.dart
...ages/flutter/lib/src/material/page_transitions_theme.dart
+84
-46
pages.dart
packages/flutter/lib/src/widgets/pages.dart
+3
-3
routes.dart
packages/flutter/lib/src/widgets/routes.dart
+7
-7
snapshot_widget.dart
packages/flutter/lib/src/widgets/snapshot_widget.dart
+444
-0
widgets.dart
packages/flutter/lib/widgets.dart
+1
-1
dropdown_test.dart
packages/flutter/test/material/dropdown_test.dart
+15
-12
page_test.dart
packages/flutter/test/material/page_test.dart
+20
-4
text_field_test.dart
packages/flutter/test/material/text_field_test.dart
+1
-1
heroes_test.dart
packages/flutter/test/widgets/heroes_test.dart
+19
-4
navigator_restoration_test.dart
...ages/flutter/test/widgets/navigator_restoration_test.dart
+22
-16
navigator_test.dart
packages/flutter/test/widgets/navigator_test.dart
+41
-49
scroll_position_test.dart
packages/flutter/test/widgets/scroll_position_test.dart
+21
-18
snapshot_widget_test.dart
packages/flutter/test/widgets/snapshot_widget_test.dart
+360
-0
No files found.
packages/flutter/lib/src/cupertino/route.dart
View file @
637bd0fb
...
@@ -342,7 +342,7 @@ class CupertinoPageRoute<T> extends PageRoute<T> with CupertinoRouteTransitionMi
...
@@ -342,7 +342,7 @@ class CupertinoPageRoute<T> extends PageRoute<T> with CupertinoRouteTransitionMi
super
.
settings
,
super
.
settings
,
this
.
maintainState
=
true
,
this
.
maintainState
=
true
,
super
.
fullscreenDialog
,
super
.
fullscreenDialog
,
super
.
preferRasterization
=
true
,
super
.
allowSnapshotting
=
true
,
})
:
assert
(
builder
!=
null
),
})
:
assert
(
builder
!=
null
),
assert
(
maintainState
!=
null
),
assert
(
maintainState
!=
null
),
assert
(
fullscreenDialog
!=
null
)
{
assert
(
fullscreenDialog
!=
null
)
{
...
@@ -372,7 +372,7 @@ class CupertinoPageRoute<T> extends PageRoute<T> with CupertinoRouteTransitionMi
...
@@ -372,7 +372,7 @@ class CupertinoPageRoute<T> extends PageRoute<T> with CupertinoRouteTransitionMi
class
_PageBasedCupertinoPageRoute
<
T
>
extends
PageRoute
<
T
>
with
CupertinoRouteTransitionMixin
<
T
>
{
class
_PageBasedCupertinoPageRoute
<
T
>
extends
PageRoute
<
T
>
with
CupertinoRouteTransitionMixin
<
T
>
{
_PageBasedCupertinoPageRoute
({
_PageBasedCupertinoPageRoute
({
required
CupertinoPage
<
T
>
page
,
required
CupertinoPage
<
T
>
page
,
super
.
preferRasterization
=
true
,
super
.
allowSnapshotting
=
true
,
})
:
assert
(
page
!=
null
),
})
:
assert
(
page
!=
null
),
super
(
settings:
page
)
{
super
(
settings:
page
)
{
assert
(
opaque
);
assert
(
opaque
);
...
@@ -419,7 +419,7 @@ class CupertinoPage<T> extends Page<T> {
...
@@ -419,7 +419,7 @@ class CupertinoPage<T> extends Page<T> {
this
.
maintainState
=
true
,
this
.
maintainState
=
true
,
this
.
title
,
this
.
title
,
this
.
fullscreenDialog
=
false
,
this
.
fullscreenDialog
=
false
,
this
.
preferRasterization
=
true
,
this
.
allowSnapshotting
=
true
,
super
.
key
,
super
.
key
,
super
.
name
,
super
.
name
,
super
.
arguments
,
super
.
arguments
,
...
@@ -440,12 +440,12 @@ class CupertinoPage<T> extends Page<T> {
...
@@ -440,12 +440,12 @@ class CupertinoPage<T> extends Page<T> {
/// {@macro flutter.widgets.PageRoute.fullscreenDialog}
/// {@macro flutter.widgets.PageRoute.fullscreenDialog}
final
bool
fullscreenDialog
;
final
bool
fullscreenDialog
;
/// {@macro flutter.widgets.TransitionRoute.
preferRasterization
}
/// {@macro flutter.widgets.TransitionRoute.
allowSnapshotting
}
final
bool
preferRasterization
;
final
bool
allowSnapshotting
;
@override
@override
Route
<
T
>
createRoute
(
BuildContext
context
)
{
Route
<
T
>
createRoute
(
BuildContext
context
)
{
return
_PageBasedCupertinoPageRoute
<
T
>(
page:
this
,
preferRasterization:
preferRasterization
);
return
_PageBasedCupertinoPageRoute
<
T
>(
page:
this
,
allowSnapshotting:
allowSnapshotting
);
}
}
}
}
...
...
packages/flutter/lib/src/material/page.dart
View file @
637bd0fb
...
@@ -39,7 +39,7 @@ class MaterialPageRoute<T> extends PageRoute<T> with MaterialRouteTransitionMixi
...
@@ -39,7 +39,7 @@ class MaterialPageRoute<T> extends PageRoute<T> with MaterialRouteTransitionMixi
super
.
settings
,
super
.
settings
,
this
.
maintainState
=
true
,
this
.
maintainState
=
true
,
super
.
fullscreenDialog
,
super
.
fullscreenDialog
,
super
.
preferRasterization
=
true
,
super
.
allowSnapshotting
=
true
,
})
:
assert
(
builder
!=
null
),
})
:
assert
(
builder
!=
null
),
assert
(
maintainState
!=
null
),
assert
(
maintainState
!=
null
),
assert
(
fullscreenDialog
!=
null
)
{
assert
(
fullscreenDialog
!=
null
)
{
...
@@ -158,7 +158,7 @@ class MaterialPage<T> extends Page<T> {
...
@@ -158,7 +158,7 @@ class MaterialPage<T> extends Page<T> {
required
this
.
child
,
required
this
.
child
,
this
.
maintainState
=
true
,
this
.
maintainState
=
true
,
this
.
fullscreenDialog
=
false
,
this
.
fullscreenDialog
=
false
,
this
.
preferRasterization
=
true
,
this
.
allowSnapshotting
=
true
,
super
.
key
,
super
.
key
,
super
.
name
,
super
.
name
,
super
.
arguments
,
super
.
arguments
,
...
@@ -176,12 +176,12 @@ class MaterialPage<T> extends Page<T> {
...
@@ -176,12 +176,12 @@ class MaterialPage<T> extends Page<T> {
/// {@macro flutter.widgets.PageRoute.fullscreenDialog}
/// {@macro flutter.widgets.PageRoute.fullscreenDialog}
final
bool
fullscreenDialog
;
final
bool
fullscreenDialog
;
/// {@macro flutter.widgets.TransitionRoute.
preferRasterization
}
/// {@macro flutter.widgets.TransitionRoute.
allowSnapshotting
}
final
bool
preferRasterization
;
final
bool
allowSnapshotting
;
@override
@override
Route
<
T
>
createRoute
(
BuildContext
context
)
{
Route
<
T
>
createRoute
(
BuildContext
context
)
{
return
_PageBasedMaterialPageRoute
<
T
>(
page:
this
,
preferRasterization:
preferRasterization
);
return
_PageBasedMaterialPageRoute
<
T
>(
page:
this
,
allowSnapshotting:
allowSnapshotting
);
}
}
}
}
...
@@ -192,7 +192,7 @@ class MaterialPage<T> extends Page<T> {
...
@@ -192,7 +192,7 @@ class MaterialPage<T> extends Page<T> {
class
_PageBasedMaterialPageRoute
<
T
>
extends
PageRoute
<
T
>
with
MaterialRouteTransitionMixin
<
T
>
{
class
_PageBasedMaterialPageRoute
<
T
>
extends
PageRoute
<
T
>
with
MaterialRouteTransitionMixin
<
T
>
{
_PageBasedMaterialPageRoute
({
_PageBasedMaterialPageRoute
({
required
MaterialPage
<
T
>
page
,
required
MaterialPage
<
T
>
page
,
super
.
preferRasterization
,
super
.
allowSnapshotting
,
})
:
assert
(
page
!=
null
),
})
:
assert
(
page
!=
null
),
super
(
settings:
page
)
{
super
(
settings:
page
)
{
assert
(
opaque
);
assert
(
opaque
);
...
...
packages/flutter/lib/src/material/page_transitions_theme.dart
View file @
637bd0fb
...
@@ -156,7 +156,7 @@ class _ZoomPageTransition extends StatelessWidget {
...
@@ -156,7 +156,7 @@ class _ZoomPageTransition extends StatelessWidget {
const
_ZoomPageTransition
({
const
_ZoomPageTransition
({
required
this
.
animation
,
required
this
.
animation
,
required
this
.
secondaryAnimation
,
required
this
.
secondaryAnimation
,
required
this
.
preferRasterization
,
required
this
.
allowSnapshotting
,
this
.
child
,
this
.
child
,
})
:
assert
(
animation
!=
null
),
})
:
assert
(
animation
!=
null
),
assert
(
secondaryAnimation
!=
null
);
assert
(
secondaryAnimation
!=
null
);
...
@@ -194,13 +194,12 @@ class _ZoomPageTransition extends StatelessWidget {
...
@@ -194,13 +194,12 @@ class _ZoomPageTransition extends StatelessWidget {
/// property when the [_ZoomPageTransition] is used as a page transition.
/// property when the [_ZoomPageTransition] is used as a page transition.
final
Animation
<
double
>
secondaryAnimation
;
final
Animation
<
double
>
secondaryAnimation
;
/// Whether the [RasterWidget] based-rasterized strategy for the zoom page transition
/// Whether the [SnapshotWidget] will be used.
/// will be used.
///
///
/// Notably, this improves performance by disabling animations on both the outgoing and
/// Notably, this improves performance by disabling animations on both the outgoing and
/// incoming route. This also implies that ink-splashes or similar animations will
/// incoming route. This also implies that ink-splashes or similar animations will
/// not animate during the transition.
/// not animate during the transition.
final
bool
preferRasterization
;
final
bool
allowSnapshotting
;
/// The widget below this widget in the tree.
/// The widget below this widget in the tree.
///
///
...
@@ -219,7 +218,7 @@ class _ZoomPageTransition extends StatelessWidget {
...
@@ -219,7 +218,7 @@ class _ZoomPageTransition extends StatelessWidget {
)
{
)
{
return
_ZoomEnterTransition
(
return
_ZoomEnterTransition
(
animation:
animation
,
animation:
animation
,
preferRasterization:
preferRasterization
,
allowSnapshotting:
allowSnapshotting
,
child:
child
,
child:
child
,
);
);
},
},
...
@@ -230,7 +229,7 @@ class _ZoomPageTransition extends StatelessWidget {
...
@@ -230,7 +229,7 @@ class _ZoomPageTransition extends StatelessWidget {
)
{
)
{
return
_ZoomExitTransition
(
return
_ZoomExitTransition
(
animation:
animation
,
animation:
animation
,
preferRasterization:
preferRasterization
,
allowSnapshotting:
allowSnapshotting
,
reverse:
true
,
reverse:
true
,
child:
child
,
child:
child
,
);
);
...
@@ -244,7 +243,7 @@ class _ZoomPageTransition extends StatelessWidget {
...
@@ -244,7 +243,7 @@ class _ZoomPageTransition extends StatelessWidget {
)
{
)
{
return
_ZoomEnterTransition
(
return
_ZoomEnterTransition
(
animation:
animation
,
animation:
animation
,
preferRasterization:
preferRasterization
,
allowSnapshotting:
allowSnapshotting
,
reverse:
true
,
reverse:
true
,
child:
child
,
child:
child
,
);
);
...
@@ -256,7 +255,7 @@ class _ZoomPageTransition extends StatelessWidget {
...
@@ -256,7 +255,7 @@ class _ZoomPageTransition extends StatelessWidget {
)
{
)
{
return
_ZoomExitTransition
(
return
_ZoomExitTransition
(
animation:
animation
,
animation:
animation
,
preferRasterization:
preferRasterization
,
allowSnapshotting:
allowSnapshotting
,
child:
child
,
child:
child
,
);
);
},
},
...
@@ -270,14 +269,14 @@ class _ZoomEnterTransition extends StatefulWidget {
...
@@ -270,14 +269,14 @@ class _ZoomEnterTransition extends StatefulWidget {
const
_ZoomEnterTransition
({
const
_ZoomEnterTransition
({
required
this
.
animation
,
required
this
.
animation
,
this
.
reverse
=
false
,
this
.
reverse
=
false
,
required
this
.
preferRasterization
,
required
this
.
allowSnapshotting
,
this
.
child
,
this
.
child
,
})
:
assert
(
animation
!=
null
),
})
:
assert
(
animation
!=
null
),
assert
(
reverse
!=
null
);
assert
(
reverse
!=
null
);
final
Animation
<
double
>
animation
;
final
Animation
<
double
>
animation
;
final
Widget
?
child
;
final
Widget
?
child
;
final
bool
preferRasterization
;
final
bool
allowSnapshotting
;
final
bool
reverse
;
final
bool
reverse
;
@override
@override
...
@@ -285,10 +284,13 @@ class _ZoomEnterTransition extends StatefulWidget {
...
@@ -285,10 +284,13 @@ class _ZoomEnterTransition extends StatefulWidget {
}
}
class
_ZoomEnterTransitionState
extends
State
<
_ZoomEnterTransition
>
with
_ZoomTransitionBase
{
class
_ZoomEnterTransitionState
extends
State
<
_ZoomEnterTransition
>
with
_ZoomTransitionBase
{
// TODO(jonahwilliams): https://github.com/flutter/flutter/issues/106689
// See SnapshotWidget doc comment, this is disabled on web because the HTML backend doesn't
bool
get
allowRasterization
=>
!
kIsWeb
&&
widget
.
preferRasterization
;
// support this functionality and the canvaskit backend uses a single thread for UI and raster
// work which diminishes the impact of this performance improvement.
@override
bool
get
useSnapshot
=>
!
kIsWeb
&&
widget
.
allowSnapshotting
;
late
_ZoomEnterTransition
Delegate
delegate
;
late
_ZoomEnterTransition
Painter
delegate
;
static
final
Animatable
<
double
>
_fadeInTransition
=
Tween
<
double
>(
static
final
Animatable
<
double
>
_fadeInTransition
=
Tween
<
double
>(
begin:
0.0
,
begin:
0.0
,
...
@@ -327,7 +329,7 @@ class _ZoomEnterTransitionState extends State<_ZoomEnterTransition> with _ZoomTr
...
@@ -327,7 +329,7 @@ class _ZoomEnterTransitionState extends State<_ZoomEnterTransition> with _ZoomTr
@override
@override
void
initState
()
{
void
initState
()
{
_updateAnimations
();
_updateAnimations
();
delegate
=
_ZoomEnterTransition
Delegate
(
delegate
=
_ZoomEnterTransition
Painter
(
reverse:
widget
.
reverse
,
reverse:
widget
.
reverse
,
fade:
fadeTransition
,
fade:
fadeTransition
,
scale:
scaleTransition
,
scale:
scaleTransition
,
...
@@ -343,7 +345,7 @@ class _ZoomEnterTransitionState extends State<_ZoomEnterTransition> with _ZoomTr
...
@@ -343,7 +345,7 @@ class _ZoomEnterTransitionState extends State<_ZoomEnterTransition> with _ZoomTr
oldWidget
.
animation
.
removeStatusListener
(
onAnimationStatusChange
);
oldWidget
.
animation
.
removeStatusListener
(
onAnimationStatusChange
);
_updateAnimations
();
_updateAnimations
();
delegate
.
dispose
();
delegate
.
dispose
();
delegate
=
_ZoomEnterTransition
Delegate
(
delegate
=
_ZoomEnterTransition
Painter
(
reverse:
widget
.
reverse
,
reverse:
widget
.
reverse
,
fade:
fadeTransition
,
fade:
fadeTransition
,
scale:
scaleTransition
,
scale:
scaleTransition
,
...
@@ -363,11 +365,10 @@ class _ZoomEnterTransitionState extends State<_ZoomEnterTransition> with _ZoomTr
...
@@ -363,11 +365,10 @@ class _ZoomEnterTransitionState extends State<_ZoomEnterTransition> with _ZoomTr
@override
@override
Widget
build
(
BuildContext
context
)
{
Widget
build
(
BuildContext
context
)
{
return
Raster
Widget
(
return
Snapshot
Widget
(
delegate
:
delegate
,
painter
:
delegate
,
controller:
controller
,
controller:
controller
,
fallback:
delegate
,
mode:
SnapshotMode
.
permissive
,
mode:
allowRasterization
?
RasterizeMode
.
enabled
:
RasterizeMode
.
fallback
,
child:
widget
.
child
,
child:
widget
.
child
,
);
);
}
}
...
@@ -377,13 +378,13 @@ class _ZoomExitTransition extends StatefulWidget {
...
@@ -377,13 +378,13 @@ class _ZoomExitTransition extends StatefulWidget {
const
_ZoomExitTransition
({
const
_ZoomExitTransition
({
required
this
.
animation
,
required
this
.
animation
,
this
.
reverse
=
false
,
this
.
reverse
=
false
,
required
this
.
preferRasterization
,
required
this
.
allowSnapshotting
,
this
.
child
,
this
.
child
,
})
:
assert
(
animation
!=
null
),
})
:
assert
(
animation
!=
null
),
assert
(
reverse
!=
null
);
assert
(
reverse
!=
null
);
final
Animation
<
double
>
animation
;
final
Animation
<
double
>
animation
;
final
bool
preferRasterization
;
final
bool
allowSnapshotting
;
final
bool
reverse
;
final
bool
reverse
;
final
Widget
?
child
;
final
Widget
?
child
;
...
@@ -392,10 +393,13 @@ class _ZoomExitTransition extends StatefulWidget {
...
@@ -392,10 +393,13 @@ class _ZoomExitTransition extends StatefulWidget {
}
}
class
_ZoomExitTransitionState
extends
State
<
_ZoomExitTransition
>
with
_ZoomTransitionBase
{
class
_ZoomExitTransitionState
extends
State
<
_ZoomExitTransition
>
with
_ZoomTransitionBase
{
late
_ZoomExitTransition
Delegate
delegate
;
late
_ZoomExitTransition
Painter
delegate
;
// TODO(jonahwilliams): https://github.com/flutter/flutter/issues/106689
// See SnapshotWidget doc comment, this is disabled on web because the HTML backend doesn't
bool
get
allowRasterization
=>
!
kIsWeb
&&
widget
.
preferRasterization
;
// support this functionality and the canvaskit backend uses a single thread for UI and raster
// work which diminishes the impact of this performance improvement.
@override
bool
get
useSnapshot
=>
!
kIsWeb
&&
widget
.
allowSnapshotting
;
static
final
Animatable
<
double
>
_fadeOutTransition
=
Tween
<
double
>(
static
final
Animatable
<
double
>
_fadeOutTransition
=
Tween
<
double
>(
begin:
1.0
,
begin:
1.0
,
...
@@ -428,10 +432,11 @@ class _ZoomExitTransitionState extends State<_ZoomExitTransition> with _ZoomTran
...
@@ -428,10 +432,11 @@ class _ZoomExitTransitionState extends State<_ZoomExitTransition> with _ZoomTran
@override
@override
void
initState
()
{
void
initState
()
{
_updateAnimations
();
_updateAnimations
();
delegate
=
_ZoomExitTransition
Delegate
(
delegate
=
_ZoomExitTransition
Painter
(
reverse:
widget
.
reverse
,
reverse:
widget
.
reverse
,
fade:
fadeTransition
,
fade:
fadeTransition
,
scale:
scaleTransition
,
scale:
scaleTransition
,
animation:
widget
.
animation
,
);
);
super
.
initState
();
super
.
initState
();
}
}
...
@@ -443,10 +448,11 @@ class _ZoomExitTransitionState extends State<_ZoomExitTransition> with _ZoomTran
...
@@ -443,10 +448,11 @@ class _ZoomExitTransitionState extends State<_ZoomExitTransition> with _ZoomTran
oldWidget
.
animation
.
removeStatusListener
(
onAnimationStatusChange
);
oldWidget
.
animation
.
removeStatusListener
(
onAnimationStatusChange
);
_updateAnimations
();
_updateAnimations
();
delegate
.
dispose
();
delegate
.
dispose
();
delegate
=
_ZoomExitTransition
Delegate
(
delegate
=
_ZoomExitTransition
Painter
(
reverse:
widget
.
reverse
,
reverse:
widget
.
reverse
,
fade:
fadeTransition
,
fade:
fadeTransition
,
scale:
scaleTransition
,
scale:
scaleTransition
,
animation:
widget
.
animation
,
);
);
}
}
super
.
didUpdateWidget
(
oldWidget
);
super
.
didUpdateWidget
(
oldWidget
);
...
@@ -462,11 +468,10 @@ class _ZoomExitTransitionState extends State<_ZoomExitTransition> with _ZoomTran
...
@@ -462,11 +468,10 @@ class _ZoomExitTransitionState extends State<_ZoomExitTransition> with _ZoomTran
@override
@override
Widget
build
(
BuildContext
context
)
{
Widget
build
(
BuildContext
context
)
{
return
Raster
Widget
(
return
Snapshot
Widget
(
delegate
:
delegate
,
painter
:
delegate
,
controller:
controller
,
controller:
controller
,
fallback:
delegate
,
mode:
SnapshotMode
.
permissive
,
mode:
allowRasterization
?
RasterizeMode
.
enabled
:
RasterizeMode
.
fallback
,
child:
widget
.
child
,
child:
widget
.
child
,
);
);
}
}
...
@@ -602,7 +607,7 @@ class ZoomPageTransitionsBuilder extends PageTransitionsBuilder {
...
@@ -602,7 +607,7 @@ class ZoomPageTransitionsBuilder extends PageTransitionsBuilder {
return
_ZoomPageTransition
(
return
_ZoomPageTransition
(
animation:
animation
,
animation:
animation
,
secondaryAnimation:
secondaryAnimation
,
secondaryAnimation:
secondaryAnimation
,
preferRasterization:
route
?.
preferRasterization
??
true
,
allowSnapshotting:
route
?.
allowSnapshotting
??
true
,
child:
child
,
child:
child
,
);
);
}
}
...
@@ -765,12 +770,14 @@ void _updateScaledTransform(Matrix4 transform, double scale, Size size) {
...
@@ -765,12 +770,14 @@ void _updateScaledTransform(Matrix4 transform, double scale, Size size) {
}
}
mixin
_ZoomTransitionBase
{
mixin
_ZoomTransitionBase
{
bool
get
useSnapshot
;
// Don't rasterize if:
// Don't rasterize if:
// 1. Rasterization is disabled by the platform.
// 1. Rasterization is disabled by the platform.
// 2. The animation is paused/stopped.
// 2. The animation is paused/stopped.
// 3. The values of the scale/fade transition do not
// 3. The values of the scale/fade transition do not
// benefit from rasterization.
// benefit from rasterization.
final
RasterWidgetController
controller
=
RasterWidge
tController
();
final
SnapshotController
controller
=
Snapsho
tController
();
late
Animation
<
double
>
fadeTransition
;
late
Animation
<
double
>
fadeTransition
;
late
Animation
<
double
>
scaleTransition
;
late
Animation
<
double
>
scaleTransition
;
...
@@ -779,9 +786,9 @@ mixin _ZoomTransitionBase {
...
@@ -779,9 +786,9 @@ mixin _ZoomTransitionBase {
if
((
scaleTransition
.
value
==
1.0
)
&&
if
((
scaleTransition
.
value
==
1.0
)
&&
(
fadeTransition
.
value
==
0.0
||
(
fadeTransition
.
value
==
0.0
||
fadeTransition
.
value
==
1.0
))
{
fadeTransition
.
value
==
1.0
))
{
controller
.
rasterize
=
false
;
controller
.
allowSnapshotting
=
false
;
}
else
{
}
else
{
controller
.
rasterize
=
true
;
controller
.
allowSnapshotting
=
useSnapshot
;
}
}
}
}
...
@@ -789,28 +796,33 @@ mixin _ZoomTransitionBase {
...
@@ -789,28 +796,33 @@ mixin _ZoomTransitionBase {
switch
(
status
)
{
switch
(
status
)
{
case
AnimationStatus
.
dismissed
:
case
AnimationStatus
.
dismissed
:
case
AnimationStatus
.
completed
:
case
AnimationStatus
.
completed
:
controller
.
rasterize
=
false
;
controller
.
allowSnapshotting
=
false
;
break
;
break
;
case
AnimationStatus
.
forward
:
case
AnimationStatus
.
forward
:
case
AnimationStatus
.
reverse
:
case
AnimationStatus
.
reverse
:
controller
.
rasterize
=
true
;
controller
.
allowSnapshotting
=
useSnapshot
;
break
;
break
;
}
}
}
}
}
}
class
_ZoomEnterTransition
Delegate
extends
RasterWidgetDelegate
implements
RasterWidgetFallbackDelegate
{
class
_ZoomEnterTransition
Painter
extends
SnapshotPainter
{
_ZoomEnterTransition
Delegate
({
_ZoomEnterTransition
Painter
({
required
this
.
reverse
,
required
this
.
reverse
,
required
this
.
scale
,
required
this
.
scale
,
required
this
.
fade
,
required
this
.
fade
,
required
this
.
animation
,
required
this
.
animation
,
})
{
})
{
animation
.
addListener
(
notifyListeners
);
animation
.
addListener
(
notifyListeners
);
animation
.
addStatusListener
(
_onStatusChange
);
scale
.
addListener
(
notifyListeners
);
scale
.
addListener
(
notifyListeners
);
fade
.
addListener
(
notifyListeners
);
fade
.
addListener
(
notifyListeners
);
}
}
void
_onStatusChange
(
_
)
{
notifyListeners
();
}
final
bool
reverse
;
final
bool
reverse
;
final
Animation
<
double
>
animation
;
final
Animation
<
double
>
animation
;
final
Animation
<
double
>
scale
;
final
Animation
<
double
>
scale
;
...
@@ -845,7 +857,15 @@ class _ZoomEnterTransitionDelegate extends RasterWidgetDelegate implements Raste
...
@@ -845,7 +857,15 @@ class _ZoomEnterTransitionDelegate extends RasterWidgetDelegate implements Raste
}
}
@override
@override
void
paintFallback
(
PaintingContext
context
,
ui
.
Offset
offset
,
Size
size
,
PaintingContextCallback
painter
)
{
void
paint
(
PaintingContext
context
,
ui
.
Offset
offset
,
Size
size
,
PaintingContextCallback
painter
)
{
switch
(
animation
.
status
)
{
case
AnimationStatus
.
completed
:
case
AnimationStatus
.
dismissed
:
return
painter
(
context
,
offset
);
case
AnimationStatus
.
forward
:
case
AnimationStatus
.
reverse
:
}
_drawScrim
(
context
,
offset
,
size
);
_drawScrim
(
context
,
offset
,
size
);
_updateScaledTransform
(
_transform
,
scale
.
value
,
size
);
_updateScaledTransform
(
_transform
,
scale
.
value
,
size
);
_transformHandler
.
layer
=
context
.
pushTransform
(
true
,
offset
,
_transform
,
(
PaintingContext
context
,
Offset
offset
)
{
_transformHandler
.
layer
=
context
.
pushTransform
(
true
,
offset
,
_transform
,
(
PaintingContext
context
,
Offset
offset
)
{
...
@@ -854,7 +874,7 @@ class _ZoomEnterTransitionDelegate extends RasterWidgetDelegate implements Raste
...
@@ -854,7 +874,7 @@ class _ZoomEnterTransitionDelegate extends RasterWidgetDelegate implements Raste
}
}
@override
@override
void
paint
(
PaintingContext
context
,
Offset
offset
,
Size
size
,
ui
.
Image
image
,
double
pixelRatio
)
{
void
paint
Snapshot
(
PaintingContext
context
,
Offset
offset
,
Size
size
,
ui
.
Image
image
,
double
pixelRatio
)
{
_drawScrim
(
context
,
offset
,
size
);
_drawScrim
(
context
,
offset
,
size
);
_drawImageScaledAndCentered
(
context
,
image
,
scale
.
value
,
fade
.
value
,
pixelRatio
);
_drawImageScaledAndCentered
(
context
,
image
,
scale
.
value
,
fade
.
value
,
pixelRatio
);
}
}
...
@@ -862,6 +882,7 @@ class _ZoomEnterTransitionDelegate extends RasterWidgetDelegate implements Raste
...
@@ -862,6 +882,7 @@ class _ZoomEnterTransitionDelegate extends RasterWidgetDelegate implements Raste
@override
@override
void
dispose
()
{
void
dispose
()
{
animation
.
removeListener
(
notifyListeners
);
animation
.
removeListener
(
notifyListeners
);
animation
.
removeStatusListener
(
_onStatusChange
);
scale
.
removeListener
(
notifyListeners
);
scale
.
removeListener
(
notifyListeners
);
fade
.
removeListener
(
notifyListeners
);
fade
.
removeListener
(
notifyListeners
);
_opacityHandle
.
layer
=
null
;
_opacityHandle
.
layer
=
null
;
...
@@ -870,7 +891,7 @@ class _ZoomEnterTransitionDelegate extends RasterWidgetDelegate implements Raste
...
@@ -870,7 +891,7 @@ class _ZoomEnterTransitionDelegate extends RasterWidgetDelegate implements Raste
}
}
@override
@override
bool
shouldRepaint
(
covariant
_ZoomEnterTransition
Delegate
oldDelegate
)
{
bool
shouldRepaint
(
covariant
_ZoomEnterTransition
Painter
oldDelegate
)
{
return
oldDelegate
.
reverse
!=
reverse
return
oldDelegate
.
reverse
!=
reverse
||
oldDelegate
.
animation
.
value
!=
animation
.
value
||
oldDelegate
.
animation
.
value
!=
animation
.
value
||
oldDelegate
.
scale
.
value
!=
scale
.
value
||
oldDelegate
.
scale
.
value
!=
scale
.
value
...
@@ -878,30 +899,46 @@ class _ZoomEnterTransitionDelegate extends RasterWidgetDelegate implements Raste
...
@@ -878,30 +899,46 @@ class _ZoomEnterTransitionDelegate extends RasterWidgetDelegate implements Raste
}
}
}
}
class
_ZoomExitTransition
Delegate
extends
RasterWidgetDelegate
implements
RasterWidgetFallbackDelegate
{
class
_ZoomExitTransition
Painter
extends
SnapshotPainter
{
_ZoomExitTransition
Delegate
({
_ZoomExitTransition
Painter
({
required
this
.
reverse
,
required
this
.
reverse
,
required
this
.
scale
,
required
this
.
scale
,
required
this
.
fade
,
required
this
.
fade
,
required
this
.
animation
,
})
{
})
{
scale
.
addListener
(
notifyListeners
);
scale
.
addListener
(
notifyListeners
);
fade
.
addListener
(
notifyListeners
);
fade
.
addListener
(
notifyListeners
);
animation
.
addStatusListener
(
_onStatusChange
);
}
void
_onStatusChange
(
_
)
{
notifyListeners
();
}
}
final
bool
reverse
;
final
bool
reverse
;
final
Animation
<
double
>
scale
;
final
Animation
<
double
>
scale
;
final
Animation
<
double
>
fade
;
final
Animation
<
double
>
fade
;
final
Animation
<
double
>
animation
;
final
Matrix4
_transform
=
Matrix4
.
zero
();
final
Matrix4
_transform
=
Matrix4
.
zero
();
final
LayerHandle
<
OpacityLayer
>
_opacityHandle
=
LayerHandle
<
OpacityLayer
>();
final
LayerHandle
<
OpacityLayer
>
_opacityHandle
=
LayerHandle
<
OpacityLayer
>();
final
LayerHandle
<
TransformLayer
>
_transformHandler
=
LayerHandle
<
TransformLayer
>();
final
LayerHandle
<
TransformLayer
>
_transformHandler
=
LayerHandle
<
TransformLayer
>();
@override
@override
void
paint
(
PaintingContext
context
,
Offset
offset
,
Size
size
,
ui
.
Image
image
,
double
pixelRatio
)
{
void
paint
Snapshot
(
PaintingContext
context
,
Offset
offset
,
Size
size
,
ui
.
Image
image
,
double
pixelRatio
)
{
_drawImageScaledAndCentered
(
context
,
image
,
scale
.
value
,
fade
.
value
,
pixelRatio
);
_drawImageScaledAndCentered
(
context
,
image
,
scale
.
value
,
fade
.
value
,
pixelRatio
);
}
}
@override
@override
void
paintFallback
(
PaintingContext
context
,
ui
.
Offset
offset
,
Size
size
,
PaintingContextCallback
painter
)
{
void
paint
(
PaintingContext
context
,
ui
.
Offset
offset
,
Size
size
,
PaintingContextCallback
painter
)
{
switch
(
animation
.
status
)
{
case
AnimationStatus
.
completed
:
case
AnimationStatus
.
dismissed
:
return
painter
(
context
,
offset
);
case
AnimationStatus
.
forward
:
case
AnimationStatus
.
reverse
:
break
;
}
_updateScaledTransform
(
_transform
,
scale
.
value
,
size
);
_updateScaledTransform
(
_transform
,
scale
.
value
,
size
);
_transformHandler
.
layer
=
context
.
pushTransform
(
true
,
offset
,
_transform
,
(
PaintingContext
context
,
Offset
offset
)
{
_transformHandler
.
layer
=
context
.
pushTransform
(
true
,
offset
,
_transform
,
(
PaintingContext
context
,
Offset
offset
)
{
_opacityHandle
.
layer
=
context
.
pushOpacity
(
offset
,
(
fade
.
value
*
255
).
round
(),
painter
,
oldLayer:
_opacityHandle
.
layer
);
_opacityHandle
.
layer
=
context
.
pushOpacity
(
offset
,
(
fade
.
value
*
255
).
round
(),
painter
,
oldLayer:
_opacityHandle
.
layer
);
...
@@ -909,7 +946,7 @@ class _ZoomExitTransitionDelegate extends RasterWidgetDelegate implements Raster
...
@@ -909,7 +946,7 @@ class _ZoomExitTransitionDelegate extends RasterWidgetDelegate implements Raster
}
}
@override
@override
bool
shouldRepaint
(
covariant
_ZoomExitTransition
Delegate
oldDelegate
)
{
bool
shouldRepaint
(
covariant
_ZoomExitTransition
Painter
oldDelegate
)
{
return
oldDelegate
.
reverse
!=
reverse
||
oldDelegate
.
fade
.
value
!=
fade
.
value
||
oldDelegate
.
scale
.
value
!=
scale
.
value
;
return
oldDelegate
.
reverse
!=
reverse
||
oldDelegate
.
fade
.
value
!=
fade
.
value
||
oldDelegate
.
scale
.
value
!=
scale
.
value
;
}
}
...
@@ -919,6 +956,7 @@ class _ZoomExitTransitionDelegate extends RasterWidgetDelegate implements Raster
...
@@ -919,6 +956,7 @@ class _ZoomExitTransitionDelegate extends RasterWidgetDelegate implements Raster
_transformHandler
.
layer
=
null
;
_transformHandler
.
layer
=
null
;
scale
.
removeListener
(
notifyListeners
);
scale
.
removeListener
(
notifyListeners
);
fade
.
removeListener
(
notifyListeners
);
fade
.
removeListener
(
notifyListeners
);
animation
.
removeStatusListener
(
_onStatusChange
);
super
.
dispose
();
super
.
dispose
();
}
}
}
}
packages/flutter/lib/src/widgets/pages.dart
View file @
637bd0fb
...
@@ -19,7 +19,7 @@ abstract class PageRoute<T> extends ModalRoute<T> {
...
@@ -19,7 +19,7 @@ abstract class PageRoute<T> extends ModalRoute<T> {
PageRoute
({
PageRoute
({
super
.
settings
,
super
.
settings
,
this
.
fullscreenDialog
=
false
,
this
.
fullscreenDialog
=
false
,
this
.
preferRasterization
=
true
,
this
.
allowSnapshotting
=
true
,
});
});
/// {@template flutter.widgets.PageRoute.fullscreenDialog}
/// {@template flutter.widgets.PageRoute.fullscreenDialog}
...
@@ -33,7 +33,7 @@ abstract class PageRoute<T> extends ModalRoute<T> {
...
@@ -33,7 +33,7 @@ abstract class PageRoute<T> extends ModalRoute<T> {
final
bool
fullscreenDialog
;
final
bool
fullscreenDialog
;
@override
@override
final
bool
preferRasterization
;
final
bool
allowSnapshotting
;
@override
@override
bool
get
opaque
=>
true
;
bool
get
opaque
=>
true
;
...
@@ -80,7 +80,7 @@ class PageRouteBuilder<T> extends PageRoute<T> {
...
@@ -80,7 +80,7 @@ class PageRouteBuilder<T> extends PageRoute<T> {
this
.
barrierLabel
,
this
.
barrierLabel
,
this
.
maintainState
=
true
,
this
.
maintainState
=
true
,
super
.
fullscreenDialog
,
super
.
fullscreenDialog
,
super
.
preferRasterization
=
true
,
super
.
allowSnapshotting
=
true
,
})
:
assert
(
pageBuilder
!=
null
),
})
:
assert
(
pageBuilder
!=
null
),
assert
(
transitionsBuilder
!=
null
),
assert
(
transitionsBuilder
!=
null
),
assert
(
opaque
!=
null
),
assert
(
opaque
!=
null
),
...
...
packages/flutter/lib/src/widgets/routes.dart
View file @
637bd0fb
...
@@ -134,20 +134,20 @@ abstract class TransitionRoute<T> extends OverlayRoute<T> {
...
@@ -134,20 +134,20 @@ abstract class TransitionRoute<T> extends OverlayRoute<T> {
/// {@endtemplate}
/// {@endtemplate}
bool
get
opaque
;
bool
get
opaque
;
/// {@template flutter.widgets.TransitionRoute.
preferRasterization
}
/// {@template flutter.widgets.TransitionRoute.
allowSnapshotting
}
/// Whether the route transition will prefer to animate a
rasterized
/// Whether the route transition will prefer to animate a
snapshot of the
///
snapshot of the
entering/exiting routes.
/// entering/exiting routes.
///
///
/// When this value is true, certain route transitions (such as the Android
/// When this value is true, certain route transitions (such as the Android
/// zoom page transition) will
rasterize
the entering and exiting routes.
/// zoom page transition) will
snapshot
the entering and exiting routes.
/// These
texture
s are then animated in place of the underlying widgets to
/// These
snapshot
s are then animated in place of the underlying widgets to
/// improve performance of the transition.
/// improve performance of the transition.
///
///
/// Generally this means that animations that occur on the entering/exiting
/// Generally this means that animations that occur on the entering/exiting
/// route while the route animation plays may appear frozen - unless they
/// route while the route animation plays may appear frozen - unless they
/// are a hero animation or something that is drawn in a separate overlay.
/// are a hero animation or something that is drawn in a separate overlay.
/// {@endtemplate}
/// {@endtemplate}
bool
get
preferRasterization
=>
true
;
bool
get
allowSnapshotting
=>
true
;
// This ensures that if we got to the dismissed state while still current,
// This ensures that if we got to the dismissed state while still current,
// we will still be disposed when we are eventually popped.
// we will still be disposed when we are eventually popped.
...
@@ -1749,7 +1749,7 @@ abstract class PopupRoute<T> extends ModalRoute<T> {
...
@@ -1749,7 +1749,7 @@ abstract class PopupRoute<T> extends ModalRoute<T> {
bool
get
maintainState
=>
true
;
bool
get
maintainState
=>
true
;
@override
@override
bool
get
preferRasterization
=>
false
;
bool
get
allowSnapshotting
=>
false
;
}
}
/// A [Navigator] observer that notifies [RouteAware]s of changes to the
/// A [Navigator] observer that notifies [RouteAware]s of changes to the
...
...
packages/flutter/lib/src/widgets/
raster
_widget.dart
→
packages/flutter/lib/src/widgets/
snapshot
_widget.dart
View file @
637bd0fb
...
@@ -7,264 +7,162 @@ import 'dart:ui' as ui;
...
@@ -7,264 +7,162 @@ import 'dart:ui' as ui;
import
'package:flutter/rendering.dart'
;
import
'package:flutter/rendering.dart'
;
import
'basic.dart'
;
import
'basic.dart'
;
import
'debug.dart'
;
import
'framework.dart'
;
import
'framework.dart'
;
import
'media_query.dart'
;
import
'media_query.dart'
;
/// Controls how the [
RasterWidget] paints its children via the [RasterWidgetController]
.
/// Controls how the [
SnapshotWidget] paints its child
.
enum
Rasterize
Mode
{
enum
Snapshot
Mode
{
///
the children are rasterized, but only if all descendants can be rasteriz
ed.
///
The child is snapshotted, but only if all descendants can be snapshott
ed.
///
///
/// This setting is the default state of the [RasterWidgetController].
/// If there is a platform view in the children of a snapshot widget, the
///
/// snapshot will not be used and the child will be rendered using
/// If there is a platform view in the children of a raster widget
/// [SnapshotPainter.paint]. This uses an un-snapshotted child and by default
/// and a [RasterWidgetFallbackDelegate]h as been provided to the raster_widget,
/// paints it with no additional modification.
/// this fallback delegate will be used to render the children instead of the image.
permissive
,
/// If there is no fallback delegate, an excpetion will be thrown
enabled
,
///
The children are rasterized and any child platform views are ignor
ed.
///
An error is thrown if the child cannot be snapshott
ed.
///
///
/// In this state a [RasterWidgetFallbackDelegate] is never used. Generally this
/// This setting is the default state of the [SnapshotWidget].
/// can be useful if there is a platform view descendant that does not need to
normal
,
/// be included in the raster.
forced
,
/// the children are not rasterized and the [RasterWidgetFallbackDelegate],
/// The child is snapshotted and any child platform views are ignored.
/// if provided, is used to draw the children.
///
///
///
/// This mode can be useful if there is a platform view descendant that does
fallback
,
/// not need to be included in the snapshot.
forced
,
}
}
/// A controller for the [
Raster
Widget] that controls when the child image is displayed
/// A controller for the [
Snapshot
Widget] that controls when the child image is displayed
/// and when to regenerated the child image.
/// and when to regenerated the child image.
///
///
/// When the value of [
rasterize] is true, the [Raster
Widget] will paint the child
/// When the value of [
allowSnapshotting] is true, the [Snapshot
Widget] will paint the child
/// widgets based on the [
RasterizeMode] of the raster
widget.
/// widgets based on the [
SnapshotMode] of the snapshot
widget.
///
///
/// To force [RasterWidget] to recreate the child image, call [clear].
/// The controller notifies its listeners when the value of [allowSnapshotting] changes
class
RasterWidgetController
extends
ChangeNotifier
{
/// or when [clear] is called.
/// Create a new [RasterWidgetController].
///
/// To force [SnapshotWidget] to recreate the child image, call [clear].
class
SnapshotController
extends
ChangeNotifier
{
/// Create a new [SnapshotController].
///
///
/// By default, [
rasterize
] is `false` and cannot be `null`.
/// By default, [
allowSnapshotting
] is `false` and cannot be `null`.
RasterWidge
tController
({
Snapsho
tController
({
bool
rasterize
=
false
,
bool
allowSnapshotting
=
false
,
})
:
_
rasterize
=
rasterize
;
})
:
_
allowSnapshotting
=
allowSnapshotting
;
/// Reset the
raster held by any listening [Raster
Widget].
/// Reset the
snapshot held by any listening [Snapshot
Widget].
///
///
/// This has no effect if [
rasterize
] is `false`.
/// This has no effect if [
allowSnapshotting
] is `false`.
void
clear
()
{
void
clear
()
{
notifyListeners
();
notifyListeners
();
}
}
/// Whether a rasterized version of this render objects child is drawn in
/// Whether a snapshot of this child widget is painted in its place.
/// place of the child.
bool
get
allowSnapshotting
=>
_allowSnapshotting
;
bool
get
rasterize
=>
_rasterize
;
bool
_allowSnapshotting
;
bool
_rasterize
;
set
allowSnapshotting
(
bool
value
)
{
set
rasterize
(
bool
value
)
{
if
(
value
==
allowSnapshotting
)
{
if
(
value
==
rasterize
)
{
return
;
return
;
}
}
_
rasterize
=
value
;
_
allowSnapshotting
=
value
;
notifyListeners
();
notifyListeners
();
}
}
}
}
/// A widget that replaces its child with a rasterized version of the child.
/// A widget that can replace its child with a snapshoted version of the child.
///
/// A snapshot is a frozen texture-backed representation of all child pictures
/// and layers stored as a [ui.Image].
///
/// This widget is useful for performing short animations that would otherwise
/// be expensive or that cannot rely on raster caching. For example, scale and
/// skew animations are often expensive to perform on complex children, as are
/// blurs. For a short animation, a widget that contains these expensive effects
/// can be replaced with a snapshot of itself and manipulated instead.
///
///
/// By default, the child is drawn as is. The default [delegate] simply scales
/// For example, the Android Q [ZoomPageTransitionsBuilder] uses a snapshot widget
/// down the image by the current device pixel ratio and paints it into the
/// for the forward and entering route to avoid the expensive scale animation.
/// canvas. How this image is drawn can be customized by providing a new
/// This also has the effect of briefly pausing any animations on the page.
/// subclass of [RasterWidgetDelegate] to the [delegate] argument.
///
/// Generally, this widget should not be used in places where users expect the
/// child widget to continue animating or to be responsive, such as an unbounded
/// animation.
///
///
/// Caveats:
/// Caveats:
///
///
///
The contents of platform views cannot be captured by a raster
///
* The contents of platform views cannot be captured by a snapshot
///
widget. If a platform view is encountered, then the raster
widget will
///
widget. If a platform view is encountered, then the snapshot
widget will
///
determine how to render its children based on the [Rasterize
Mode]. This
///
determine how to render its children based on the [Snapshot
Mode]. This
///
defaults to [RasterizeMode.enabled] which will throw an exception if a platform
///
defaults to [SnapshotMode.normal] which will throw an exception if a
/// view is encountered.
///
platform
view is encountered.
///
///
/// This widget is not supported on the HTML backend of Flutter for the web.
/// * The snapshotting functionality of this widget is not supported on the HTML
class
RasterWidget
extends
SingleChildRenderObjectWidget
{
/// backend of Flutter for the Web. Setting [SnapshotController.allowSnapshotting] to true
/// Create a new [RasterWidget].
/// may cause an error to be thrown. On the CanvasKit backend of Flutter, the
/// performance of using this widget may regress performance due to the fact
/// that both the UI and engine share a single thread.
class
SnapshotWidget
extends
SingleChildRenderObjectWidget
{
/// Create a new [SnapshotWidget].
///
///
/// The [controller] and [child] arguments are required.
/// The [controller] and [child] arguments are required.
const
Raster
Widget
({
const
Snapshot
Widget
({
super
.
key
,
super
.
key
,
this
.
delegate
=
const
_RasterDefaultDelegate
(),
this
.
mode
=
SnapshotMode
.
normal
,
this
.
fallback
,
this
.
painter
=
const
_DefaultSnapshotPainter
(),
this
.
mode
=
RasterizeMode
.
enabled
,
required
this
.
controller
,
required
this
.
controller
,
required
super
.
child
required
super
.
child
});
});
/// A delegate that allows customization of how the image is painted.
/// The controller that determines when to display the children as a snapshot.
///
final
SnapshotController
controller
;
/// If not provided, defaults to a delegate which paints the child as is.
final
RasterWidgetDelegate
delegate
;
/// The controller that determines when to display the children as an image.
final
RasterWidgetController
controller
;
/// A fallback delegate which is used if the child layers contains a platform view.
final
RasterWidgetFallbackDelegate
?
fallback
;
/// Configuration that controls how the
raster widget decides to draw
its children.
/// Configuration that controls how the
snapshot widget decides to paint
its children.
///
///
/// Defaults to [
RasterizeMode.enabled
], which throws an error when a platform view
/// Defaults to [
SnapshotMode.normal
], which throws an error when a platform view
/// or
other un-rasterizabl
e view is encountered.
/// or
textur
e view is encountered.
///
///
/// See [RasterizeMode] for more information.
/// See [SnapshotMode] for more information.
final
RasterizeMode
mode
;
final
SnapshotMode
mode
;
/// The painter used to paint the child snapshot or child widgets.
final
SnapshotPainter
painter
;
@override
@override
RenderObject
createRenderObject
(
BuildContext
context
)
{
RenderObject
createRenderObject
(
BuildContext
context
)
{
return
RenderRasterWidget
(
debugCheckHasMediaQuery
(
context
);
delegate:
delegate
,
return
_RenderSnapshotWidget
(
controller:
controller
,
controller:
controller
,
fallback:
fallback
,
mode:
mode
,
mode:
mode
,
devicePixelRatio:
MediaQuery
.
maybeOf
(
context
)?.
devicePixelRatio
??
1.0
,
devicePixelRatio:
MediaQuery
.
of
(
context
).
devicePixelRatio
,
painter:
painter
,
);
);
}
}
@override
@override
void
updateRenderObject
(
BuildContext
context
,
covariant
Render
RasterWidge
t
renderObject
)
{
void
updateRenderObject
(
BuildContext
context
,
covariant
Render
Objec
t
renderObject
)
{
renderObject
debugCheckHasMediaQuery
(
context
);
..
delegate
=
delegate
(
renderObject
as
_RenderSnapshotWidget
)
..
controller
=
controller
..
controller
=
controller
..
fallback
=
fallback
..
mode
=
mode
..
mode
=
mode
..
devicePixelRatio
=
MediaQuery
.
maybeOf
(
context
)?.
devicePixelRatio
??
1.0
;
..
devicePixelRatio
=
MediaQuery
.
of
(
context
).
devicePixelRatio
..
painter
=
painter
;
}
}
}
}
/// A delegate which the [RasterWidget] can use to fallback to regular rendering
// A render object that conditionally converts its child into a [ui.Image]
/// if a platform view is present in the layer tree.
// and then paints it in place of the child.
///
class
_RenderSnapshotWidget
extends
RenderProxyBox
{
/// Consumers of [RasterWidget] should almost never use this delegate. For the most part,
// Create a new [_RenderSnapshotWidget].
/// the raster widget only functions as a performance improvement. If a platform view is
_RenderSnapshotWidget
({
/// present, the performance improving qualities aren't possible and using this API is
/// pointless.
///
/// Instead, this interface is useful if a generic/reusable widget is being created which
/// may include a platform view and it needs to handle this transparently. For example, the
/// framework uses this for the zoom page transition so that navigating to a page shows the same
/// animation whether or not there is a platform view.
abstract
class
RasterWidgetFallbackDelegate
{
/// const constructor so that subclasses can be const.
const
RasterWidgetFallbackDelegate
();
/// Paint the child via [painter], applying any effects that would have been painted
/// with the [RasterWidgetDelegate].
///
/// The [offset] and [size] are the location and dimensions of the render object.
void
paintFallback
(
PaintingContext
context
,
Offset
offset
,
Size
size
,
PaintingContextCallback
painter
);
}
/// A delegate used to draw the image representing the rasterized child.
///
/// The delegate can call [notifyListeners] to have the raster widget
/// re-paint (re-using the same raster). This allows animations to be connected
/// to the raster and performed without re-rasterization of children. For
/// certain scale or perspective changing transforms, such as a rotation, this
/// can be significantly faster than performing the same animation at the
/// widget level.
///
/// By default, the [RasterWidget] includes a delegate that draws the child raster
/// exactly as the child widgets would have been drawn. Nevertheless, this can
/// also be used to efficiently transform the child raster and apply complex paint
/// effects.
///
/// {@tool snippet}
///
/// The following method shows how to efficiently rotate the child raster.
///
/// ```dart
/// void paint(PaintingContext context, Offset offset, Size size, ui.Image image, double pixelRatio) {
/// const double radians = 0.5; // Could be driven by an animation.
/// final Matrix4 transform = Matrix4.rotationZ(radians);
/// context.canvas.transform(transform.storage);
/// final Rect src = Rect.fromLTWH(0, 0, image.width.toDouble(), image.height.toDouble());
/// final Rect dst = Rect.fromLTWH(offset.dx, offset.dy, size.width, size.height);
/// final Paint paint = Paint()
/// ..filterQuality = FilterQuality.low;
/// context.canvas.drawImageRect(image, src, dst, paint);
/// }
/// ```
/// {@end-tool}
abstract
class
RasterWidgetDelegate
extends
ChangeNotifier
{
/// Called whenever the [image] that represents a [RasterWidget]s child should be painted.
///
/// The image is rasterized at the physical pixel resolution and should be scaled down by
/// [pixelRatio] to account for device independent pixels.
///
/// There is no offset given in this paint method, as the parent is an [OffsetLayer] all
/// offsets are [Offset.zero].
///
/// {@tool snippet}
///
/// The follow method shows how the default implementation of the delegate used by the
/// [RasterWidget] paints the child image. This must account for the fact that the image
/// width and height will be given in physical pixels, while the image must be painted with
/// device independent pixels. That is, the width and height of the image is the widget and
/// height of the provided `size`, multiplied by the `pixelRatio`:
///
/// ```dart
/// void paint(PaintingContext context, Offset offset, Size size, ui.Image image, double pixelRatio) {
/// final Rect src = Rect.fromLTWH(0, 0, image.width.toDouble(), image.height.toDouble());
/// final Rect dst = Rect.fromLTWH(offset.dx, offset.dy, size.width, size.height);
/// final Paint paint = Paint()
/// ..filterQuality = FilterQuality.low;
/// context.canvas.drawImageRect(image, src, dst, paint);
/// }
/// ```
/// {@end-tool}
void
paint
(
PaintingContext
context
,
Offset
offset
,
Size
size
,
ui
.
Image
image
,
double
pixelRatio
);
/// Called whenever a new instance of the raster widget delegate class is
/// provided to the [RenderRasterWidget] object, or any time that a new
/// [RasterWidgetDelegate] object is created with a new instance of the
/// delegate class (which amounts to the same thing, because the latter is
/// implemented in terms of the former).
///
/// If the new instance represents different information than the old
/// instance, then the method should return true, otherwise it should return
/// false.
///
/// If the method returns false, then the [paint] call might be optimized
/// away.
///
/// It's possible that the [paint] method will get called even if
/// [shouldRepaint] returns false (e.g. if an ancestor or descendant needed to
/// be repainted). It's also possible that the [paint] method will get called
/// without [shouldRepaint] being called at all (e.g. if the box changes
/// size).
///
/// Changing the delegate will not cause the child image retained by the
/// [RenderRasterWidget] to be updated. Instead, [RasterWidgetController.clear] can
/// be used to force the generation of a new image.
///
/// The `oldDelegate` argument will never be null.
bool
shouldRepaint
(
covariant
RasterWidgetDelegate
oldDelegate
);
}
/// A render object that draws its child as a [ui.Image].
class
RenderRasterWidget
extends
RenderProxyBox
{
/// Create a new [RenderRasterWidget].
RenderRasterWidget
({
required
RasterWidgetDelegate
delegate
,
required
double
devicePixelRatio
,
required
double
devicePixelRatio
,
required
RasterWidgetController
controller
,
required
SnapshotController
controller
,
required
RasterizeMode
mode
,
required
SnapshotMode
mode
,
RasterWidgetFallbackDelegate
?
fallback
,
required
SnapshotPainter
painter
,
})
:
_delegate
=
delegate
,
})
:
_devicePixelRatio
=
devicePixelRatio
,
_devicePixelRatio
=
devicePixelRatio
,
_controller
=
controller
,
_controller
=
controller
,
_
fallback
=
fallback
,
_
mode
=
mode
,
_
mode
=
mode
;
_
painter
=
painter
;
/// The device pixel ratio used to create the child image.
/// The device pixel ratio used to create the child image.
double
get
devicePixelRatio
=>
_devicePixelRatio
;
double
get
devicePixelRatio
=>
_devicePixelRatio
;
...
@@ -274,61 +172,57 @@ class RenderRasterWidget extends RenderProxyBox {
...
@@ -274,61 +172,57 @@ class RenderRasterWidget extends RenderProxyBox {
return
;
return
;
}
}
_devicePixelRatio
=
value
;
_devicePixelRatio
=
value
;
if
(
_childRaster
==
null
)
{
return
;
}
else
{
_childRaster
?.
dispose
();
_childRaster
=
null
;
markNeedsPaint
();
markNeedsPaint
();
}
}
}
/// Whether a rasterized version of this render objects child is drawn in
/// The painter used to paint the child snapshot or child widgets.
/// place of the child.
SnapshotPainter
get
painter
=>
_painter
;
RasterWidgetController
get
controller
=>
_controller
;
SnapshotPainter
_painter
;
RasterWidgetController
_controller
;
set
painter
(
SnapshotPainter
value
)
{
set
controller
(
RasterWidgetController
value
)
{
if
(
value
==
painter
)
{
if
(
value
==
controller
)
{
return
;
return
;
}
}
controller
.
removeListener
(
_onRasterValueChanged
);
final
SnapshotPainter
oldPainter
=
painter
;
final
bool
oldValue
=
controller
.
rasterize
;
oldPainter
.
removeListener
(
markNeedsPaint
);
_controller
=
value
;
_painter
=
value
;
if
(
attached
)
{
if
(
oldPainter
.
runtimeType
!=
painter
.
runtimeType
||
controller
.
addListener
(
_onRasterValueChanged
);
painter
.
shouldRepaint
(
oldPainter
))
{
if
(
oldValue
!=
controller
.
rasterize
)
{
markNeedsPaint
();
_onRasterValueChanged
();
}
}
if
(
attached
)
{
painter
.
addListener
(
markNeedsPaint
);
}
}
}
}
/// The delegate used to draw the image representing the child.
/// A controller that determines whether to paint the child normally or to
RasterWidgetDelegate
get
delegate
=>
_delegate
;
/// paint a snapshotted version of that child.
RasterWidgetDelegate
_delegate
;
SnapshotController
get
controller
=>
_controller
;
set
delegate
(
RasterWidgetDelegate
value
)
{
SnapshotController
_controller
;
if
(
value
==
delegate
)
{
set
controller
(
SnapshotController
value
)
{
if
(
value
==
controller
)
{
return
;
return
;
}
}
delegate
.
removeListener
(
markNeedsPaint
);
controller
.
removeListener
(
_onRasterValueChanged
);
final
RasterWidgetDelegate
oldDelegate
=
_delegate
;
final
bool
oldValue
=
controller
.
allowSnapshotting
;
_
delegate
=
value
;
_
controller
=
value
;
if
(
attached
)
{
if
(
attached
)
{
delegate
.
addListener
(
markNeedsPaint
);
controller
.
addListener
(
_onRasterValueChanged
);
if
(
delegate
.
shouldRepaint
(
oldDelegate
))
{
if
(
oldValue
!=
controller
.
allowSnapshotting
)
{
markNeedsPaint
();
_onRasterValueChanged
();
}
}
}
}
/// A fallback delegate which is used if the child layers contains a platform view.
RasterWidgetFallbackDelegate
?
get
fallback
=>
_fallback
;
RasterWidgetFallbackDelegate
?
_fallback
;
set
fallback
(
RasterWidgetFallbackDelegate
?
value
)
{
if
(
value
==
fallback
)
{
return
;
}
}
_fallback
=
value
;
markNeedsPaint
();
}
}
/// How the
raster
widget will handle platform views in child layers.
/// How the
snapshot
widget will handle platform views in child layers.
Rasterize
Mode
get
mode
=>
_mode
;
Snapshot
Mode
get
mode
=>
_mode
;
Rasterize
Mode
_mode
;
Snapshot
Mode
_mode
;
set
mode
(
Rasterize
Mode
value
)
{
set
mode
(
Snapshot
Mode
value
)
{
if
(
value
==
_mode
)
{
if
(
value
==
_mode
)
{
return
;
return
;
}
}
...
@@ -337,18 +231,22 @@ class RenderRasterWidget extends RenderProxyBox {
...
@@ -337,18 +231,22 @@ class RenderRasterWidget extends RenderProxyBox {
}
}
ui
.
Image
?
_childRaster
;
ui
.
Image
?
_childRaster
;
// Set to true if the snapshot mode was not forced and a platform view
// was encountered while attempting to snapshot the child.
bool
_disableSnapshotAttempt
=
false
;
@override
@override
void
attach
(
covariant
PipelineOwner
owner
)
{
void
attach
(
covariant
PipelineOwner
owner
)
{
delegate
.
addListener
(
markNeedsPaint
);
controller
.
addListener
(
_onRasterValueChanged
);
controller
.
addListener
(
_onRasterValueChanged
);
painter
.
addListener
(
markNeedsPaint
);
super
.
attach
(
owner
);
super
.
attach
(
owner
);
}
}
@override
@override
void
detach
()
{
void
detach
()
{
delegate
.
removeListener
(
markNeedsPaint
)
;
_disableSnapshotAttempt
=
false
;
controller
.
removeListener
(
_onRasterValueChanged
);
controller
.
removeListener
(
_onRasterValueChanged
);
painter
.
removeListener
(
markNeedsPaint
);
_childRaster
?.
dispose
();
_childRaster
?.
dispose
();
_childRaster
=
null
;
_childRaster
=
null
;
super
.
detach
();
super
.
detach
();
...
@@ -356,22 +254,20 @@ class RenderRasterWidget extends RenderProxyBox {
...
@@ -356,22 +254,20 @@ class RenderRasterWidget extends RenderProxyBox {
@override
@override
void
dispose
()
{
void
dispose
()
{
delegate
.
removeListener
(
markNeedsPaint
);
controller
.
removeListener
(
_onRasterValueChanged
);
controller
.
removeListener
(
_onRasterValueChanged
);
painter
.
removeListener
(
markNeedsPaint
);
_childRaster
?.
dispose
();
_childRaster
?.
dispose
();
_childRaster
=
null
;
_childRaster
=
null
;
super
.
dispose
();
super
.
dispose
();
}
}
void
_onRasterValueChanged
()
{
void
_onRasterValueChanged
()
{
_disableSnapshotAttempt
=
false
;
_childRaster
?.
dispose
();
_childRaster
?.
dispose
();
_childRaster
=
null
;
_childRaster
=
null
;
markNeedsPaint
();
markNeedsPaint
();
}
}
bool
_hitPlatformView
=
false
;
bool
get
_useFallback
=>
_hitPlatformView
||
mode
==
RasterizeMode
.
fallback
;
// Paint [child] with this painting context, then convert to a raster and detach all
// Paint [child] with this painting context, then convert to a raster and detach all
// children from this layer.
// children from this layer.
ui
.
Image
?
_paintAndDetachToImage
()
{
ui
.
Image
?
_paintAndDetachToImage
()
{
...
@@ -383,15 +279,11 @@ class RenderRasterWidget extends RenderProxyBox {
...
@@ -383,15 +279,11 @@ class RenderRasterWidget extends RenderProxyBox {
// that would conflict with our goals of minimizing painting context.
// that would conflict with our goals of minimizing painting context.
// ignore: invalid_use_of_protected_member
// ignore: invalid_use_of_protected_member
context
.
stopRecordingIfNeeded
();
context
.
stopRecordingIfNeeded
();
if
(
mode
!=
RasterizeMode
.
forced
&&
!
offsetLayer
.
supportsRasterization
())
{
if
(
mode
!=
SnapshotMode
.
forced
&&
!
offsetLayer
.
supportsRasterization
())
{
_hitPlatformView
=
true
;
if
(
mode
==
SnapshotMode
.
normal
)
{
if
(
fallback
==
null
)
{
throw
FlutterError
(
'SnapshotWidget used with a child that contains a PlatformView.'
);
assert
(()
{
throw
FlutterError
(
'RasterWidget used with a child that contains a PlatformView.'
);
}());
}
}
_disableSnapshotAttempt
=
true
;
return
null
;
return
null
;
}
}
final
ui
.
Image
image
=
offsetLayer
.
toImageSync
(
Offset
.
zero
&
size
,
pixelRatio:
devicePixelRatio
);
final
ui
.
Image
image
=
offsetLayer
.
toImageSync
(
Offset
.
zero
&
size
,
pixelRatio:
devicePixelRatio
);
...
@@ -406,40 +298,117 @@ class RenderRasterWidget extends RenderProxyBox {
...
@@ -406,40 +298,117 @@ class RenderRasterWidget extends RenderProxyBox {
_childRaster
=
null
;
_childRaster
=
null
;
return
;
return
;
}
}
if
(
controller
.
rasterize
)
{
if
(!
controller
.
allowSnapshotting
||
_disableSnapshotAttempt
)
{
if
(
_useFallback
)
{
_childRaster
?.
dispose
();
fallback
?.
paintFallback
(
context
,
offset
,
size
,
super
.
paint
);
_childRaster
=
null
;
}
else
{
painter
.
paint
(
context
,
offset
,
size
,
super
.
paint
);
return
;
}
_childRaster
??=
_paintAndDetachToImage
();
_childRaster
??=
_paintAndDetachToImage
();
if
(
_childRaster
==
null
&&
_useFallback
)
{
if
(
_childRaster
==
null
)
{
fallback
?.
paintFallback
(
context
,
offset
,
size
,
super
.
paint
);
painter
.
paint
(
context
,
offset
,
size
,
super
.
paint
);
}
else
{
}
else
{
delegate
.
paint
(
context
,
offset
,
size
,
_childRaster
!,
devicePixelRatio
);
painter
.
paintSnapshot
(
context
,
offset
,
size
,
_childRaster
!,
devicePixelRatio
);
}
}
}
return
;
return
;
}
}
_childRaster
?.
dispose
();
_childRaster
=
null
;
super
.
paint
(
context
,
offset
);
}
}
}
// A delegate that paints the child widget as is.
/// A painter used to paint either a snapshot or the child widgets that
class
_RasterDefaultDelegate
implements
RasterWidgetDelegate
{
/// would be a snapshot.
const
_RasterDefaultDelegate
();
///
/// The painter can call [notifyListeners] to have the [SnapshotWidget]
/// re-paint (re-using the same raster). This allows animations to be performed
/// without re-snapshotting of children. For certain scale or perspective changing
/// transforms, such as a rotation, this can be significantly faster than performing
/// the same animation at the widget level.
///
/// By default, the [SnapshotWidget] includes a delegate that draws the child raster
/// exactly as the child widgets would have been drawn. Nevertheless, this can
/// also be used to efficiently transform the child raster and apply complex paint
/// effects.
///
/// {@tool snippet}
///
/// The following method shows how to efficiently rotate the child raster.
///
/// ```dart
/// void paint(PaintingContext context, Offset offset, Size size, ui.Image image, double pixelRatio) {
/// const double radians = 0.5; // Could be driven by an animation.
/// final Matrix4 transform = Matrix4.rotationZ(radians);
/// context.canvas.transform(transform.storage);
/// final Rect src = Rect.fromLTWH(0, 0, image.width.toDouble(), image.height.toDouble());
/// final Rect dst = Rect.fromLTWH(offset.dx, offset.dy, size.width, size.height);
/// final Paint paint = Paint()
/// ..filterQuality = FilterQuality.low;
/// context.canvas.drawImageRect(image, src, dst, paint);
/// }
/// ```
/// {@end-tool}
abstract
class
SnapshotPainter
extends
ChangeNotifier
{
/// Called whenever the [image] that represents a [SnapshotWidget]s child should be painted.
///
/// The image is rasterized at the physical pixel resolution and should be scaled down by
/// [pixelRatio] to account for device independent pixels.
///
/// {@tool snippet}
///
/// The following method shows how the default implementation of the delegate used by the
/// [SnapshotPainter] paints the snapshot. This must account for the fact that the image
/// width and height will be given in physical pixels, while the image must be painted with
/// device independent pixels. That is, the width and height of the image is the widget and
/// height of the provided `size`, multiplied by the `pixelRatio`:
///
/// ```dart
/// void paint(PaintingContext context, Offset offset, Size size, ui.Image image, double pixelRatio) {
/// final Rect src = Rect.fromLTWH(0, 0, image.width.toDouble(), image.height.toDouble());
/// final Rect dst = Rect.fromLTWH(offset.dx, offset.dy, size.width, size.height);
/// final Paint paint = Paint()
/// ..filterQuality = FilterQuality.low;
/// context.canvas.drawImageRect(image, src, dst, paint);
/// }
/// ```
/// {@end-tool}
void
paintSnapshot
(
PaintingContext
context
,
Offset
offset
,
Size
size
,
ui
.
Image
image
,
double
pixelRatio
);
@override
/// Paint the child via [painter], applying any effects that would have been painted
void
paint
(
PaintingContext
context
,
Offset
offset
,
Size
size
,
ui
.
Image
image
,
double
pixelRatio
)
{
/// in [SnapshotPainter.paintSnapshot].
final
Rect
src
=
Rect
.
fromLTWH
(
0
,
0
,
image
.
width
.
toDouble
(),
image
.
height
.
toDouble
());
///
final
Rect
dst
=
Rect
.
fromLTWH
(
offset
.
dx
,
offset
.
dy
,
size
.
width
,
size
.
height
);
/// This method is called when snapshotting is disabled, or when [SnapshotMode.permissive]
final
Paint
paint
=
Paint
()
/// is used and a child platform view prevents snapshotting.
..
filterQuality
=
FilterQuality
.
low
;
///
context
.
canvas
.
drawImageRect
(
image
,
src
,
dst
,
paint
);
/// The [offset] and [size] are the location and dimensions of the render object.
}
void
paint
(
PaintingContext
context
,
Offset
offset
,
Size
size
,
PaintingContextCallback
painter
);
@override
/// Called whenever a new instance of the snapshot widget delegate class is
bool
shouldRepaint
(
covariant
RasterWidgetDelegate
oldDelegate
)
=>
false
;
/// provided to the [SnapshotWidget] object, or any time that a new
/// [SnapshotPainter] object is created with a new instance of the
/// delegate class (which amounts to the same thing, because the latter is
/// implemented in terms of the former).
///
/// If the new instance represents different information than the old
/// instance, then the method should return true, otherwise it should return
/// false.
///
/// If the method returns false, then the [paint] call might be optimized
/// away.
///
/// It's possible that the [paint] method will get called even if
/// [shouldRepaint] returns false (e.g. if an ancestor or descendant needed to
/// be repainted). It's also possible that the [paint] method will get called
/// without [shouldRepaint] being called at all (e.g. if the box changes
/// size).
///
/// Changing the delegate will not cause the child image retained by the
/// [SnapshotWidget] to be updated. Instead, [SnapshotController.clear] can
/// be used to force the generation of a new image.
///
/// The `oldPainter` argument will never be null.
bool
shouldRepaint
(
covariant
SnapshotPainter
oldPainter
);
}
class
_DefaultSnapshotPainter
implements
SnapshotPainter
{
const
_DefaultSnapshotPainter
();
@override
@override
void
addListener
(
ui
.
VoidCallback
listener
)
{
}
void
addListener
(
ui
.
VoidCallback
listener
)
{
}
...
@@ -453,6 +422,23 @@ class _RasterDefaultDelegate implements RasterWidgetDelegate {
...
@@ -453,6 +422,23 @@ class _RasterDefaultDelegate implements RasterWidgetDelegate {
@override
@override
void
notifyListeners
()
{
}
void
notifyListeners
()
{
}
@override
void
paint
(
PaintingContext
context
,
ui
.
Offset
offset
,
ui
.
Size
size
,
PaintingContextCallback
painter
)
{
painter
(
context
,
offset
);
}
@override
void
paintSnapshot
(
PaintingContext
context
,
ui
.
Offset
offset
,
ui
.
Size
size
,
ui
.
Image
image
,
double
pixelRatio
)
{
final
Rect
src
=
Rect
.
fromLTWH
(
0
,
0
,
image
.
width
.
toDouble
(),
image
.
height
.
toDouble
());
final
Rect
dst
=
Rect
.
fromLTWH
(
offset
.
dx
,
offset
.
dy
,
size
.
width
,
size
.
height
);
final
Paint
paint
=
Paint
()
..
filterQuality
=
FilterQuality
.
low
;
context
.
canvas
.
drawImageRect
(
image
,
src
,
dst
,
paint
);
}
@override
@override
void
removeListener
(
ui
.
VoidCallback
listener
)
{
}
void
removeListener
(
ui
.
VoidCallback
listener
)
{
}
@override
bool
shouldRepaint
(
covariant
_DefaultSnapshotPainter
oldPainter
)
=>
false
;
}
}
packages/flutter/lib/widgets.dart
View file @
637bd0fb
...
@@ -91,7 +91,6 @@ export 'src/widgets/platform_selectable_region_context_menu.dart';
...
@@ -91,7 +91,6 @@ export 'src/widgets/platform_selectable_region_context_menu.dart';
export
'src/widgets/platform_view.dart'
;
export
'src/widgets/platform_view.dart'
;
export
'src/widgets/preferred_size.dart'
;
export
'src/widgets/preferred_size.dart'
;
export
'src/widgets/primary_scroll_controller.dart'
;
export
'src/widgets/primary_scroll_controller.dart'
;
export
'src/widgets/raster_widget.dart'
;
export
'src/widgets/raw_keyboard_listener.dart'
;
export
'src/widgets/raw_keyboard_listener.dart'
;
export
'src/widgets/reorderable_list.dart'
;
export
'src/widgets/reorderable_list.dart'
;
export
'src/widgets/restoration.dart'
;
export
'src/widgets/restoration.dart'
;
...
@@ -127,6 +126,7 @@ export 'src/widgets/sliver_layout_builder.dart';
...
@@ -127,6 +126,7 @@ export 'src/widgets/sliver_layout_builder.dart';
export
'src/widgets/sliver_persistent_header.dart'
;
export
'src/widgets/sliver_persistent_header.dart'
;
export
'src/widgets/sliver_prototype_extent_list.dart'
;
export
'src/widgets/sliver_prototype_extent_list.dart'
;
export
'src/widgets/slotted_render_object_widget.dart'
;
export
'src/widgets/slotted_render_object_widget.dart'
;
export
'src/widgets/snapshot_widget.dart'
;
export
'src/widgets/spacer.dart'
;
export
'src/widgets/spacer.dart'
;
export
'src/widgets/spell_check.dart'
;
export
'src/widgets/spell_check.dart'
;
export
'src/widgets/status_transitions.dart'
;
export
'src/widgets/status_transitions.dart'
;
...
...
packages/flutter/test/material/dropdown_test.dart
View file @
637bd0fb
...
@@ -399,6 +399,8 @@ void main() {
...
@@ -399,6 +399,8 @@ void main() {
Widget
build
()
{
Widget
build
()
{
return
Directionality
(
return
Directionality
(
textDirection:
TextDirection
.
ltr
,
textDirection:
TextDirection
.
ltr
,
child:
MediaQuery
(
data:
MediaQueryData
.
fromWindow
(
WidgetsBinding
.
instance
.
window
),
child:
Navigator
(
child:
Navigator
(
initialRoute:
'/'
,
initialRoute:
'/'
,
onGenerateRoute:
(
RouteSettings
settings
)
{
onGenerateRoute:
(
RouteSettings
settings
)
{
...
@@ -412,6 +414,7 @@ void main() {
...
@@ -412,6 +414,7 @@ void main() {
);
);
},
},
),
),
),
);
);
}
}
...
...
packages/flutter/test/material/page_test.dart
View file @
637bd0fb
...
@@ -158,7 +158,7 @@ void main() {
...
@@ -158,7 +158,7 @@ void main() {
testWidgets
(
'test page transition (_ZoomPageTransition) without rasterization'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'test page transition (_ZoomPageTransition) without rasterization'
,
(
WidgetTester
tester
)
async
{
Iterable
<
Layer
>
findLayers
(
Finder
of
)
{
Iterable
<
Layer
>
findLayers
(
Finder
of
)
{
return
tester
.
layerListOf
(
return
tester
.
layerListOf
(
find
.
ancestor
(
of:
of
,
matching:
find
.
byType
(
Raster
Widget
)).
first
,
find
.
ancestor
(
of:
of
,
matching:
find
.
byType
(
Snapshot
Widget
)).
first
,
);
);
}
}
...
@@ -174,7 +174,7 @@ void main() {
...
@@ -174,7 +174,7 @@ void main() {
MaterialApp
(
MaterialApp
(
onGenerateRoute:
(
RouteSettings
settings
)
{
onGenerateRoute:
(
RouteSettings
settings
)
{
return
MaterialPageRoute
<
void
>(
return
MaterialPageRoute
<
void
>(
preferRasterization
:
false
,
allowSnapshotting
:
false
,
builder:
(
BuildContext
context
)
{
builder:
(
BuildContext
context
)
{
if
(
settings
.
name
==
'/'
)
{
if
(
settings
.
name
==
'/'
)
{
return
const
Material
(
child:
Text
(
'Page 1'
));
return
const
Material
(
child:
Text
(
'Page 1'
));
...
@@ -1004,8 +1004,7 @@ void main() {
...
@@ -1004,8 +1004,7 @@ void main() {
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
RootRestorationScope
(
RootRestorationScope
(
restorationId:
'root'
,
restorationId:
'root'
,
child:
Directionality
(
child:
TestDependencies
(
textDirection:
TextDirection
.
ltr
,
child:
Navigator
(
child:
Navigator
(
onPopPage:
(
Route
<
dynamic
>
route
,
dynamic
result
)
{
return
false
;
},
onPopPage:
(
Route
<
dynamic
>
route
,
dynamic
result
)
{
return
false
;
},
pages:
const
<
Page
<
Object
?>>[
pages:
const
<
Page
<
Object
?>>[
...
@@ -1177,3 +1176,20 @@ class _TestRestorableWidgetState extends State<TestRestorableWidget> with Restor
...
@@ -1177,3 +1176,20 @@ class _TestRestorableWidgetState extends State<TestRestorableWidget> with Restor
);
);
}
}
}
}
class
TestDependencies
extends
StatelessWidget
{
const
TestDependencies
({
required
this
.
child
,
super
.
key
});
final
Widget
child
;
@override
Widget
build
(
BuildContext
context
)
{
return
Directionality
(
textDirection:
TextDirection
.
ltr
,
child:
MediaQuery
(
data:
MediaQueryData
.
fromWindow
(
WidgetsBinding
.
instance
.
window
),
child:
child
,
),
);
}
}
packages/flutter/test/material/text_field_test.dart
View file @
637bd0fb
...
@@ -1821,7 +1821,7 @@ void main() {
...
@@ -1821,7 +1821,7 @@ void main() {
// Wait for context menu to be built.
// Wait for context menu to be built.
await
tester
.
pumpAndSettle
();
await
tester
.
pumpAndSettle
();
final
RenderBox
container
=
tester
.
renderObject
(
find
.
descendant
(
final
RenderBox
container
=
tester
.
renderObject
(
find
.
descendant
(
of:
find
.
byType
(
Raster
Widget
),
of:
find
.
byType
(
Snapshot
Widget
),
matching:
find
.
byType
(
SizedBox
),
matching:
find
.
byType
(
SizedBox
),
).
first
);
).
first
);
expect
(
container
.
size
,
Size
.
zero
);
expect
(
container
.
size
,
Size
.
zero
);
...
...
packages/flutter/test/widgets/heroes_test.dart
View file @
637bd0fb
...
@@ -327,8 +327,7 @@ Future<void> main() async {
...
@@ -327,8 +327,7 @@ Future<void> main() async {
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
HeroControllerScope
(
HeroControllerScope
(
controller:
HeroController
(),
controller:
HeroController
(),
child:
Directionality
(
child:
TestDependencies
(
textDirection:
TextDirection
.
ltr
,
child:
Navigator
(
child:
Navigator
(
key:
key
,
key:
key
,
initialRoute:
'navigator1'
,
initialRoute:
'navigator1'
,
...
@@ -382,8 +381,7 @@ Future<void> main() async {
...
@@ -382,8 +381,7 @@ Future<void> main() async {
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
HeroControllerScope
(
HeroControllerScope
(
controller:
HeroController
(),
controller:
HeroController
(),
child:
Directionality
(
child:
TestDependencies
(
textDirection:
TextDirection
.
ltr
,
child:
Navigator
(
child:
Navigator
(
key:
key
,
key:
key
,
initialRoute:
'navigator1'
,
initialRoute:
'navigator1'
,
...
@@ -3160,3 +3158,20 @@ Future<void> main() async {
...
@@ -3160,3 +3158,20 @@ Future<void> main() async {
},
},
);
);
}
}
class
TestDependencies
extends
StatelessWidget
{
const
TestDependencies
({
required
this
.
child
,
super
.
key
});
final
Widget
child
;
@override
Widget
build
(
BuildContext
context
)
{
return
Directionality
(
textDirection:
TextDirection
.
ltr
,
child:
MediaQuery
(
data:
MediaQueryData
.
fromWindow
(
WidgetsBinding
.
instance
.
window
),
child:
child
,
),
);
}
}
packages/flutter/test/widgets/navigator_restoration_test.dart
View file @
637bd0fb
...
@@ -1042,9 +1042,12 @@ class PagedTestWidget extends StatelessWidget {
...
@@ -1042,9 +1042,12 @@ class PagedTestWidget extends StatelessWidget {
Widget
build
(
BuildContext
context
)
{
Widget
build
(
BuildContext
context
)
{
return
RootRestorationScope
(
return
RootRestorationScope
(
restorationId:
restorationId
,
restorationId:
restorationId
,
child:
const
Directionality
(
child:
Directionality
(
textDirection:
TextDirection
.
ltr
,
textDirection:
TextDirection
.
ltr
,
child:
PagedTestNavigator
(),
child:
MediaQuery
(
data:
MediaQueryData
.
fromWindow
(
WidgetsBinding
.
instance
.
window
),
child:
const
PagedTestNavigator
(),
),
),
),
);
);
}
}
...
@@ -1167,6 +1170,8 @@ class TestWidget extends StatelessWidget {
...
@@ -1167,6 +1170,8 @@ class TestWidget extends StatelessWidget {
restorationId:
restorationId
,
restorationId:
restorationId
,
child:
Directionality
(
child:
Directionality
(
textDirection:
TextDirection
.
ltr
,
textDirection:
TextDirection
.
ltr
,
child:
MediaQuery
(
data:
MediaQueryData
.
fromWindow
(
WidgetsBinding
.
instance
.
window
),
child:
Navigator
(
child:
Navigator
(
initialRoute:
'home'
,
initialRoute:
'home'
,
restorationScopeId:
'app'
,
restorationScopeId:
'app'
,
...
@@ -1183,6 +1188,7 @@ class TestWidget extends StatelessWidget {
...
@@ -1183,6 +1188,7 @@ class TestWidget extends StatelessWidget {
},
},
),
),
),
),
),
);
);
}
}
}
}
...
...
packages/flutter/test/widgets/navigator_test.dart
View file @
637bd0fb
...
@@ -2,8 +2,6 @@
...
@@ -2,8 +2,6 @@
// 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
'dart:ui'
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter/scheduler.dart'
;
import
'package:flutter/scheduler.dart'
;
...
@@ -201,8 +199,7 @@ void main() {
...
@@ -201,8 +199,7 @@ void main() {
};
};
final
GlobalKey
<
NavigatorState
>
navigator
=
GlobalKey
<
NavigatorState
>();
final
GlobalKey
<
NavigatorState
>
navigator
=
GlobalKey
<
NavigatorState
>();
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
Directionality
(
TestDependencies
(
textDirection:
TextDirection
.
ltr
,
child:
Navigator
(
child:
Navigator
(
key:
navigator
,
key:
navigator
,
pages:
pages
,
pages:
pages
,
...
@@ -566,8 +563,7 @@ void main() {
...
@@ -566,8 +563,7 @@ void main() {
}
}
final
TabController
controller
=
TabController
(
length:
3
,
vsync:
tester
);
final
TabController
controller
=
TabController
(
length:
3
,
vsync:
tester
);
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
Directionality
(
TestDependencies
(
textDirection:
TextDirection
.
ltr
,
child:
TabBarView
(
child:
TabBarView
(
controller:
controller
,
controller:
controller
,
children:
<
Widget
>[
children:
<
Widget
>[
...
@@ -598,8 +594,7 @@ void main() {
...
@@ -598,8 +594,7 @@ void main() {
);
);
}
}
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
Directionality
(
TestDependencies
(
textDirection:
TextDirection
.
ltr
,
child:
buildNavigator
(),
child:
buildNavigator
(),
),
),
);
);
...
@@ -608,8 +603,7 @@ void main() {
...
@@ -608,8 +603,7 @@ void main() {
pages
.
add
(
const
MaterialPage
<
void
>(
child:
Text
(
'Page 2'
)));
pages
.
add
(
const
MaterialPage
<
void
>(
child:
Text
(
'Page 2'
)));
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
Directionality
(
TestDependencies
(
textDirection:
TextDirection
.
ltr
,
child:
buildNavigator
(),
child:
buildNavigator
(),
),
),
);
);
...
@@ -641,8 +635,7 @@ void main() {
...
@@ -641,8 +635,7 @@ void main() {
);
);
}
}
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
Directionality
(
TestDependencies
(
textDirection:
TextDirection
.
ltr
,
child:
buildNavigator
(),
child:
buildNavigator
(),
),
),
);
);
...
@@ -659,8 +652,7 @@ void main() {
...
@@ -659,8 +652,7 @@ void main() {
];
];
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
Directionality
(
TestDependencies
(
textDirection:
TextDirection
.
ltr
,
child:
buildNavigator
(),
child:
buildNavigator
(),
),
),
);
);
...
@@ -1904,8 +1896,7 @@ void main() {
...
@@ -1904,8 +1896,7 @@ void main() {
testWidgets
(
'initial routes below opaque route are offstage'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'initial routes below opaque route are offstage'
,
(
WidgetTester
tester
)
async
{
final
GlobalKey
<
NavigatorState
>
testKey
=
GlobalKey
<
NavigatorState
>();
final
GlobalKey
<
NavigatorState
>
testKey
=
GlobalKey
<
NavigatorState
>();
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
Directionality
(
TestDependencies
(
textDirection:
TextDirection
.
ltr
,
child:
Navigator
(
child:
Navigator
(
key:
testKey
,
key:
testKey
,
initialRoute:
'/a/b'
,
initialRoute:
'/a/b'
,
...
@@ -1947,8 +1938,7 @@ void main() {
...
@@ -1947,8 +1938,7 @@ void main() {
bool
onGenerateInitialRoutesCalled
=
false
;
bool
onGenerateInitialRoutesCalled
=
false
;
final
GlobalKey
<
NavigatorState
>
testKey
=
GlobalKey
<
NavigatorState
>();
final
GlobalKey
<
NavigatorState
>
testKey
=
GlobalKey
<
NavigatorState
>();
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
Directionality
(
TestDependencies
(
textDirection:
TextDirection
.
ltr
,
child:
Navigator
(
child:
Navigator
(
key:
testKey
,
key:
testKey
,
initialRoute:
'Hello World'
,
initialRoute:
'Hello World'
,
...
@@ -2074,8 +2064,7 @@ void main() {
...
@@ -2074,8 +2064,7 @@ void main() {
final
Map
<
String
,
MaterialPageRoute
<
dynamic
>>
routeNameToContext
=
<
String
,
MaterialPageRoute
<
dynamic
>>{};
final
Map
<
String
,
MaterialPageRoute
<
dynamic
>>
routeNameToContext
=
<
String
,
MaterialPageRoute
<
dynamic
>>{};
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
Directionality
(
TestDependencies
(
textDirection:
TextDirection
.
ltr
,
child:
Navigator
(
child:
Navigator
(
key:
navigator
,
key:
navigator
,
initialRoute:
'root'
,
initialRoute:
'root'
,
...
@@ -2154,8 +2143,7 @@ void main() {
...
@@ -2154,8 +2143,7 @@ void main() {
Widget
widgetUnderTest
({
required
bool
enabled
})
{
Widget
widgetUnderTest
({
required
bool
enabled
})
{
return
TickerMode
(
return
TickerMode
(
enabled:
enabled
,
enabled:
enabled
,
child:
Directionality
(
child:
TestDependencies
(
textDirection:
TextDirection
.
ltr
,
child:
Navigator
(
child:
Navigator
(
initialRoute:
'root'
,
initialRoute:
'root'
,
onGenerateRoute:
(
RouteSettings
settings
)
{
onGenerateRoute:
(
RouteSettings
settings
)
{
...
@@ -2261,8 +2249,7 @@ void main() {
...
@@ -2261,8 +2249,7 @@ void main() {
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
HeroControllerScope
(
HeroControllerScope
(
controller:
spy
,
controller:
spy
,
child:
Directionality
(
child:
TestDependencies
(
textDirection:
TextDirection
.
ltr
,
child:
Navigator
(
child:
Navigator
(
key:
top
,
key:
top
,
initialRoute:
'top1'
,
initialRoute:
'top1'
,
...
@@ -2332,8 +2319,7 @@ void main() {
...
@@ -2332,8 +2319,7 @@ void main() {
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
HeroControllerScope
(
HeroControllerScope
(
controller:
spy
,
controller:
spy
,
child:
Directionality
(
child:
TestDependencies
(
textDirection:
TextDirection
.
ltr
,
child:
Navigator
(
child:
Navigator
(
key:
key1
,
key:
key1
,
initialRoute:
'navigator1'
,
initialRoute:
'navigator1'
,
...
@@ -2353,8 +2339,7 @@ void main() {
...
@@ -2353,8 +2339,7 @@ void main() {
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
HeroControllerScope
(
HeroControllerScope
(
controller:
spy
,
controller:
spy
,
child:
Directionality
(
child:
TestDependencies
(
textDirection:
TextDirection
.
ltr
,
child:
Navigator
(
child:
Navigator
(
key:
key2
,
key:
key2
,
initialRoute:
'navigator2'
,
initialRoute:
'navigator2'
,
...
@@ -2412,8 +2397,7 @@ void main() {
...
@@ -2412,8 +2397,7 @@ void main() {
);
);
};
};
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
Directionality
(
TestDependencies
(
textDirection:
TextDirection
.
ltr
,
child:
Stack
(
child:
Stack
(
children:
<
Widget
>[
children:
<
Widget
>[
HeroControllerScope
(
HeroControllerScope
(
...
@@ -2459,8 +2443,7 @@ void main() {
...
@@ -2459,8 +2443,7 @@ void main() {
// Swaps the spies.
// Swaps the spies.
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
Directionality
(
TestDependencies
(
textDirection:
TextDirection
.
ltr
,
child:
Stack
(
child:
Stack
(
children:
<
Widget
>[
children:
<
Widget
>[
HeroControllerScope
(
HeroControllerScope
(
...
@@ -2532,8 +2515,7 @@ void main() {
...
@@ -2532,8 +2515,7 @@ void main() {
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
HeroControllerScope
(
HeroControllerScope
(
controller:
spy
,
controller:
spy
,
child:
Directionality
(
child:
TestDependencies
(
textDirection:
TextDirection
.
ltr
,
child:
Stack
(
child:
Stack
(
children:
<
Widget
>[
children:
<
Widget
>[
Navigator
(
Navigator
(
...
@@ -2571,8 +2553,7 @@ void main() {
...
@@ -2571,8 +2553,7 @@ void main() {
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
HeroControllerScope
(
HeroControllerScope
(
controller:
spy
,
controller:
spy
,
child:
Directionality
(
child:
TestDependencies
(
textDirection:
TextDirection
.
ltr
,
child:
Stack
(
child:
Stack
(
children:
<
Widget
>[
children:
<
Widget
>[
Navigator
(
Navigator
(
...
@@ -2637,8 +2618,7 @@ void main() {
...
@@ -2637,8 +2618,7 @@ void main() {
DefaultMaterialLocalizations
.
delegate
,
DefaultMaterialLocalizations
.
delegate
,
DefaultWidgetsLocalizations
.
delegate
,
DefaultWidgetsLocalizations
.
delegate
,
],
],
child:
Directionality
(
child:
TestDependencies
(
textDirection:
TextDirection
.
ltr
,
child:
Navigator
(
child:
Navigator
(
key:
key
,
key:
key
,
pages:
pages
,
pages:
pages
,
...
@@ -2736,8 +2716,7 @@ void main() {
...
@@ -2736,8 +2716,7 @@ void main() {
DefaultMaterialLocalizations
.
delegate
,
DefaultMaterialLocalizations
.
delegate
,
DefaultWidgetsLocalizations
.
delegate
,
DefaultWidgetsLocalizations
.
delegate
,
],
],
child:
Directionality
(
child:
TestDependencies
(
textDirection:
TextDirection
.
ltr
,
child:
Navigator
(
child:
Navigator
(
pages:
myPages
,
pages:
myPages
,
),
),
...
@@ -2832,8 +2811,7 @@ void main() {
...
@@ -2832,8 +2811,7 @@ void main() {
DefaultMaterialLocalizations
.
delegate
,
DefaultMaterialLocalizations
.
delegate
,
DefaultWidgetsLocalizations
.
delegate
,
DefaultWidgetsLocalizations
.
delegate
,
],
],
child:
Directionality
(
child:
TestDependencies
(
textDirection:
TextDirection
.
ltr
,
child:
Navigator
(
child:
Navigator
(
pages:
myPages
,
pages:
myPages
,
),
),
...
@@ -3086,8 +3064,7 @@ void main() {
...
@@ -3086,8 +3064,7 @@ void main() {
testWidgets
(
'Pop no animation page does not crash'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'Pop no animation page does not crash'
,
(
WidgetTester
tester
)
async
{
// Regression Test for https://github.com/flutter/flutter/issues/86604.
// Regression Test for https://github.com/flutter/flutter/issues/86604.
Widget
buildNavigator
(
bool
secondPage
)
{
Widget
buildNavigator
(
bool
secondPage
)
{
return
Directionality
(
return
TestDependencies
(
textDirection:
TextDirection
.
ltr
,
child:
Navigator
(
child:
Navigator
(
pages:
<
Page
<
void
>>[
pages:
<
Page
<
void
>>[
const
ZeroDurationPage
(
const
ZeroDurationPage
(
...
@@ -3691,8 +3668,7 @@ void main() {
...
@@ -3691,8 +3668,7 @@ void main() {
testWidgets
(
'Can reuse NavigatorObserver in rebuilt tree'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'Can reuse NavigatorObserver in rebuilt tree'
,
(
WidgetTester
tester
)
async
{
final
NavigatorObserver
observer
=
NavigatorObserver
();
final
NavigatorObserver
observer
=
NavigatorObserver
();
Widget
build
([
Key
?
key
])
{
Widget
build
([
Key
?
key
])
{
return
Directionality
(
return
TestDependencies
(
textDirection:
TextDirection
.
ltr
,
child:
Navigator
(
child:
Navigator
(
key:
key
,
key:
key
,
observers:
<
NavigatorObserver
>[
observer
],
observers:
<
NavigatorObserver
>[
observer
],
...
@@ -3869,8 +3845,7 @@ void main() {
...
@@ -3869,8 +3845,7 @@ void main() {
testWidgets
(
'class implementing NavigatorObserver can be used without problems'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'class implementing NavigatorObserver can be used without problems'
,
(
WidgetTester
tester
)
async
{
final
_MockNavigatorObserver
observer
=
_MockNavigatorObserver
();
final
_MockNavigatorObserver
observer
=
_MockNavigatorObserver
();
Widget
build
([
Key
?
key
])
{
Widget
build
([
Key
?
key
])
{
return
Directionality
(
return
TestDependencies
(
textDirection:
TextDirection
.
ltr
,
child:
Navigator
(
child:
Navigator
(
key:
key
,
key:
key
,
observers:
<
NavigatorObserver
>[
observer
],
observers:
<
NavigatorObserver
>[
observer
],
...
@@ -4122,7 +4097,7 @@ class ZeroDurationPage extends Page<void> {
...
@@ -4122,7 +4097,7 @@ class ZeroDurationPage extends Page<void> {
class
ZeroDurationPageRoute
extends
PageRoute
<
void
>
{
class
ZeroDurationPageRoute
extends
PageRoute
<
void
>
{
ZeroDurationPageRoute
({
required
ZeroDurationPage
page
})
ZeroDurationPageRoute
({
required
ZeroDurationPage
page
})
:
super
(
settings:
page
,
preferRasterization
:
false
);
:
super
(
settings:
page
,
allowSnapshotting
:
false
);
@override
@override
Duration
get
transitionDuration
=>
Duration
.
zero
;
Duration
get
transitionDuration
=>
Duration
.
zero
;
...
@@ -4163,3 +4138,20 @@ class _MockNavigatorObserver implements NavigatorObserver {
...
@@ -4163,3 +4138,20 @@ class _MockNavigatorObserver implements NavigatorObserver {
return
null
;
return
null
;
}
}
}
}
class
TestDependencies
extends
StatelessWidget
{
const
TestDependencies
({
super
.
key
,
required
this
.
child
});
final
Widget
child
;
@override
Widget
build
(
BuildContext
context
)
{
return
MediaQuery
(
data:
MediaQueryData
.
fromWindow
(
WidgetsBinding
.
instance
.
window
),
child:
Directionality
(
textDirection:
TextDirection
.
ltr
,
child:
child
,
)
);
}
}
packages/flutter/test/widgets/scroll_position_test.dart
View file @
637bd0fb
...
@@ -33,6 +33,8 @@ Future<void> performTest(WidgetTester tester, bool maintainState) async {
...
@@ -33,6 +33,8 @@ Future<void> performTest(WidgetTester tester, bool maintainState) async {
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
Directionality
(
Directionality
(
textDirection:
TextDirection
.
ltr
,
textDirection:
TextDirection
.
ltr
,
child:
MediaQuery
(
data:
MediaQueryData
.
fromWindow
(
WidgetsBinding
.
instance
.
window
),
child:
Navigator
(
child:
Navigator
(
key:
navigatorKey
,
key:
navigatorKey
,
onGenerateRoute:
(
RouteSettings
settings
)
{
onGenerateRoute:
(
RouteSettings
settings
)
{
...
@@ -53,6 +55,7 @@ Future<void> performTest(WidgetTester tester, bool maintainState) async {
...
@@ -53,6 +55,7 @@ Future<void> performTest(WidgetTester tester, bool maintainState) async {
},
},
),
),
),
),
),
);
);
// we're 600 pixels high, each item is 100 pixels high, scroll position is
// we're 600 pixels high, each item is 100 pixels high, scroll position is
...
...
packages/flutter/test/widgets/
raster
_widget_test.dart
→
packages/flutter/test/widgets/
snapshot
_widget_test.dart
View file @
637bd0fb
...
@@ -14,13 +14,13 @@ import 'package:flutter/widgets.dart';
...
@@ -14,13 +14,13 @@ import 'package:flutter/widgets.dart';
import
'package:flutter_test/flutter_test.dart'
;
import
'package:flutter_test/flutter_test.dart'
;
void
main
(
)
{
void
main
(
)
{
testWidgets
(
'
Raster
Widget can rasterize child'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'
Snapshot
Widget can rasterize child'
,
(
WidgetTester
tester
)
async
{
final
RasterWidgetController
controller
=
RasterWidgetController
(
rasterize
:
true
);
final
SnapshotController
controller
=
SnapshotController
(
allowSnapshotting
:
true
);
final
Key
key
=
UniqueKey
();
final
Key
key
=
UniqueKey
();
await
tester
.
pumpWidget
(
RepaintBoundary
(
await
tester
.
pumpWidget
(
RepaintBoundary
(
key:
key
,
key:
key
,
child:
Center
(
child:
TestDependencies
(
child:
Raster
Widget
(
child:
Snapshot
Widget
(
controller:
controller
,
controller:
controller
,
child:
Container
(
child:
Container
(
width:
100
,
width:
100
,
...
@@ -30,151 +30,107 @@ void main() {
...
@@ -30,151 +30,107 @@ void main() {
),
),
),
),
));
));
// Rasterization is not actually complete until a frame has been pumped through
// the engine.
await
tester
.
pumpAndSettle
();
await
expectLater
(
find
.
byKey
(
key
),
matchesGoldenFile
(
'raster_widget.yellow.png'
));
await
expectLater
(
find
.
byKey
(
key
),
matchesGoldenFile
(
'raster_widget.yellow.png'
));
},
skip:
kIsWeb
);
// TODO(jonahwilliams): https://github.com/flutter/flutter/issues/106689
testWidgets
(
'RasterWidget is not a repaint boundary when rasterizing'
,
(
WidgetTester
tester
)
async
{
// Now change the color and assert the old snapshot still matches.
final
RasterWidgetController
controller
=
RasterWidgetController
(
rasterize:
true
);
await
tester
.
pumpWidget
(
RepaintBoundary
(
await
tester
.
pumpWidget
(
RepaintBoundary
(
child:
Center
(
key:
key
,
child:
RasterWidget
(
child:
TestDependencies
(
child:
SnapshotWidget
(
controller:
controller
,
controller:
controller
,
child:
Container
(
child:
Container
(
width:
100
,
width:
100
,
height:
100
,
height:
100
,
color:
const
Color
(
0xFFAA
BB11
),
color:
const
Color
(
0xFFAA
0000
),
),
),
),
),
),
),
));
));
await
expectLater
(
find
.
byKey
(
key
),
matchesGoldenFile
(
'raster_widget.yellow.png'
));
expect
(
tester
.
layers
,
hasLength
(
3
));
// Now invoke clear and the raster is re-generated.
expect
(
tester
.
layers
.
last
,
isA
<
PictureLayer
>());
controller
.
clear
();
controller
.
rasterize
=
false
;
await
tester
.
pump
();
await
tester
.
pump
();
expect
(
tester
.
layers
,
hasLength
(
3
));
await
expectLater
(
find
.
byKey
(
key
),
matchesGoldenFile
(
'raster_widget.red.png'
));
expect
(
tester
.
layers
.
last
,
isA
<
PictureLayer
>());
},
skip:
kIsWeb
);
// TODO(jonahwilliams): https://github.com/flutter/flutter/issues/106689
},
skip:
kIsWeb
);
// TODO(jonahwilliams): https://github.com/flutter/flutter/issues/106689
testWidgets
(
'RasterWidget repaints when RasterWidgetDelegate notifies listeners'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'Changing devicePixelRatio does not repaint if snapshotting is not enabled'
,
(
WidgetTester
tester
)
async
{
final
TestDelegate
delegate
=
TestDelegate
();
final
SnapshotController
controller
=
SnapshotController
();
final
RasterWidgetController
controller
=
RasterWidgetController
(
rasterize:
true
);
final
TestPainter
painter
=
TestPainter
();
await
tester
.
pumpWidget
(
RepaintBoundary
(
double
devicePixelRatio
=
1.0
;
child:
Center
(
late
StateSetter
localSetState
;
child:
RasterWidget
(
delegate:
delegate
,
controller:
controller
,
child:
Container
(
width:
100
,
height:
100
,
color:
const
Color
(
0xFFAABB11
),
),
),
),
));
expect
(
delegate
.
count
,
1
);
delegate
.
notify
();
await
tester
.
pump
();
expect
(
delegate
.
count
,
2
);
// Remove widget and verify removal of listeners.
await
tester
.
pumpWidget
(
const
SizedBox
());
delegate
.
notify
();
await
tester
.
pump
();
expect
(
delegate
.
count
,
2
);
},
skip:
kIsWeb
);
// TODO(jonahwilliams): https://github.com/flutter/flutter/issues/106689
testWidgets
(
'RasterWidget will recreate raster when controller calls clear'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
final
TestDelegate
delegate
=
TestDelegate
();
StatefulBuilder
(
builder:
(
BuildContext
context
,
StateSetter
setState
)
{
final
RasterWidgetController
controller
=
RasterWidgetController
(
rasterize:
true
)
;
localSetState
=
setState
;
await
tester
.
pumpWidget
(
RepaintBoundary
(
return
Center
(
child:
Center
(
child:
TestDependencies
(
child:
RasterWidget
(
devicePixelRatio:
devicePixelRatio
,
delegate:
delegate
,
child:
SnapshotWidget
(
controller:
controller
,
controller:
controller
,
child:
Container
(
painter:
painter
,
width:
100
,
child:
const
SizedBox
(
width:
100
,
height:
100
),
height:
100
,
color:
const
Color
(
0xFFAABB11
),
),
),
),
),
),
));
);
}),
);
expect
(
delegate
.
lastImage
,
isNotNull
);
expect
(
painter
.
count
,
1
);
final
ui
.
Image
lastImage
=
delegate
.
lastImage
!;
localSetState
(()
{
devicePixelRatio
=
2.0
;
});
await
tester
.
pump
();
await
tester
.
pump
();
// Raster is re-used
// Not repainted as dpr was not used.
expect
(
lastImage
,
equals
(
delegate
.
lastImage
));
expect
(
painter
.
count
,
1
);
controller
.
clear
();
await
tester
.
pump
();
// Raster is re-created.
expect
(
delegate
.
lastImage
,
isNotNull
);
expect
(
lastImage
,
isNot
(
delegate
.
lastImage
));
},
skip:
kIsWeb
);
// TODO(jonahwilliams): https://github.com/flutter/flutter/issues/106689
},
skip:
kIsWeb
);
// TODO(jonahwilliams): https://github.com/flutter/flutter/issues/106689
testWidgets
(
'RasterWidget can update the delegate'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'Changing devicePixelRatio forces raster regeneration'
,
(
WidgetTester
tester
)
async
{
final
TestDelegate
delegateA
=
TestDelegate
();
final
SnapshotController
controller
=
SnapshotController
(
allowSnapshotting:
true
);
final
TestDelegate
delegateB
=
TestDelegate
()
final
TestPainter
painter
=
TestPainter
();
..
shouldRepaintValue
=
true
;
double
devicePixelRatio
=
1.0
;
TestDelegate
delegate
=
delegateA
;
late
StateSetter
localSetState
;
final
RasterWidgetController
controller
=
RasterWidgetController
(
rasterize:
true
);
await
tester
.
pumpWidget
(
late
void
Function
(
void
Function
())
setStateFn
;
StatefulBuilder
(
builder:
(
BuildContext
context
,
StateSetter
setState
)
{
await
tester
.
pumpWidget
(
StatefulBuilder
(
localSetState
=
setState
;
builder:
(
BuildContext
context
,
void
Function
(
void
Function
())
setState
)
{
setStateFn
=
setState
;
return
Center
(
return
Center
(
child:
RasterWidget
(
child:
TestDependencies
(
delegate:
delegate
,
devicePixelRatio:
devicePixelRatio
,
child:
SnapshotWidget
(
controller:
controller
,
controller:
controller
,
child:
Container
(
painter:
painter
,
width:
100
,
child:
const
SizedBox
(
width:
100
,
height:
100
),
height:
100
,
color:
const
Color
(
0xFFAABB11
),
),
),
),
),
);
);
})
})
,
);
);
final
ui
.
Image
?
raster
=
painter
.
lastImage
;
expect
(
raster
,
isNotNull
);
expect
(
painter
.
count
,
1
);
expect
(
delegateA
.
count
,
1
);
localSetState
(()
{
expect
(
delegateB
.
count
,
0
);
devicePixelRatio
=
2.0
;
setStateFn
(()
{
delegate
=
delegateB
;
});
});
await
tester
.
pump
();
await
tester
.
pump
();
expect
(
delegateA
.
count
,
1
);
final
ui
.
Image
?
newRaster
=
painter
.
lastImage
;
expect
(
delegateB
.
count
,
1
);
expect
(
painter
.
count
,
2
);
expect
(
raster
,
isNot
(
newRaster
));
},
skip:
kIsWeb
);
// TODO(jonahwilliams): https://github.com/flutter/flutter/issues/106689
},
skip:
kIsWeb
);
// TODO(jonahwilliams): https://github.com/flutter/flutter/issues/106689
testWidgets
(
'RasterWidget can update the ValueNotifier'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'SnapshotWidget paints its child as a single picture layer'
,
(
WidgetTester
tester
)
async
{
final
TestDelegate
delegate
=
TestDelegate
();
final
SnapshotController
controller
=
SnapshotController
(
allowSnapshotting:
true
);
final
RasterWidgetController
controllerA
=
RasterWidgetController
(
rasterize:
true
);
await
tester
.
pumpWidget
(
RepaintBoundary
(
final
RasterWidgetController
controllerB
=
RasterWidgetController
();
child:
Center
(
RasterWidgetController
controller
=
controllerA
;
child:
TestDependencies
(
late
void
Function
(
void
Function
())
setStateFn
;
child:
SnapshotWidget
(
await
tester
.
pumpWidget
(
StatefulBuilder
(
builder:
(
BuildContext
context
,
void
Function
(
void
Function
())
setState
)
{
setStateFn
=
setState
;
return
Center
(
child:
RasterWidget
(
delegate:
delegate
,
controller:
controller
,
controller:
controller
,
child:
Container
(
child:
Container
(
width:
100
,
width:
100
,
...
@@ -182,155 +138,73 @@ void main() {
...
@@ -182,155 +138,73 @@ void main() {
color:
const
Color
(
0xFFAABB11
),
color:
const
Color
(
0xFFAABB11
),
),
),
),
),
);
),
})
),
);
));
expect
(
delegate
.
count
,
1
);
expect
(
tester
.
layers
.
last
,
isA
<
OffsetLayer
>());
setStateFn
(()
{
controller
=
controllerB
;
});
await
tester
.
pump
();
expect
(
delegate
.
count
,
1
);
expect
(
tester
.
layers
,
hasLength
(
3
)
);
expect
(
tester
.
layers
.
last
,
isA
<
PictureLayer
>());
expect
(
tester
.
layers
.
last
,
isA
<
PictureLayer
>());
// changes to old notifier do not impact widget.
controller
.
allowSnapshotting
=
false
;
controllerA
.
rasterize
=
false
;
await
tester
.
pump
();
await
tester
.
pump
();
expect
(
delegate
.
count
,
1
);
expect
(
tester
.
layers
,
hasLength
(
3
)
);
expect
(
tester
.
layers
.
last
,
isA
<
PictureLayer
>());
expect
(
tester
.
layers
.
last
,
isA
<
PictureLayer
>());
await
tester
.
pumpWidget
(
const
SizedBox
());
// changes to notifier do not impact widget after disposal.
controllerB
.
rasterize
=
true
;
await
tester
.
pump
();
expect
(
delegate
.
count
,
1
);
},
skip:
kIsWeb
);
// TODO(jonahwilliams): https://github.com/flutter/flutter/issues/106689
},
skip:
kIsWeb
);
// TODO(jonahwilliams): https://github.com/flutter/flutter/issues/106689
testWidgets
(
'RenderRasterWidget correctly attaches and detaches delegate callbacks'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'SnapshotWidget can update the painter type'
,
(
WidgetTester
tester
)
async
{
final
TestDelegate
delegate
=
TestDelegate
();
final
SnapshotController
controller
=
SnapshotController
(
allowSnapshotting:
true
);
final
RasterWidgetController
controller
=
RasterWidgetController
(
rasterize:
true
);
await
tester
.
pumpWidget
(
final
RenderRasterWidget
rasterWidget
=
RenderRasterWidget
(
Center
(
delegate:
delegate
,
child:
TestDependencies
(
controller:
controller
,
child:
SnapshotWidget
(
devicePixelRatio:
1.0
,
mode:
RasterizeMode
.
enabled
,
);
expect
(
delegate
.
addedListenerCount
,
0
);
expect
(
delegate
.
removedListenerCount
,
0
);
final
PipelineOwner
owner
=
PipelineOwner
();
rasterWidget
.
attach
(
owner
);
expect
(
delegate
.
addedListenerCount
,
1
);
expect
(
delegate
.
removedListenerCount
,
0
);
rasterWidget
.
detach
();
expect
(
delegate
.
addedListenerCount
,
1
);
expect
(
delegate
.
removedListenerCount
,
1
);
final
TestDelegate
updatedDelegate
=
TestDelegate
();
rasterWidget
.
delegate
=
updatedDelegate
;
// No listeners added or removed while not attached.
expect
(
updatedDelegate
.
addedListenerCount
,
0
);
expect
(
updatedDelegate
.
removedListenerCount
,
0
);
},
skip:
kIsWeb
);
// TODO(jonahwilliams): https://github.com/flutter/flutter/issues/106689
testWidgets
(
'RenderRasterWidget correctly attaches and detaches controller callbacks'
,
(
WidgetTester
tester
)
async
{
final
TestDelegate
delegate
=
TestDelegate
();
final
TestController
controller
=
TestController
();
final
RenderRasterWidget
rasterWidget
=
RenderRasterWidget
(
delegate:
delegate
,
controller:
controller
,
controller:
controller
,
devicePixelRatio:
1.0
,
painter:
TestPainter
(),
mode:
RasterizeMode
.
enabled
,
child:
const
SizedBox
(),
),
),
),
);
);
expect
(
controller
.
addedListenerCount
,
0
);
expect
(
controller
.
removedListenerCount
,
0
);
final
PipelineOwner
owner
=
PipelineOwner
();
rasterWidget
.
attach
(
owner
);
expect
(
controller
.
addedListenerCount
,
1
);
expect
(
controller
.
removedListenerCount
,
0
);
rasterWidget
.
detach
();
expect
(
controller
.
addedListenerCount
,
1
);
expect
(
controller
.
removedListenerCount
,
1
);
final
TestController
updatedController
=
TestController
();
rasterWidget
.
controller
=
updatedController
;
// No listeners added or removed while not attached.
expect
(
updatedController
.
addedListenerCount
,
0
);
expect
(
updatedController
.
removedListenerCount
,
0
);
},
skip:
kIsWeb
);
// TODO(jonahwilliams): https://github.com/flutter/flutter/issues/106689
testWidgets
(
'RenderRasterWidget does not error on rasterization of child with empty size'
,
(
WidgetTester
tester
)
async
{
final
TestDelegate
delegate
=
TestDelegate
();
final
RasterWidgetController
controller
=
RasterWidgetController
(
rasterize:
true
);
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
Center
(
Center
(
child:
Directionality
(
child:
TestDependencies
(
textDirection:
TextDirection
.
ltr
,
child:
SnapshotWidget
(
child:
RasterWidget
(
delegate:
delegate
,
controller:
controller
,
controller:
controller
,
painter:
TestPainter2
(),
child:
const
SizedBox
(),
child:
const
SizedBox
(),
),
),
),
),
),
),
);
);
},
skip:
kIsWeb
);
// TODO(jonahwilliams): https://github.com/flutter/flutter/issues/106689
expect
(
tester
.
takeException
(),
isNull
);
},
skip:
kIsWeb
);
// TODO(jonahwilliams): https://github.com/flutter/flutter/issues/106689
testWidgets
(
'RenderRasterWidget throws assertion if platform view is encountered'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'RenderSnapshotWidget does not error on rasterization of child with empty size'
,
(
WidgetTester
tester
)
async
{
final
TestDelegate
delegate
=
TestDelegate
();
final
SnapshotController
controller
=
SnapshotController
(
allowSnapshotting:
true
);
final
RasterWidgetController
controller
=
RasterWidgetController
(
rasterize:
true
);
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
Center
(
Center
(
child:
Directionality
(
child:
TestDependencies
(
textDirection:
TextDirection
.
ltr
,
child:
SnapshotWidget
(
child:
RasterWidget
(
delegate:
delegate
,
controller:
controller
,
controller:
controller
,
child:
const
SizedBox
(
child:
const
SizedBox
(),
width:
100
,
height:
100
,
child:
TestPlatformView
(),
),
),
),
),
),
),
),
);
);
expect
(
tester
.
takeException
(),
isA
<
FlutterError
>()
expect
(
tester
.
takeException
(),
isNull
);
.
having
((
FlutterError
error
)
=>
error
.
message
,
'message'
,
contains
(
'RasterWidget used with a child that contains a PlatformView'
)));
},
skip:
kIsWeb
);
// TODO(jonahwilliams): https://github.com/flutter/flutter/issues/106689
},
skip:
kIsWeb
);
// TODO(jonahwilliams): https://github.com/flutter/flutter/issues/106689
testWidgets
(
'RenderRasterWidget does not assert if RasterizeMode.forced'
,
(
WidgetTester
tester
)
async
{
final
TestDelegate
delegate
=
TestDelegate
();
final
RasterWidgetController
controller
=
RasterWidgetController
(
rasterize:
true
);
testWidgets
(
'RenderSnapshotWidget throws assertion if platform view is encountered'
,
(
WidgetTester
tester
)
async
{
final
SnapshotController
controller
=
SnapshotController
(
allowSnapshotting:
true
);
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
Center
(
Center
(
child:
Directionality
(
child:
TestDependencies
(
textDirection:
TextDirection
.
ltr
,
child:
SnapshotWidget
(
child:
RasterWidget
(
delegate:
delegate
,
controller:
controller
,
controller:
controller
,
mode:
RasterizeMode
.
forced
,
child:
const
SizedBox
(
child:
const
SizedBox
(
width:
100
,
width:
100
,
height:
100
,
height:
100
,
...
@@ -341,21 +215,18 @@ void main() {
...
@@ -341,21 +215,18 @@ void main() {
),
),
);
);
expect
(
tester
.
takeException
(),
isNull
);
expect
(
tester
.
takeException
(),
isA
<
FlutterError
>()
.
having
((
FlutterError
error
)
=>
error
.
message
,
'message'
,
contains
(
'SnapshotWidget used with a child that contains a PlatformView'
)));
},
skip:
kIsWeb
);
// TODO(jonahwilliams): https://github.com/flutter/flutter/issues/106689
},
skip:
kIsWeb
);
// TODO(jonahwilliams): https://github.com/flutter/flutter/issues/106689
testWidgets
(
'RenderRasterWidget fallbacks to delegate if PlatformView is present'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'RenderSnapshotWidget does not assert if SnapshotMode.forced'
,
(
WidgetTester
tester
)
async
{
final
TestDelegate
delegate
=
TestDelegate
();
final
SnapshotController
controller
=
SnapshotController
(
allowSnapshotting:
true
);
final
RasterWidgetController
controller
=
RasterWidgetController
(
rasterize:
true
);
final
TestFallback
fallback
=
TestFallback
();
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
Center
(
Center
(
child:
Directionality
(
child:
TestDependencies
(
textDirection:
TextDirection
.
ltr
,
child:
SnapshotWidget
(
child:
RasterWidget
(
delegate:
delegate
,
controller:
controller
,
controller:
controller
,
fallback:
fallback
,
mode:
SnapshotMode
.
forced
,
child:
const
SizedBox
(
child:
const
SizedBox
(
width:
100
,
width:
100
,
height:
100
,
height:
100
,
...
@@ -366,48 +237,33 @@ void main() {
...
@@ -366,48 +237,33 @@ void main() {
),
),
);
);
expect
(
fallback
.
calledFallback
,
1
);
expect
(
tester
.
takeException
(),
isNull
);
expect
(
delegate
.
count
,
0
);
},
skip:
kIsWeb
);
// TODO(jonahwilliams): https://github.com/flutter/flutter/issues/106689
},
skip:
kIsWeb
);
// TODO(jonahwilliams): https://github.com/flutter/flutter/issues/106689
testWidgets
(
'RenderRasterWidget fallbacks to delegate if mode: RasterizeMode.fallback'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'RenderSnapshotWidget does not take a snapshot if a platform view is encounted with SnapshotMode.permissive'
,
(
WidgetTester
tester
)
async
{
final
TestDelegate
delegate
=
TestDelegate
();
final
SnapshotController
controller
=
SnapshotController
(
allowSnapshotting:
true
);
final
RasterWidgetController
controller
=
RasterWidgetController
(
rasterize:
true
);
final
TestFallback
fallback
=
TestFallback
();
await
tester
.
pumpWidget
(
await
tester
.
pumpWidget
(
Center
(
Center
(
child:
Directionality
(
child:
TestDependencies
(
textDirection:
TextDirection
.
ltr
,
child:
SnapshotWidget
(
child:
RasterWidget
(
delegate:
delegate
,
controller:
controller
,
controller:
controller
,
fallback:
fallback
,
mode:
SnapshotMode
.
permissive
,
mode:
RasterizeMode
.
fallback
,
child:
const
SizedBox
(
child:
const
SizedBox
(
width:
100
,
width:
100
,
height:
100
,
height:
100
,
child:
TestPlatformView
(),
),
),
),
),
),
),
),
),
);
);
expect
(
fallback
.
calledFallback
,
1
);
expect
(
tester
.
takeException
(),
isNull
);
expect
(
delegate
.
count
,
0
);
expect
(
tester
.
layers
.
last
,
isA
<
PlatformViewLayer
>()
);
},
skip:
kIsWeb
);
// TODO(jonahwilliams): https://github.com/flutter/flutter/issues/106689
},
skip:
kIsWeb
);
// TODO(jonahwilliams): https://github.com/flutter/flutter/issues/106689
}
}
class
TestFallback
extends
RasterWidgetFallbackDelegate
{
class
TestController
extends
SnapshotController
{
int
calledFallback
=
0
;
@override
void
paintFallback
(
PaintingContext
context
,
ui
.
Offset
offset
,
ui
.
Size
size
,
PaintingContextCallback
painter
)
{
calledFallback
+=
1
;
}
}
class
TestController
extends
RasterWidgetController
{
int
addedListenerCount
=
0
;
int
addedListenerCount
=
0
;
int
removedListenerCount
=
0
;
int
removedListenerCount
=
0
;
...
@@ -424,7 +280,23 @@ class TestController extends RasterWidgetController {
...
@@ -424,7 +280,23 @@ class TestController extends RasterWidgetController {
}
}
}
}
class
TestDelegate
extends
RasterWidgetDelegate
{
class
TestPlatformView
extends
SingleChildRenderObjectWidget
{
const
TestPlatformView
({
super
.
key
});
@override
RenderObject
createRenderObject
(
BuildContext
context
)
{
return
RenderTestPlatformView
();
}
}
class
RenderTestPlatformView
extends
RenderProxyBox
{
@override
void
paint
(
PaintingContext
context
,
ui
.
Offset
offset
)
{
context
.
addLayer
(
PlatformViewLayer
(
rect:
offset
&
size
,
viewId:
1
));
}
}
class
TestPainter
extends
SnapshotPainter
{
int
count
=
0
;
int
count
=
0
;
bool
shouldRepaintValue
=
false
;
bool
shouldRepaintValue
=
false
;
ui
.
Image
?
lastImage
;
ui
.
Image
?
lastImage
;
...
@@ -449,29 +321,40 @@ class TestDelegate extends RasterWidgetDelegate {
...
@@ -449,29 +321,40 @@ class TestDelegate extends RasterWidgetDelegate {
}
}
@override
@override
void
paint
(
PaintingContext
context
,
Offset
offset
,
Size
size
,
ui
.
Image
image
,
double
pixelRatio
)
{
void
paint
Snapshot
(
PaintingContext
context
,
Offset
offset
,
Size
size
,
ui
.
Image
image
,
double
pixelRatio
)
{
count
+=
1
;
count
+=
1
;
lastImage
=
image
;
lastImage
=
image
;
}
}
@override
@override
bool
shouldRepaint
(
covariant
RasterWidgetDelegate
oldDelegate
)
=>
shouldRepaintValue
;
void
paint
(
PaintingContext
context
,
ui
.
Offset
offset
,
ui
.
Size
size
,
PaintingContextCallback
painter
)
{
}
count
+=
1
;
}
class
TestPlatformView
extends
SingleChildRenderObjectWidget
{
@override
const
TestPlatformView
({
super
.
key
});
bool
shouldRepaint
(
covariant
TestPainter
oldDelegate
)
=>
shouldRepaintValue
;
}
class
TestPainter2
extends
TestPainter
{
@override
@override
RenderObject
createRenderObject
(
BuildContext
context
)
{
bool
shouldRepaint
(
covariant
TestPainter2
oldDelegate
)
=>
shouldRepaintValue
;
return
RenderTestPlatformView
();
}
}
}
class
RenderTestPlatformView
extends
RenderProxyBox
{
class
TestDependencies
extends
StatelessWidget
{
const
TestDependencies
({
required
this
.
child
,
super
.
key
,
this
.
devicePixelRatio
});
final
Widget
child
;
final
double
?
devicePixelRatio
;
@override
@override
void
paint
(
PaintingContext
context
,
ui
.
Offset
offset
)
{
Widget
build
(
BuildContext
context
)
{
context
.
addLayer
(
PlatformViewLayer
(
rect:
offset
&
size
,
viewId:
1
));
return
Directionality
(
textDirection:
TextDirection
.
ltr
,
child:
MediaQuery
(
data:
MediaQueryData
.
fromWindow
(
WidgetsBinding
.
instance
.
window
)
.
copyWith
(
devicePixelRatio:
devicePixelRatio
),
child:
child
,
),
);
}
}
}
}
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