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
f5f05511
Unverified
Commit
f5f05511
authored
Jun 22, 2018
by
Jonah Williams
Committed by
GitHub
Jun 22, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Initial implementation of AnnotatedRegion for system chrome (#17672)
parent
9a51588d
Changes
14
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
503 additions
and
43 deletions
+503
-43
nav_bar.dart
packages/flutter/lib/src/cupertino/nav_bar.dart
+10
-15
app.dart
packages/flutter/lib/src/material/app.dart
+1
-1
app_bar.dart
packages/flutter/lib/src/material/app_bar.dart
+11
-20
layer.dart
packages/flutter/lib/src/rendering/layer.dart
+153
-2
proxy_box.dart
packages/flutter/lib/src/rendering/proxy_box.dart
+55
-0
view.dart
packages/flutter/lib/src/rendering/view.dart
+53
-0
system_chrome.dart
packages/flutter/lib/src/services/system_chrome.dart
+3
-3
annotated_region.dart
packages/flutter/lib/src/widgets/annotated_region.dart
+57
-0
widget_inspector.dart
packages/flutter/lib/src/widgets/widget_inspector.dart
+3
-0
widgets.dart
packages/flutter/lib/widgets.dart
+1
-0
ink_well_test.dart
packages/flutter/test/material/ink_well_test.dart
+2
-2
annotated_region_test.dart
packages/flutter/test/rendering/annotated_region_test.dart
+128
-0
recording_canvas.dart
packages/flutter/test/rendering/recording_canvas.dart
+5
-0
annotated_region_test.dart
packages/flutter/test/widgets/annotated_region_test.dart
+21
-0
No files found.
packages/flutter/lib/src/cupertino/nav_bar.dart
View file @
f5f05511
...
...
@@ -292,28 +292,23 @@ Widget _wrapWithBackground({
Color
backgroundColor
,
Widget
child
,
})
{
final
bool
darkBackground
=
backgroundColor
.
computeLuminance
()
<
0.179
;
final
SystemUiOverlayStyle
overlayStyle
=
darkBackground
?
SystemUiOverlayStyle
.
light
:
SystemUiOverlayStyle
.
dark
;
final
DecoratedBox
childWithBackground
=
new
DecoratedBox
(
decoration:
new
BoxDecoration
(
border:
border
,
color:
backgroundColor
,
),
child:
child
,
child:
new
AnnotatedRegion
<
SystemUiOverlayStyle
>(
value:
overlayStyle
,
sized:
true
,
child:
child
,
),
);
final
bool
darkBackground
=
backgroundColor
.
computeLuminance
()
<
0.179
;
// TODO(jonahwilliams): remove once we have platform themes.
switch
(
defaultTargetPlatform
)
{
case
TargetPlatform
.
iOS
:
SystemChrome
.
setSystemUIOverlayStyle
(
darkBackground
?
SystemUiOverlayStyle
.
light
:
SystemUiOverlayStyle
.
dark
);
break
;
case
TargetPlatform
.
android
:
case
TargetPlatform
.
fuchsia
:
SystemChrome
.
setSystemUIOverlayStyle
(
SystemUiOverlayStyle
.
dark
);
}
if
(
backgroundColor
.
alpha
==
0xFF
)
return
childWithBackground
;
...
...
packages/flutter/lib/src/material/app.dart
View file @
f5f05511
...
...
@@ -702,7 +702,7 @@ class _MaterialAppState extends State<MaterialApp> {
},
)
);
assert
(()
{
if
(
widget
.
debugShowMaterialGrid
)
{
result
=
new
GridPaper
(
...
...
packages/flutter/lib/src/material/app_bar.dart
View file @
f5f05511
...
...
@@ -345,21 +345,6 @@ class _AppBarState extends State<AppBar> {
TextStyle
centerStyle
=
widget
.
textTheme
?.
title
??
themeData
.
primaryTextTheme
.
title
;
TextStyle
sideStyle
=
widget
.
textTheme
?.
body1
??
themeData
.
primaryTextTheme
.
body1
;
if
(
parentRoute
?.
isCurrent
??
true
)
{
final
Brightness
brightness
=
widget
.
brightness
??
themeData
.
primaryColorBrightness
;
// TODO(jonahwilliams): remove once we have platform themes.
switch
(
defaultTargetPlatform
)
{
case
TargetPlatform
.
iOS
:
SystemChrome
.
setSystemUIOverlayStyle
(
brightness
==
Brightness
.
dark
?
SystemUiOverlayStyle
.
light
:
SystemUiOverlayStyle
.
dark
);
break
;
case
TargetPlatform
.
android
:
case
TargetPlatform
.
fuchsia
:
SystemChrome
.
setSystemUIOverlayStyle
(
SystemUiOverlayStyle
.
dark
);
}
}
if
(
widget
.
toolbarOpacity
!=
1.0
)
{
final
double
opacity
=
const
Interval
(
0.25
,
1.0
,
curve:
Curves
.
fastOutSlowIn
).
transform
(
widget
.
toolbarOpacity
);
if
(
centerStyle
?.
color
!=
null
)
...
...
@@ -451,7 +436,6 @@ class _AppBarState extends State<AppBar> {
),
),
);
if
(
widget
.
bottom
!=
null
)
{
appBar
=
new
Column
(
mainAxisAlignment:
MainAxisAlignment
.
spaceBetween
,
...
...
@@ -492,14 +476,21 @@ class _AppBarState extends State<AppBar> {
],
);
}
final
Brightness
brightness
=
widget
.
brightness
??
themeData
.
primaryColorBrightness
;
final
SystemUiOverlayStyle
overlayStyle
=
brightness
==
Brightness
.
dark
?
SystemUiOverlayStyle
.
dark
:
SystemUiOverlayStyle
.
light
;
return
new
Semantics
(
container:
true
,
explicitChildNodes:
true
,
child:
new
Material
(
color:
widget
.
backgroundColor
??
themeData
.
primaryColor
,
elevation:
widget
.
elevation
,
child:
appBar
,
child:
new
AnnotatedRegion
<
SystemUiOverlayStyle
>(
value:
overlayStyle
,
child:
new
Material
(
color:
widget
.
backgroundColor
??
themeData
.
primaryColor
,
elevation:
widget
.
elevation
,
child:
appBar
,
),
),
);
}
...
...
packages/flutter/lib/src/rendering/layer.dart
View file @
f5f05511
...
...
@@ -89,6 +89,19 @@ abstract class Layer extends AbstractNode with DiagnosticableTreeMixin {
assert
(!
attached
);
}
/// Returns the value of [S] that corresponds to the point described by
/// [regionOffset].
///
/// Returns null if no matching region is found.
///
/// The main way for a value to be assigned here is by pushing an
/// [AnnotatedRegionLayer] into the layer tree.
///
/// See also:
///
/// * [AnnotatedRegionLayer], for placing values in the layer tree.
S
find
<
S
>(
Offset
regionOffset
);
/// Override this method to upload this layer to the engine.
///
/// The `layerOffset` is the accumulated offset of this layer's parent from the
...
...
@@ -166,6 +179,9 @@ class PictureLayer extends Layer {
super
.
debugFillProperties
(
properties
);
properties
.
add
(
new
DiagnosticsProperty
<
Rect
>(
'paint bounds'
,
canvasBounds
));
}
@override
S
find
<
S
>(
Offset
regionOffset
)
=>
null
;
}
/// A composited layer that maps a backend texture to a rectangle.
...
...
@@ -218,6 +234,9 @@ class TextureLayer extends Layer {
height:
shiftedRect
.
height
,
);
}
@override
S
find
<
S
>(
Offset
regionOffset
)
=>
null
;
}
/// A layer that indicates to the compositor that it should display
...
...
@@ -280,6 +299,9 @@ class PerformanceOverlayLayer extends Layer {
builder
.
setCheckerboardRasterCacheImages
(
checkerboardRasterCacheImages
);
builder
.
setCheckerboardOffscreenLayers
(
checkerboardOffscreenLayers
);
}
@override
S
find
<
S
>(
Offset
regionOffset
)
=>
null
;
}
/// A composited layer that has a list of children.
...
...
@@ -316,6 +338,19 @@ class ContainerLayer extends Layer {
return
child
==
equals
;
}
@override
S
find
<
S
>(
Offset
regionOffset
)
{
Layer
current
=
lastChild
;
while
(
current
!=
null
)
{
final
Object
value
=
current
.
find
<
S
>(
regionOffset
);
if
(
value
!=
null
)
{
return
value
;
}
current
=
current
.
previousSibling
;
}
return
null
;
}
@override
void
attach
(
Object
owner
)
{
super
.
attach
(
owner
);
...
...
@@ -506,6 +541,11 @@ class OffsetLayer extends ContainerLayer {
/// pipeline.
Offset
offset
;
@override
S
find
<
S
>(
Offset
regionOffset
)
{
return
super
.
find
<
S
>(
regionOffset
-
offset
);
}
@override
void
addToScene
(
ui
.
SceneBuilder
builder
,
Offset
layerOffset
)
{
addChildrenToScene
(
builder
,
offset
+
layerOffset
);
...
...
@@ -573,6 +613,13 @@ class ClipRectLayer extends ContainerLayer {
/// (as described at [Layer]).
Rect
clipRect
;
@override
S
find
<
S
>(
Offset
regionOffset
)
{
if
(!
clipRect
.
contains
(
regionOffset
))
return
null
;
return
super
.
find
<
S
>(
regionOffset
);
}
@override
void
addToScene
(
ui
.
SceneBuilder
builder
,
Offset
layerOffset
)
{
bool
enabled
=
true
;
...
...
@@ -612,6 +659,13 @@ class ClipRRectLayer extends ContainerLayer {
/// (as described at [Layer]).
RRect
clipRRect
;
@override
S
find
<
S
>(
Offset
regionOffset
)
{
if
(!
clipRRect
.
contains
(
regionOffset
))
return
null
;
return
super
.
find
<
S
>(
regionOffset
);
}
@override
void
addToScene
(
ui
.
SceneBuilder
builder
,
Offset
layerOffset
)
{
bool
enabled
=
true
;
...
...
@@ -651,6 +705,13 @@ class ClipPathLayer extends ContainerLayer {
/// (as described at [Layer]).
Path
clipPath
;
@override
S
find
<
S
>(
Offset
regionOffset
)
{
if
(!
clipPath
.
contains
(
regionOffset
))
return
null
;
return
super
.
find
<
S
>(
regionOffset
);
}
@override
void
addToScene
(
ui
.
SceneBuilder
builder
,
Offset
layerOffset
)
{
bool
enabled
=
true
;
...
...
@@ -676,7 +737,9 @@ class TransformLayer extends OffsetLayer {
///
/// The [transform] and [offset] properties must be non-null before the
/// compositing phase of the pipeline.
TransformLayer
({
this
.
transform
,
Offset
offset
=
Offset
.
zero
})
:
super
(
offset:
offset
);
TransformLayer
({
Matrix4
transform
,
Offset
offset
=
Offset
.
zero
})
:
_transform
=
transform
,
super
(
offset:
offset
);
/// The matrix to apply.
///
...
...
@@ -687,9 +750,17 @@ class TransformLayer extends OffsetLayer {
///
/// The [transform] property must be non-null before the compositing phase of
/// the pipeline.
Matrix4
transform
;
Matrix4
get
transform
=>
_transform
;
Matrix4
_transform
;
set
transform
(
Matrix4
value
)
{
if
(
value
==
_transform
)
return
;
_transform
=
value
;
_invertedTransform
=
null
;
}
Matrix4
_lastEffectiveTransform
;
Matrix4
_invertedTransform
;
@override
void
addToScene
(
ui
.
SceneBuilder
builder
,
Offset
layerOffset
)
{
...
...
@@ -704,6 +775,14 @@ class TransformLayer extends OffsetLayer {
builder
.
pop
();
}
@override
S
find
<
S
>(
Offset
regionOffset
)
{
_invertedTransform
??=
new
Matrix4
.
inverted
(
transform
);
final
Vector4
vector
=
new
Vector4
(
regionOffset
.
dx
,
regionOffset
.
dy
,
0.0
,
1.0
);
final
Vector4
result
=
_invertedTransform
.
transform
(
vector
);
return
super
.
find
<
S
>(
new
Offset
(
result
[
0
],
result
[
1
]));
}
@override
void
applyTransform
(
Layer
child
,
Matrix4
transform
)
{
assert
(
child
!=
null
);
...
...
@@ -875,6 +954,13 @@ class PhysicalModelLayer extends ContainerLayer {
/// The shadow color.
Color
shadowColor
;
@override
S
find
<
S
>(
Offset
regionOffset
)
{
if
(!
clipPath
.
contains
(
regionOffset
))
return
null
;
return
super
.
find
<
S
>(
regionOffset
);
}
@override
void
addToScene
(
ui
.
SceneBuilder
builder
,
Offset
layerOffset
)
{
bool
enabled
=
true
;
...
...
@@ -978,6 +1064,11 @@ class LeaderLayer extends ContainerLayer {
/// not every case can be detected.
Offset
_lastOffset
;
@override
S
find
<
S
>(
Offset
regionOffset
)
{
return
super
.
find
(
regionOffset
-
offset
);
}
@override
void
addToScene
(
ui
.
SceneBuilder
builder
,
Offset
layerOffset
)
{
assert
(
offset
!=
null
);
...
...
@@ -1086,6 +1177,23 @@ class FollowerLayer extends ContainerLayer {
Offset
_lastOffset
;
Matrix4
_lastTransform
;
Matrix4
_invertedTransform
;
@override
S
find
<
S
>(
Offset
regionOffset
)
{
if
(
link
.
leader
==
null
)
{
return
showWhenUnlinked
?
super
.
find
<
S
>(
regionOffset
-
unlinkedOffset
)
:
null
;
}
if
(
_invertedTransform
==
null
)
{
final
Matrix4
transform
=
getLastTransform
();
assert
(
transform
!=
null
);
_invertedTransform
=
new
Matrix4
.
zero
();
transform
.
copyInverse
(
_invertedTransform
);
}
final
Vector4
vector
=
new
Vector4
(
regionOffset
.
dx
,
regionOffset
.
dy
,
0.0
,
1.0
);
final
Vector4
result
=
_invertedTransform
.
transform
(
vector
);
return
super
.
find
<
S
>(
new
Offset
(
result
[
0
]
-
linkedOffset
.
dx
,
result
[
1
]
-
linkedOffset
.
dy
));
}
/// The transform that was used during the last composition phase.
///
...
...
@@ -1199,3 +1307,46 @@ class FollowerLayer extends ContainerLayer {
properties
.
add
(
new
TransformProperty
(
'transform'
,
getLastTransform
(),
defaultValue:
null
));
}
}
/// A composited layer which annotates its children with a value.
///
/// These values can be retrieved using [Layer.find] with a given [Offset]. If
/// a [Size] is provided to this layer, then find will check if the provided
/// offset is within the bounds of the layer.
class
AnnotatedRegionLayer
<
T
>
extends
ContainerLayer
{
/// Creates a new layer annotated with [value] that clips to [size] if provided.
///
/// The value provided cannot be null.
AnnotatedRegionLayer
(
this
.
value
,
{
this
.
size
})
:
assert
(
value
!=
null
);
/// The value returned by [find] if the offset is contained within this layer.
final
T
value
;
/// The [size] is optionally used to clip the hit-testing of [find].
///
/// If not provided, all offsets are considered to be contained within this
/// layer, unless an ancestor layer applies a clip.
final
Size
size
;
@override
S
find
<
S
>(
Offset
regionOffset
)
{
final
S
result
=
super
.
find
<
S
>(
regionOffset
);
if
(
result
!=
null
)
return
result
;
if
(
size
!=
null
&&
!
size
.
contains
(
regionOffset
))
return
null
;
if
(
T
==
S
)
{
final
Object
untypedResult
=
value
;
final
S
typedResult
=
untypedResult
;
return
typedResult
;
}
return
super
.
find
<
S
>(
regionOffset
);
}
@override
void
debugFillProperties
(
DiagnosticPropertiesBuilder
properties
)
{
super
.
debugFillProperties
(
properties
);
properties
.
add
(
new
DiagnosticsProperty
<
T
>(
'value'
,
value
));
properties
.
add
(
new
DiagnosticsProperty
<
Size
>(
'size'
,
size
,
defaultValue:
null
));
}
}
packages/flutter/lib/src/rendering/proxy_box.dart
View file @
f5f05511
...
...
@@ -4235,3 +4235,58 @@ class RenderFollowerLayer extends RenderProxyBox {
properties
.
add
(
new
TransformProperty
(
'current transform matrix'
,
getCurrentTransform
()));
}
}
/// Render object which inserts an [AnnotatedRegionLayer] into the layer tree.
///
/// See also:
///
/// * [Layer.find], for an example of how this value is retrieved.
/// * [AnnotatedRegionLayer], the layer this render object creates.
class
RenderAnnotatedRegion
<
T
>
extends
RenderProxyBox
{
/// Creates a new [RenderAnnotatedRegion] to insert [value] into the
/// layer tree.
///
/// If [sized] is true, the layer is provided with the size of this render
/// object to clip the results of [Layer.findRegion].
///
/// Neither [value] nor [sized] can be null.
RenderAnnotatedRegion
({
@required
T
value
,
@required
bool
sized
,
RenderBox
child
,
})
:
assert
(
value
!=
null
),
assert
(
sized
!=
null
),
_value
=
value
,
_sized
=
sized
,
super
(
child
);
/// A value which can be retrieved using [Layer.find].
T
get
value
=>
_value
;
T
_value
;
set
value
(
T
newValue
)
{
if
(
_value
==
newValue
)
return
;
_value
=
newValue
;
markNeedsPaint
();
}
/// Whether the render object will pass its [size] to the [AnnotatedRegionLayer].
bool
get
sized
=>
_sized
;
bool
_sized
;
set
sized
(
bool
value
)
{
if
(
_sized
==
value
)
return
;
_sized
=
value
;
markNeedsPaint
();
}
@override
final
bool
alwaysNeedsCompositing
=
true
;
@override
void
paint
(
PaintingContext
context
,
Offset
offset
)
{
final
AnnotatedRegionLayer
<
T
>
layer
=
new
AnnotatedRegionLayer
<
T
>(
value
,
size:
sized
?
size
:
null
);
context
.
pushLayer
(
layer
,
super
.
paint
,
offset
);
}
}
packages/flutter/lib/src/rendering/view.dart
View file @
f5f05511
...
...
@@ -7,6 +7,7 @@ import 'dart:io' show Platform;
import
'dart:ui'
as
ui
show
Scene
,
SceneBuilder
,
window
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/services.dart'
;
import
'package:vector_math/vector_math_64.dart'
;
import
'binding.dart'
;
...
...
@@ -81,6 +82,27 @@ class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox>
markNeedsLayout
();
}
/// Whether Flutter should automatically compute the desired system UI.
///
/// When this setting is enabled, Flutter will hit-test the layer tree at the
/// top and bottom of the screen on each frame looking for an
/// [AnnotatedRegionLayer] with an instance of a [SystemUiOverlayStyle]. The
/// hit-test result from the top of the screen provides the status bar settings
/// and the hit-test result from the bottom of the screen provides the system
/// nav bar settings.
///
/// Setting this to false does not cause previous automatic adjustments to be
/// reset, nor does setting it to true cause the app to update immediately.
///
/// If you want to imperatively set the system ui style instead, it is
/// recommended that [automaticSystemUiAdjustment] is set to false.
///
/// See also:
///
/// * [AnnotatedRegion], for placing [SystemUiOverlayStyle] in the layer tree.
/// * [SystemChrome.setSystemUIOverlayStyle], for imperatively setting the system ui style.
bool
automaticSystemUiAdjustment
=
true
;
/// Bootstrap the rendering pipeline by scheduling the first frame.
///
/// This should only be called once, and must be called before changing
...
...
@@ -172,6 +194,8 @@ class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox>
final
ui
.
SceneBuilder
builder
=
new
ui
.
SceneBuilder
();
layer
.
addToScene
(
builder
,
Offset
.
zero
);
final
ui
.
Scene
scene
=
builder
.
build
();
if
(
automaticSystemUiAdjustment
)
_updateSystemChrome
();
ui
.
window
.
render
(
scene
);
scene
.
dispose
();
assert
(()
{
...
...
@@ -184,6 +208,35 @@ class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox>
}
}
void
_updateSystemChrome
()
{
final
Rect
bounds
=
paintBounds
;
final
Offset
top
=
new
Offset
(
bounds
.
center
.
dx
,
ui
.
window
.
padding
.
top
/
ui
.
window
.
devicePixelRatio
);
final
Offset
bottom
=
new
Offset
(
bounds
.
center
.
dx
,
bounds
.
center
.
dy
-
ui
.
window
.
padding
.
bottom
/
ui
.
window
.
devicePixelRatio
);
final
SystemUiOverlayStyle
upperOverlayStyle
=
layer
.
find
<
SystemUiOverlayStyle
>(
top
);
// Only android has a customizable system navigation bar.
SystemUiOverlayStyle
lowerOverlayStyle
;
switch
(
defaultTargetPlatform
)
{
case
TargetPlatform
.
android
:
lowerOverlayStyle
=
layer
.
find
<
SystemUiOverlayStyle
>(
bottom
);
break
;
case
TargetPlatform
.
iOS
:
case
TargetPlatform
.
fuchsia
:
break
;
}
// If there are no overlay styles in the UI don't bother updating.
if
(
upperOverlayStyle
!=
null
||
lowerOverlayStyle
!=
null
)
{
final
SystemUiOverlayStyle
overlayStyle
=
new
SystemUiOverlayStyle
(
statusBarBrightness:
upperOverlayStyle
?.
statusBarBrightness
,
statusBarIconBrightness:
upperOverlayStyle
?.
statusBarIconBrightness
,
statusBarColor:
upperOverlayStyle
?.
statusBarColor
,
systemNavigationBarColor:
lowerOverlayStyle
?.
systemNavigationBarColor
,
systemNavigationBarDividerColor:
lowerOverlayStyle
?.
systemNavigationBarDividerColor
,
systemNavigationBarIconBrightness:
lowerOverlayStyle
?.
systemNavigationBarIconBrightness
,
);
SystemChrome
.
setSystemUIOverlayStyle
(
overlayStyle
);
}
}
@override
Rect
get
paintBounds
=>
Offset
.
zero
&
(
size
*
configuration
.
devicePixelRatio
);
...
...
packages/flutter/lib/src/services/system_chrome.dart
View file @
f5f05511
...
...
@@ -171,6 +171,9 @@ class SystemUiOverlayStyle {
};
}
@override
String
toString
()
=>
_toMap
().
toString
();
/// Creates a copy of this theme with the given fields replaced with new values.
SystemUiOverlayStyle
copyWith
({
Color
systemNavigationBarColor
,
...
...
@@ -302,19 +305,16 @@ class SystemChrome {
/// ```
static
void
setSystemUIOverlayStyle
(
SystemUiOverlayStyle
style
)
{
assert
(
style
!=
null
);
if
(
_pendingStyle
!=
null
)
{
// The microtask has already been queued; just update the pending value.
_pendingStyle
=
style
;
return
;
}
if
(
style
==
_latestStyle
)
{
// Trivial success: no microtask has been queued and the given style is
// already in effect, so no need to queue a microtask.
return
;
}
_pendingStyle
=
style
;
scheduleMicrotask
(()
{
assert
(
_pendingStyle
!=
null
);
...
...
packages/flutter/lib/src/widgets/annotated_region.dart
0 → 100644
View file @
f5f05511
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'package:flutter/foundation.dart'
;
import
'package:flutter/rendering.dart'
;
import
'framework.dart'
;
/// Annotates a region of the layer tree with a value.
///
/// See also:
///
/// * [Layer.find], for an example of how this value is retrieved.
/// * [AnnotatedRegionLayer], the layer pushed into the layer tree.
class
AnnotatedRegion
<
T
>
extends
SingleChildRenderObjectWidget
{
/// Creates a new annotated region to insert [value] into the layer tree.
///
/// Neither [child] nor [value] may be null.
///
/// [sized] defaults to true and controls whether the annotated region will
/// clip its child.
const
AnnotatedRegion
({
Key
key
,
@required
Widget
child
,
@required
this
.
value
,
this
.
sized
=
true
,
})
:
assert
(
value
!=
null
),
assert
(
child
!=
null
),
super
(
key:
key
,
child:
child
);
/// A value which can be retrieved using [Layer.find].
final
T
value
;
/// If false, the layer pushed into the tree will not be provided with a size.
///
/// An [AnnotatedRegionLayer] with a size checks that the offset provided in
/// [Layer.find] is within the bounds, returning null otherwise.
///
/// See also:
///
/// * [AnnotatedRegionLayer], for a description of this behavior.
final
bool
sized
;
@override
RenderObject
createRenderObject
(
BuildContext
context
)
{
return
new
RenderAnnotatedRegion
<
T
>(
value:
value
,
sized:
sized
);
}
@override
void
updateRenderObject
(
BuildContext
context
,
RenderAnnotatedRegion
<
T
>
renderObject
)
{
renderObject
..
value
=
value
..
sized
=
sized
;
}
}
packages/flutter/lib/src/widgets/widget_inspector.dart
View file @
f5f05511
...
...
@@ -1703,6 +1703,9 @@ class _InspectorOverlayLayer extends Layer {
_textPainter
.
paint
(
canvas
,
tipOffset
+
const
Offset
(
_kTooltipPadding
,
_kTooltipPadding
));
canvas
.
restore
();
}
@override
S
find
<
S
>(
Offset
regionOffset
)
=>
null
;
}
const
double
_kScreenEdgeMargin
=
10.0
;
...
...
packages/flutter/lib/widgets.dart
View file @
f5f05511
...
...
@@ -18,6 +18,7 @@ export 'src/widgets/animated_cross_fade.dart';
export
'src/widgets/animated_list.dart'
;
export
'src/widgets/animated_size.dart'
;
export
'src/widgets/animated_switcher.dart'
;
export
'src/widgets/annotated_region.dart'
;
export
'src/widgets/app.dart'
;
export
'src/widgets/async.dart'
;
export
'src/widgets/automatic_keep_alive.dart'
;
...
...
packages/flutter/test/material/ink_well_test.dart
View file @
f5f05511
...
...
@@ -160,7 +160,7 @@ void main() {
),
),
);
expect
(
tester
.
renderObject
<
RenderProxyBox
>(
find
.
byType
(
PhysicalModel
)).
child
,
paintsNothing
);
expect
(
tester
.
renderObject
<
RenderProxyBox
>(
find
.
byType
(
PhysicalModel
)).
child
,
isNot
(
paints
..
circle
())
);
await
tester
.
tap
(
find
.
byType
(
InkWell
));
await
tester
.
pump
();
await
tester
.
pump
(
const
Duration
(
milliseconds:
10
));
...
...
@@ -171,7 +171,7 @@ void main() {
await
tester
.
pump
(
const
Duration
(
milliseconds:
10
));
expect
(
tester
.
renderObject
<
RenderProxyBox
>(
find
.
byType
(
PhysicalModel
)).
child
,
keepAlive
?
(
paints
..
circle
())
:
paintsNothing
,
keepAlive
?
(
paints
..
circle
())
:
isNot
(
paints
..
circle
())
,
);
}
await
runTest
(
true
);
...
...
packages/flutter/test/rendering/annotated_region_test.dart
0 → 100644
View file @
f5f05511
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'package:flutter/rendering.dart'
;
import
'package:flutter/widgets.dart'
;
import
'package:test/test.dart'
;
void
main
(
)
{
group
(
AnnotatedRegion
,
()
{
test
(
'finds the first value in a OffsetLayer when sized'
,
()
{
final
ContainerLayer
containerLayer
=
new
ContainerLayer
();
final
List
<
OffsetLayer
>
layers
=
<
OffsetLayer
>[
new
OffsetLayer
(
offset:
Offset
.
zero
),
new
OffsetLayer
(
offset:
const
Offset
(
0.0
,
100.0
)),
new
OffsetLayer
(
offset:
const
Offset
(
0.0
,
200.0
)),
];
int
i
=
0
;
for
(
OffsetLayer
layer
in
layers
)
{
layer
.
append
(
new
AnnotatedRegionLayer
<
int
>(
i
,
size:
const
Size
(
200.0
,
100.0
)));
containerLayer
.
append
(
layer
);
i
+=
1
;
}
expect
(
containerLayer
.
find
<
int
>(
const
Offset
(
0.0
,
1.0
)),
0
);
expect
(
containerLayer
.
find
<
int
>(
const
Offset
(
0.0
,
101.0
)),
1
);
expect
(
containerLayer
.
find
<
int
>(
const
Offset
(
0.0
,
201.0
)),
2
);
});
test
(
'finds a value within the clip in a ClipRectLayer'
,
()
{
final
ContainerLayer
containerLayer
=
new
ContainerLayer
();
final
List
<
ClipRectLayer
>
layers
=
<
ClipRectLayer
>[
new
ClipRectLayer
(
clipRect:
new
Rect
.
fromLTRB
(
0.0
,
0.0
,
100.0
,
100.0
)),
new
ClipRectLayer
(
clipRect:
new
Rect
.
fromLTRB
(
0.0
,
100.0
,
100.0
,
200.0
)),
new
ClipRectLayer
(
clipRect:
new
Rect
.
fromLTRB
(
0.0
,
200.0
,
100.0
,
300.0
)),
];
int
i
=
0
;
for
(
ClipRectLayer
layer
in
layers
)
{
layer
.
append
(
new
AnnotatedRegionLayer
<
int
>(
i
));
containerLayer
.
append
(
layer
);
i
+=
1
;
}
expect
(
containerLayer
.
find
<
int
>(
const
Offset
(
0.0
,
1.0
)),
0
);
expect
(
containerLayer
.
find
<
int
>(
const
Offset
(
0.0
,
101.0
)),
1
);
expect
(
containerLayer
.
find
<
int
>(
const
Offset
(
0.0
,
201.0
)),
2
);
});
test
(
'finds a value within the clip in a ClipRRectLayer'
,
()
{
final
ContainerLayer
containerLayer
=
new
ContainerLayer
();
final
List
<
ClipRRectLayer
>
layers
=
<
ClipRRectLayer
>[
new
ClipRRectLayer
(
clipRRect:
new
RRect
.
fromLTRBR
(
0.0
,
0.0
,
100.0
,
100.0
,
const
Radius
.
circular
(
4.0
))),
new
ClipRRectLayer
(
clipRRect:
new
RRect
.
fromLTRBR
(
0.0
,
100.0
,
100.0
,
200.0
,
const
Radius
.
circular
(
4.0
))),
new
ClipRRectLayer
(
clipRRect:
new
RRect
.
fromLTRBR
(
0.0
,
200.0
,
100.0
,
300.0
,
const
Radius
.
circular
(
4.0
))),
];
int
i
=
0
;
for
(
ClipRRectLayer
layer
in
layers
)
{
layer
.
append
(
new
AnnotatedRegionLayer
<
int
>(
i
));
containerLayer
.
append
(
layer
);
i
+=
1
;
}
expect
(
containerLayer
.
find
<
int
>(
const
Offset
(
5.0
,
5.0
)),
0
);
expect
(
containerLayer
.
find
<
int
>(
const
Offset
(
5.0
,
105.0
)),
1
);
expect
(
containerLayer
.
find
<
int
>(
const
Offset
(
5.0
,
205.0
)),
2
);
});
test
(
'finds a value under a TransformLayer'
,
()
{
final
Matrix4
transform
=
new
Matrix4
(
2.625
,
0.0
,
0.0
,
0.0
,
0.0
,
2.625
,
0.0
,
0.0
,
0.0
,
0.0
,
1.0
,
0.0
,
0.0
,
0.0
,
0.0
,
1.0
,
);
final
TransformLayer
transformLayer
=
new
TransformLayer
(
transform:
transform
);
final
List
<
OffsetLayer
>
layers
=
<
OffsetLayer
>[
new
OffsetLayer
(),
new
OffsetLayer
(
offset:
const
Offset
(
0.0
,
100.0
)),
new
OffsetLayer
(
offset:
const
Offset
(
0.0
,
200.0
)),
];
int
i
=
0
;
for
(
OffsetLayer
layer
in
layers
)
{
final
AnnotatedRegionLayer
<
int
>
annotatedRegionLayer
=
new
AnnotatedRegionLayer
<
int
>(
i
,
size:
const
Size
(
100.0
,
100.0
));
layer
.
append
(
annotatedRegionLayer
);
transformLayer
.
append
(
layer
);
i
+=
1
;
}
expect
(
transformLayer
.
find
<
int
>(
const
Offset
(
0.0
,
100.0
)),
0
);
expect
(
transformLayer
.
find
<
int
>(
const
Offset
(
0.0
,
200.0
)),
0
);
expect
(
transformLayer
.
find
<
int
>(
const
Offset
(
0.0
,
270.0
)),
1
);
expect
(
transformLayer
.
find
<
int
>(
const
Offset
(
0.0
,
400.0
)),
1
);
expect
(
transformLayer
.
find
<
int
>(
const
Offset
(
0.0
,
530.0
)),
2
);
});
test
(
'looks for child AnnotatedRegions before parents'
,
()
{
final
AnnotatedRegionLayer
<
int
>
parent
=
new
AnnotatedRegionLayer
<
int
>(
1
);
final
AnnotatedRegionLayer
<
int
>
child
=
new
AnnotatedRegionLayer
<
int
>(
2
);
final
ContainerLayer
layer
=
new
ContainerLayer
();
parent
.
append
(
child
);
layer
.
append
(
parent
);
expect
(
parent
.
find
<
int
>(
Offset
.
zero
),
2
);
});
test
(
'looks for correct type'
,
()
{
final
AnnotatedRegionLayer
<
int
>
child1
=
new
AnnotatedRegionLayer
<
int
>(
1
);
final
AnnotatedRegionLayer
<
String
>
child2
=
new
AnnotatedRegionLayer
<
String
>(
'hello'
);
final
ContainerLayer
layer
=
new
ContainerLayer
();
layer
.
append
(
child2
);
layer
.
append
(
child1
);
expect
(
layer
.
find
<
String
>(
Offset
.
zero
),
'hello'
);
});
test
(
'does not clip Layer.find on an AnnotatedRegion with an unrelated type'
,
()
{
final
AnnotatedRegionLayer
<
int
>
child
=
new
AnnotatedRegionLayer
<
int
>(
1
);
final
AnnotatedRegionLayer
<
String
>
parent
=
new
AnnotatedRegionLayer
<
String
>(
'hello'
,
size:
const
Size
(
10.0
,
10.0
));
final
ContainerLayer
layer
=
new
ContainerLayer
();
parent
.
append
(
child
);
layer
.
append
(
parent
);
expect
(
layer
.
find
<
int
>(
const
Offset
(
100.0
,
100.0
)),
1
);
});
});
}
packages/flutter/test/rendering/recording_canvas.dart
View file @
f5f05511
...
...
@@ -135,6 +135,11 @@ class TestRecordingPaintingContext implements PaintingContext {
canvas
.
restore
();
}
@override
void
pushLayer
(
Layer
childLayer
,
PaintingContextCallback
painter
,
Offset
offset
,
{
Rect
childPaintBounds
})
{
painter
(
this
,
offset
);
}
@override
void
noSuchMethod
(
Invocation
invocation
)
{
}
}
...
...
packages/flutter/test/widgets/annotated_region_test.dart
0 → 100644
View file @
f5f05511
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'package:flutter/rendering.dart'
;
import
'package:flutter/widgets.dart'
;
import
'package:flutter_test/flutter_test.dart'
;
void
main
(
)
{
testWidgets
(
'provides a value to the layer tree'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
const
AnnotatedRegion
<
int
>(
child:
const
SizedBox
(
width:
100.0
,
height:
100.0
),
value:
1
,
),
);
final
List
<
Layer
>
layers
=
tester
.
layers
;
final
AnnotatedRegionLayer
<
int
>
layer
=
layers
.
firstWhere
((
Layer
layer
)
=>
layer
is
AnnotatedRegionLayer
<
int
>);
expect
(
layer
.
value
,
1
);
});
}
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