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
e4c8f1b9
Unverified
Commit
e4c8f1b9
authored
Jan 16, 2019
by
Michael Goderbauer
Committed by
GitHub
Jan 16, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
3D SemanticsTree (#25670)
parent
14faa8d9
Changes
15
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
845 additions
and
283 deletions
+845
-283
goldens.version
bin/internal/goldens.version
+1
-1
app_bar.dart
packages/flutter/lib/src/material/app_bar.dart
+4
-2
bottom_navigation_bar.dart
packages/flutter/lib/src/material/bottom_navigation_bar.dart
+19
-32
card.dart
packages/flutter/lib/src/material/card.dart
+4
-2
dialog.dart
packages/flutter/lib/src/material/dialog.dart
+5
-1
object.dart
packages/flutter/lib/src/rendering/object.dart
+38
-7
proxy_box.dart
packages/flutter/lib/src/rendering/proxy_box.dart
+6
-0
semantics.dart
packages/flutter/lib/src/semantics/semantics.dart
+185
-26
card_test.dart
packages/flutter/test/material/card_test.dart
+27
-20
date_picker_test.dart
packages/flutter/test/material/date_picker_test.dart
+196
-192
semantics_elevation_test.dart
...ages/flutter/test/semantics/semantics_elevation_test.dart
+305
-0
semantics_test.dart
packages/flutter/test/semantics/semantics_test.dart
+4
-0
semantics_tester.dart
packages/flutter/test/widgets/semantics_tester.dart
+31
-0
matchers.dart
packages/flutter_test/lib/src/matchers.dart
+16
-0
matchers_test.dart
packages/flutter_test/test/matchers_test.dart
+4
-0
No files found.
bin/internal/goldens.version
View file @
e4c8f1b9
02905560cf2c2132a7adea10943001f29325f3b
e
ecbdcf8d56d3aba0212c2b1b923466023ef09b4
e
packages/flutter/lib/src/material/app_bar.dart
View file @
e4c8f1b9
...
...
@@ -524,13 +524,15 @@ class _AppBarState extends State<AppBar> {
return
Semantics
(
container:
true
,
explicitChildNodes:
true
,
child:
AnnotatedRegion
<
SystemUiOverlayStyle
>(
value:
overlayStyle
,
child:
Material
(
color:
widget
.
backgroundColor
??
themeData
.
primaryColor
,
elevation:
widget
.
elevation
,
child:
appBar
,
child:
Semantics
(
explicitChildNodes:
true
,
child:
appBar
,
),
),
),
);
...
...
packages/flutter/lib/src/material/bottom_navigation_bar.dart
View file @
e4c8f1b9
...
...
@@ -567,43 +567,30 @@ class _BottomNavigationBarState extends State<BottomNavigationBar> with TickerPr
break
;
}
return
Semantics
(
container:
true
,
explicitChildNodes:
true
,
child:
Stack
(
children:
<
Widget
>[
Positioned
.
fill
(
child:
Material
(
// Casts shadow.
elevation:
8.0
,
color:
backgroundColor
,
child:
Material
(
elevation:
8.0
,
color:
backgroundColor
,
child:
ConstrainedBox
(
constraints:
BoxConstraints
(
minHeight:
kBottomNavigationBarHeight
+
additionalBottomPadding
),
child:
CustomPaint
(
painter:
_RadialPainter
(
circles:
_circles
.
toList
(),
textDirection:
Directionality
.
of
(
context
),
),
),
ConstrainedBox
(
constraints:
BoxConstraints
(
minHeight:
kBottomNavigationBarHeight
+
additionalBottomPadding
),
child:
Stack
(
children:
<
Widget
>[
Positioned
.
fill
(
child:
CustomPaint
(
painter:
_RadialPainter
(
circles:
_circles
.
toList
(),
textDirection:
Directionality
.
of
(
context
),
),
),
),
Material
(
// Splashes.
type:
MaterialType
.
transparency
,
child:
Padding
(
padding:
EdgeInsets
.
only
(
bottom:
additionalBottomPadding
),
child:
MediaQuery
.
removePadding
(
context:
context
,
removeBottom:
true
,
child:
_createContainer
(
_createTiles
()),
),
),
child:
Material
(
// Splashes.
type:
MaterialType
.
transparency
,
child:
Padding
(
padding:
EdgeInsets
.
only
(
bottom:
additionalBottomPadding
),
child:
MediaQuery
.
removePadding
(
context:
context
,
removeBottom:
true
,
child:
_createContainer
(
_createTiles
()),
),
]
,
)
,
),
),
]
,
)
,
),
);
}
...
...
packages/flutter/lib/src/material/card.dart
View file @
e4c8f1b9
...
...
@@ -135,7 +135,6 @@ class Card extends StatelessWidget {
Widget
build
(
BuildContext
context
)
{
return
Semantics
(
container:
semanticContainer
,
explicitChildNodes:
!
semanticContainer
,
child:
Container
(
margin:
margin
??
const
EdgeInsets
.
all
(
4.0
),
child:
Material
(
...
...
@@ -146,7 +145,10 @@ class Card extends StatelessWidget {
borderRadius:
BorderRadius
.
all
(
Radius
.
circular
(
4.0
)),
),
clipBehavior:
clipBehavior
,
child:
child
,
child:
Semantics
(
explicitChildNodes:
!
semanticContainer
,
child:
child
,
),
),
),
);
...
...
packages/flutter/lib/src/material/dialog.dart
View file @
e4c8f1b9
...
...
@@ -311,7 +311,11 @@ class AlertDialog extends StatelessWidget {
padding:
titlePadding
??
EdgeInsets
.
fromLTRB
(
24.0
,
24.0
,
24.0
,
content
==
null
?
20.0
:
0.0
),
child:
DefaultTextStyle
(
style:
titleTextStyle
??
dialogTheme
.
titleTextStyle
??
theme
.
textTheme
.
title
,
child:
Semantics
(
child:
title
,
namesRoute:
true
),
child:
Semantics
(
child:
title
,
namesRoute:
true
,
container:
true
,
),
),
));
}
else
{
...
...
packages/flutter/lib/src/rendering/object.dart
View file @
e4c8f1b9
...
...
@@ -2406,6 +2406,7 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
final
SemanticsNode
node
=
interestingFragment
.
compileChildren
(
parentSemanticsClipRect:
_semantics
?.
parentSemanticsClipRect
,
parentPaintClipRect:
_semantics
?.
parentPaintClipRect
,
elevationAdjustment:
_semantics
?.
elevationAdjustment
??
0.0
,
).
single
;
// Fragment only wants to add this node's SemanticsNode to the parent.
assert
(
interestingFragment
.
config
==
null
&&
node
==
_semantics
);
...
...
@@ -3193,9 +3194,19 @@ abstract class _InterestingSemanticsFragment extends _SemanticsFragment {
final
List
<
RenderObject
>
_ancestorChain
;
/// The children to be added to the parent.
///
/// See also:
///
/// * [SemanticsNode.parentSemanticsClipRect] for the source and definition
/// of the `parentSemanticsClipRect` argument.
/// * [SemanticsNode.parentPaintClipRect] for the source and definition
// of the `parentPaintClipRect` argument.
/// * [SemanticsNode.elevationAdjustment] for the source and definition
// of the `elevationAdjustment` argument.
Iterable
<
SemanticsNode
>
compileChildren
({
@required
Rect
parentSemanticsClipRect
,
@required
Rect
parentPaintClipRect
@required
Rect
parentPaintClipRect
,
@required
double
elevationAdjustment
,
});
/// The [SemanticsConfiguration] the child wants to merge into the parent's
...
...
@@ -3264,11 +3275,12 @@ class _RootSemanticsFragment extends _InterestingSemanticsFragment {
})
:
super
(
owner:
owner
,
dropsSemanticsOfPreviousSiblings:
dropsSemanticsOfPreviousSiblings
);
@override
Iterable
<
SemanticsNode
>
compileChildren
({
Rect
parentSemanticsClipRect
,
Rect
parentPaintClipRect
})
sync
*
{
Iterable
<
SemanticsNode
>
compileChildren
({
Rect
parentSemanticsClipRect
,
Rect
parentPaintClipRect
,
double
elevationAdjustment
})
sync
*
{
assert
(
_tagsForChildren
==
null
||
_tagsForChildren
.
isEmpty
);
assert
(
parentSemanticsClipRect
==
null
);
assert
(
parentPaintClipRect
==
null
);
assert
(
_ancestorChain
.
length
==
1
);
assert
(
elevationAdjustment
==
0.0
);
owner
.
_semantics
??=
SemanticsNode
.
root
(
showOnScreen:
owner
.
showOnScreen
,
...
...
@@ -3287,6 +3299,7 @@ class _RootSemanticsFragment extends _InterestingSemanticsFragment {
children
.
addAll
(
fragment
.
compileChildren
(
parentSemanticsClipRect:
parentSemanticsClipRect
,
parentPaintClipRect:
parentPaintClipRect
,
elevationAdjustment:
0.0
,
));
}
node
.
updateWith
(
config:
null
,
childrenInInversePaintOrder:
children
);
...
...
@@ -3352,13 +3365,20 @@ class _SwitchableSemanticsFragment extends _InterestingSemanticsFragment {
final
List
<
_InterestingSemanticsFragment
>
_children
=
<
_InterestingSemanticsFragment
>[];
@override
Iterable
<
SemanticsNode
>
compileChildren
({
Rect
parentSemanticsClipRect
,
Rect
parentPaintClipRect
})
sync
*
{
Iterable
<
SemanticsNode
>
compileChildren
({
Rect
parentSemanticsClipRect
,
Rect
parentPaintClipRect
,
double
elevationAdjustment
})
sync
*
{
if
(!
_isExplicit
)
{
owner
.
_semantics
=
null
;
for
(
_InterestingSemanticsFragment
fragment
in
_children
)
{
assert
(
_ancestorChain
.
first
==
fragment
.
_ancestorChain
.
last
);
fragment
.
_ancestorChain
.
addAll
(
_ancestorChain
.
sublist
(
1
));
yield
*
fragment
.
compileChildren
(
parentSemanticsClipRect:
parentSemanticsClipRect
,
parentPaintClipRect:
parentPaintClipRect
);
yield
*
fragment
.
compileChildren
(
parentSemanticsClipRect:
parentSemanticsClipRect
,
parentPaintClipRect:
parentPaintClipRect
,
// The fragment is not explicit, its elevation has been absorbed by
// the parent config (as thickness). We still need to make sure that
// its children are placed at the elevation dictated by this config.
elevationAdjustment:
elevationAdjustment
+
_config
.
elevation
,
);
}
return
;
}
...
...
@@ -3375,6 +3395,12 @@ class _SwitchableSemanticsFragment extends _InterestingSemanticsFragment {
..
isMergedIntoParent
=
_mergeIntoParent
..
tags
=
_tagsForChildren
;
node
.
elevationAdjustment
=
elevationAdjustment
;
if
(
elevationAdjustment
!=
0.0
)
{
_ensureConfigIsWritable
();
_config
.
elevation
+=
elevationAdjustment
;
}
if
(
geometry
!=
null
)
{
assert
(
_needsGeometryUpdate
);
node
...
...
@@ -3389,8 +3415,13 @@ class _SwitchableSemanticsFragment extends _InterestingSemanticsFragment {
}
final
List
<
SemanticsNode
>
children
=
<
SemanticsNode
>[];
for
(
_InterestingSemanticsFragment
fragment
in
_children
)
children
.
addAll
(
fragment
.
compileChildren
(
parentSemanticsClipRect:
node
.
parentSemanticsClipRect
,
parentPaintClipRect:
node
.
parentPaintClipRect
));
for
(
_InterestingSemanticsFragment
fragment
in
_children
)
{
children
.
addAll
(
fragment
.
compileChildren
(
parentSemanticsClipRect:
node
.
parentSemanticsClipRect
,
parentPaintClipRect:
node
.
parentPaintClipRect
,
elevationAdjustment:
0.0
,
));
}
if
(
_config
.
isSemanticBoundary
)
{
owner
.
assembleSemanticsNode
(
node
,
_config
,
children
);
...
...
@@ -3457,7 +3488,7 @@ class _AbortingSemanticsFragment extends _InterestingSemanticsFragment {
}
@override
Iterable
<
SemanticsNode
>
compileChildren
({
Rect
parentSemanticsClipRect
,
Rect
parentPaintClipRect
})
sync
*
{
Iterable
<
SemanticsNode
>
compileChildren
({
Rect
parentSemanticsClipRect
,
Rect
parentPaintClipRect
,
double
elevationAdjustment
})
sync
*
{
yield
owner
.
_semantics
;
}
...
...
packages/flutter/lib/src/rendering/proxy_box.dart
View file @
e4c8f1b9
...
...
@@ -1571,6 +1571,12 @@ abstract class _RenderPhysicalModelBase<T> extends _RenderCustomClip<T> {
@override
bool
get
alwaysNeedsCompositing
=>
_elevation
!=
0.0
&&
defaultTargetPlatform
==
TargetPlatform
.
fuchsia
;
@override
void
describeSemanticsConfiguration
(
SemanticsConfiguration
config
)
{
super
.
describeSemanticsConfiguration
(
config
);
config
.
elevation
=
elevation
;
}
@override
void
debugFillProperties
(
DiagnosticPropertiesBuilder
description
)
{
super
.
debugFillProperties
(
description
);
...
...
packages/flutter/lib/src/semantics/semantics.dart
View file @
e4c8f1b9
...
...
@@ -187,6 +187,8 @@ class SemanticsData extends Diagnosticable {
@required
this
.
hint
,
@required
this
.
textDirection
,
@required
this
.
rect
,
@required
this
.
elevation
,
@required
this
.
thickness
,
@required
this
.
textSelection
,
@required
this
.
scrollIndex
,
@required
this
.
scrollChildCount
,
...
...
@@ -305,6 +307,21 @@ class SemanticsData extends Diagnosticable {
/// parent).
final
Matrix4
transform
;
/// The elevation of this node relative to the parent semantics node.
///
/// See also:
///
/// * [SemanticsConfiguration.elevation] for a detailed discussion regarding
/// elevation and semantics.
final
double
elevation
;
/// The extent of this node along the z-axis beyond its [elevation]
///
/// See also:
///
/// * [SemanticsConfiguration.thickness] for a more detailed definition.
final
double
thickness
;
/// The identifiers for the custom semantics actions and standard action
/// overrides for this node.
///
...
...
@@ -329,6 +346,8 @@ class SemanticsData extends Diagnosticable {
super
.
debugFillProperties
(
properties
);
properties
.
add
(
DiagnosticsProperty
<
Rect
>(
'rect'
,
rect
,
showName:
false
));
properties
.
add
(
TransformProperty
(
'transform'
,
transform
,
showName:
false
,
defaultValue:
null
));
properties
.
add
(
DoubleProperty
(
'elevation'
,
elevation
,
defaultValue:
0.0
));
properties
.
add
(
DoubleProperty
(
'thickness'
,
thickness
,
defaultValue:
0.0
));
final
List
<
String
>
actionSummary
=
<
String
>[];
for
(
SemanticsAction
action
in
SemanticsAction
.
values
.
values
)
{
if
((
actions
&
action
.
index
)
!=
0
)
...
...
@@ -383,6 +402,8 @@ class SemanticsData extends Diagnosticable {
&&
typedOther
.
scrollExtentMax
==
scrollExtentMax
&&
typedOther
.
scrollExtentMin
==
scrollExtentMin
&&
typedOther
.
transform
==
transform
&&
typedOther
.
elevation
==
elevation
&&
typedOther
.
thickness
==
thickness
&&
_sortedListsEqual
(
typedOther
.
customSemanticsActionIds
,
customSemanticsActionIds
);
}
...
...
@@ -406,6 +427,8 @@ class SemanticsData extends Diagnosticable {
scrollExtentMax
,
scrollExtentMin
,
transform
,
elevation
,
thickness
,
ui
.
hashList
(
customSemanticsActionIds
),
);
}
...
...
@@ -1143,6 +1166,23 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin {
/// If this rect is null [parentSemanticsClipRect] also has to be null.
Rect
parentPaintClipRect
;
/// The elevation adjustment that the parent imposes on this node.
///
/// The [elevation] property is relative to the elevation of the parent
/// [SemanticsNode]. However, as [SemanticsConfiguration]s from various
/// ascending [RenderObjects] are merged into each other to form that
/// [SemanticsNode] the parent’s elevation may change. This requires an
/// adjustment of the child’s relative elevation which is represented by this
/// value.
///
/// The value is rarely accessed directly. Instead, for most use cases the
/// [elevation] value should be used, which includes this adjustment.
///
/// See also:
///
/// * [elevation], the actual elevation of this [SemanticsNode].
double
elevationAdjustment
;
/// The index of this node within the parent's list of semantic children.
///
/// This includes all semantic nodes, not just those currently in the
...
...
@@ -1409,6 +1449,8 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin {
bool
_isDifferentFromCurrentSemanticAnnotation
(
SemanticsConfiguration
config
)
{
return
_label
!=
config
.
label
||
_hint
!=
config
.
hint
||
_elevation
!=
config
.
elevation
||
_thickness
!=
config
.
thickness
||
_decreasedValue
!=
config
.
decreasedValue
||
_value
!=
config
.
value
||
_increasedValue
!=
config
.
increasedValue
||
...
...
@@ -1483,6 +1525,73 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin {
String
get
hint
=>
_hint
;
String
_hint
=
_kEmptyConfig
.
hint
;
/// The elevation along the z-axis at which the [rect] of this [SemanticsNode]
/// is located above its parent.
///
/// The value is relative to the parent's [elevation]. The sum of the
/// [elevation]s of all ancestor node plus this value determines the absolute
/// elevation of this [SemanticsNode].
///
/// See also:
///
/// * [thickness], which describes how much space in z-direction this
/// [SemanticsNode] occupies starting at this [elevation].
/// * [elevationAdjustment], which has been used to calculate this value.
double
get
elevation
=>
_elevation
;
double
_elevation
=
_kEmptyConfig
.
elevation
;
/// Describes how much space the [SemanticsNode] takes up along the z-axis.
///
/// A [SemanticsNode] represents multiple [RenderObject]s, which can be
/// located at various elevations in 3D. The [thickness] is the difference
/// between the absolute elevations of the lowest and highest [RenderObject]
/// represented by this [SemanticsNode]. In other words, the thickness
/// describes how high the box is that this [SemanticsNode] occupies in three
/// dimensional space. The two other dimensions are defined by [rect].
///
/// ## Sample Code
///
/// The following code stacks three [PhysicalModel]s on top of each other
/// separated by none-zero elevations:
///
/// ```dart
/// PhysicalModel( // A
/// color: Colors.amber,
/// elevation: 0.0,
/// child: Semantics(
/// explicitChildNodes: true,
/// child: PhysicalModel( // B
/// color: Colors.brown,
/// elevation: 5.0,
/// child: PhysicalModel( // C
/// color: Colors.cyan,
/// elevation: 10.0,
/// child: Placeholder(),
/// ),
/// ),
/// ),
/// );
/// ```
///
/// [PhysicalModel] C is elevated 10.0 above [PhysicalModel] B, which in turn
/// is elevated 5.0 above [PhysicalModel] A. The side view of this
/// constellation looks as follows:
///
/// ![A diagram illustrating the elevations of three PhysicalModels and their
/// corresponding SemanticsNodes.](https://flutter.github.io/assets-for-api-docs/assets/semantics/SemanticsNode.thickness.png)
///
/// In this example the [RenderObject]s for [PhysicalModel] C and B share one
/// [SemanticsNode] Y. Given the elevations of those [RenderObject]s, this
/// [SemanticsNode] has a [thickness] of 10.0 and an elevation of 5.0 over
/// its parent [SemanticsNode] X.
///
/// See also:
///
/// * [elevation], which describes the elevation of the box defined by
/// [thickness] and [rect] relative to the parent of this [SemanticsNode].
double
get
thickness
=>
_thickness
;
double
_thickness
=
_kEmptyConfig
.
thickness
;
/// Provides hint values which override the default hints on supported
/// platforms.
SemanticsHintOverrides
get
hintOverrides
=>
_hintOverrides
;
...
...
@@ -1581,6 +1690,8 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin {
_increasedValue
=
config
.
increasedValue
;
_hint
=
config
.
hint
;
_hintOverrides
=
config
.
hintOverrides
;
_elevation
=
config
.
elevation
;
_thickness
=
config
.
thickness
;
_flags
=
config
.
_flags
;
_textDirection
=
config
.
textDirection
;
_sortKey
=
config
.
sortKey
;
...
...
@@ -1629,6 +1740,8 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin {
double
scrollPosition
=
_scrollPosition
;
double
scrollExtentMax
=
_scrollExtentMax
;
double
scrollExtentMin
=
_scrollExtentMin
;
final
double
elevation
=
_elevation
;
double
thickness
=
_thickness
;
final
Set
<
int
>
customSemanticsActionIds
=
Set
<
int
>();
for
(
CustomSemanticsAction
action
in
_customSemanticsActions
.
keys
)
customSemanticsActionIds
.
add
(
CustomSemanticsAction
.
getIdentifier
(
action
));
...
...
@@ -1703,6 +1816,9 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin {
otherString:
node
.
_hint
,
otherTextDirection:
node
.
_textDirection
,
);
thickness
=
math
.
max
(
thickness
,
node
.
_thickness
+
node
.
_elevation
);
return
true
;
});
}
...
...
@@ -1718,6 +1834,8 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin {
textDirection:
textDirection
,
rect:
rect
,
transform:
transform
,
elevation:
elevation
,
thickness:
thickness
,
tags:
mergedTags
,
textSelection:
textSelection
,
scrollChildCount:
scrollChildCount
,
...
...
@@ -1786,6 +1904,8 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin {
scrollExtentMax:
data
.
scrollExtentMax
!=
null
?
data
.
scrollExtentMax
:
double
.
nan
,
scrollExtentMin:
data
.
scrollExtentMin
!=
null
?
data
.
scrollExtentMin
:
double
.
nan
,
transform:
data
.
transform
?.
storage
??
_kIdentityTransform
,
elevation:
data
.
elevation
,
thickness:
data
.
thickness
,
childrenInTraversalOrder:
childrenInTraversalOrder
,
childrenInHitTestOrder:
childrenInHitTestOrder
,
additionalActions:
customSemanticsActionIds
??
_kEmptyCustomSemanticsActionsList
,
...
...
@@ -1923,6 +2043,8 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin {
properties
.
add
(
DoubleProperty
(
'scrollExtentMin'
,
scrollExtentMin
,
defaultValue:
null
));
properties
.
add
(
DoubleProperty
(
'scrollPosition'
,
scrollPosition
,
defaultValue:
null
));
properties
.
add
(
DoubleProperty
(
'scrollExtentMax'
,
scrollExtentMax
,
defaultValue:
null
));
properties
.
add
(
DoubleProperty
(
'elevation'
,
elevation
,
defaultValue:
0.0
));
properties
.
add
(
DoubleProperty
(
'thicknes'
,
thickness
,
defaultValue:
0.0
));
}
/// Returns a string representation of this node and its descendants.
...
...
@@ -3115,6 +3237,36 @@ class SemanticsConfiguration {
_hasBeenAnnotated
=
true
;
}
/// The elevation in z-direction at which the owning [RenderObject] is
/// located relative to its parent.
double
get
elevation
=>
_elevation
;
double
_elevation
=
0.0
;
set
elevation
(
double
value
)
{
assert
(
value
!=
null
&&
value
>=
0.0
);
if
(
value
==
_elevation
)
{
return
;
}
_elevation
=
value
;
_hasBeenAnnotated
=
true
;
}
/// The extend that the owning [RenderObject] occupies in z-direction starting
/// at [elevation].
///
/// It's extremely rare to set this value directly. Instead, it is calculated
/// implicitly when other [SemanticsConfiguration]s are merged into this one
/// via [absorb].
double
get
thickness
=>
_thickness
;
double
_thickness
=
0.0
;
set
thickness
(
double
value
)
{
assert
(
value
!=
null
&&
value
>=
0.0
);
if
(
value
==
_thickness
)
{
return
;
}
_thickness
=
value
;
_hasBeenAnnotated
=
true
;
}
/// Whether the semantics node is the root of a subtree for which values
/// should be announced.
///
...
...
@@ -3436,55 +3588,60 @@ class SemanticsConfiguration {
return
true
;
}
/// Absorb the semantic information from `
other
` into this configuration.
/// Absorb the semantic information from `
child
` into this configuration.
///
/// This adds the semantic information of both configurations and saves the
/// result in this configuration.
///
/// The [RenderObject] owning the `child` configuration must be a descendant
/// of the [RenderObject] that owns this configuration.
///
/// Only configurations that have [explicitChildNodes] set to false can
/// absorb other configurations and it is recommended to only absorb compatible
/// configurations as determined by [isCompatibleWith].
void
absorb
(
SemanticsConfiguration
other
)
{
void
absorb
(
SemanticsConfiguration
child
)
{
assert
(!
explicitChildNodes
);
if
(!
other
.
hasBeenAnnotated
)
if
(!
child
.
hasBeenAnnotated
)
return
;
_actions
.
addAll
(
other
.
_actions
);
_customSemanticsActions
.
addAll
(
other
.
_customSemanticsActions
);
_actionsAsBits
|=
other
.
_actionsAsBits
;
_flags
|=
other
.
_flags
;
_textSelection
??=
other
.
_textSelection
;
_scrollPosition
??=
other
.
_scrollPosition
;
_scrollExtentMax
??=
other
.
_scrollExtentMax
;
_scrollExtentMin
??=
other
.
_scrollExtentMin
;
_hintOverrides
??=
other
.
_hintOverrides
;
_indexInParent
??=
other
.
indexInParent
;
_scrollIndex
??=
other
.
_scrollIndex
;
_scrollChildCount
??=
other
.
_scrollChildCount
;
textDirection
??=
other
.
textDirection
;
_sortKey
??=
other
.
_sortKey
;
_actions
.
addAll
(
child
.
_actions
);
_customSemanticsActions
.
addAll
(
child
.
_customSemanticsActions
);
_actionsAsBits
|=
child
.
_actionsAsBits
;
_flags
|=
child
.
_flags
;
_textSelection
??=
child
.
_textSelection
;
_scrollPosition
??=
child
.
_scrollPosition
;
_scrollExtentMax
??=
child
.
_scrollExtentMax
;
_scrollExtentMin
??=
child
.
_scrollExtentMin
;
_hintOverrides
??=
child
.
_hintOverrides
;
_indexInParent
??=
child
.
indexInParent
;
_scrollIndex
??=
child
.
_scrollIndex
;
_scrollChildCount
??=
child
.
_scrollChildCount
;
textDirection
??=
child
.
textDirection
;
_sortKey
??=
child
.
_sortKey
;
_label
=
_concatStrings
(
thisString:
_label
,
thisTextDirection:
textDirection
,
otherString:
other
.
_label
,
otherTextDirection:
other
.
textDirection
,
otherString:
child
.
_label
,
otherTextDirection:
child
.
textDirection
,
);
if
(
_decreasedValue
==
''
||
_decreasedValue
==
null
)
_decreasedValue
=
other
.
_decreasedValue
;
_decreasedValue
=
child
.
_decreasedValue
;
if
(
_value
==
''
||
_value
==
null
)
_value
=
other
.
_value
;
_value
=
child
.
_value
;
if
(
_increasedValue
==
''
||
_increasedValue
==
null
)
_increasedValue
=
other
.
_increasedValue
;
_increasedValue
=
child
.
_increasedValue
;
_hint
=
_concatStrings
(
thisString:
_hint
,
thisTextDirection:
textDirection
,
otherString:
other
.
_hint
,
otherTextDirection:
other
.
textDirection
,
otherString:
child
.
_hint
,
otherTextDirection:
child
.
textDirection
,
);
_hasBeenAnnotated
=
_hasBeenAnnotated
||
other
.
_hasBeenAnnotated
;
_thickness
=
math
.
max
(
_thickness
,
child
.
_thickness
+
child
.
_elevation
);
_hasBeenAnnotated
=
_hasBeenAnnotated
||
child
.
_hasBeenAnnotated
;
}
/// Returns an exact copy of this configuration.
...
...
@@ -3503,6 +3660,8 @@ class SemanticsConfiguration {
..
_decreasedValue
=
_decreasedValue
..
_hint
=
_hint
..
_hintOverrides
=
_hintOverrides
..
_elevation
=
_elevation
..
_thickness
=
_thickness
..
_flags
=
_flags
..
_tagsForChildren
=
_tagsForChildren
..
_textSelection
=
_textSelection
...
...
packages/flutter/test/material/card_test.dart
View file @
e4c8f1b9
...
...
@@ -40,27 +40,34 @@ void main() {
children:
<
TestSemantics
>[
TestSemantics
(
id:
1
,
label:
'I am text!'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
id:
2
,
label:
'Moar text!!1'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
id:
3
,
label:
'Button'
,
textDirection:
TextDirection
.
ltr
,
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
,
],
flags:
<
SemanticsFlag
>[
SemanticsFlag
.
isButton
,
SemanticsFlag
.
hasEnabledState
,
SemanticsFlag
.
isEnabled
,
elevation:
1.0
,
thickness:
0.0
,
children:
<
TestSemantics
>[
TestSemantics
(
id:
2
,
label:
'I am text!'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
id:
3
,
label:
'Moar text!!1'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
id:
4
,
label:
'Button'
,
textDirection:
TextDirection
.
ltr
,
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
,
],
flags:
<
SemanticsFlag
>[
SemanticsFlag
.
isButton
,
SemanticsFlag
.
hasEnabledState
,
SemanticsFlag
.
isEnabled
,
],
),
],
)
,
)
],
),
ignoreTransform:
true
,
...
...
packages/flutter/test/material/date_picker_test.dart
View file @
e4c8f1b9
...
...
@@ -425,23 +425,23 @@ void _tests() {
final
SemanticsTester
semantics
=
SemanticsTester
(
tester
);
await
preparePicker
(
tester
,
(
Future
<
DateTime
>
date
)
async
{
final
TestSemantics
expected
=
TestSemantics
(
flags:
<
SemanticsFlag
>[
SemanticsFlag
.
scopesRoute
,
],
flags:
<
SemanticsFlag
>[
SemanticsFlag
.
scopesRoute
],
children:
<
TestSemantics
>[
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
flags:
<
SemanticsFlag
>[
SemanticsFlag
.
isSelected
],
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'Fri, Jan 15'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
elevation:
24.0
,
thickness:
0.0
,
children:
<
TestSemantics
>[
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
flags:
<
SemanticsFlag
>[
SemanticsFlag
.
isSelected
],
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'Fri, Jan 15'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
children:
<
TestSemantics
>[
TestSemantics
(
...
...
@@ -452,160 +452,164 @@ void _tests() {
TestSemantics
(
children:
<
TestSemantics
>[
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'1, Friday, January 1, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'2, Saturday, January 2, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'3, Sunday, January 3, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'4, Monday, January 4, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'5, Tuesday, January 5, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'6, Wednesday, January 6, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'7, Thursday, January 7, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'8, Friday, January 8, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'9, Saturday, January 9, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'10, Sunday, January 10, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'11, Monday, January 11, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'12, Tuesday, January 12, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'13, Wednesday, January 13, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'14, Thursday, January 14, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
flags:
<
SemanticsFlag
>[
SemanticsFlag
.
isSelected
],
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'15, Friday, January 15, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'16, Saturday, January 16, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'17, Sunday, January 17, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'18, Monday, January 18, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'19, Tuesday, January 19, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'20, Wednesday, January 20, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'21, Thursday, January 21, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'22, Friday, January 22, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'23, Saturday, January 23, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'24, Sunday, January 24, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'25, Monday, January 25, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'26, Tuesday, January 26, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'27, Wednesday, January 27, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'28, Thursday, January 28, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'29, Friday, January 29, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'30, Saturday, January 30, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'31, Sunday, January 31, 2016'
,
textDirection:
TextDirection
.
ltr
,
children:
<
TestSemantics
>[
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'1, Friday, January 1, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'2, Saturday, January 2, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'3, Sunday, January 3, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'4, Monday, January 4, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'5, Tuesday, January 5, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'6, Wednesday, January 6, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'7, Thursday, January 7, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'8, Friday, January 8, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'9, Saturday, January 9, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'10, Sunday, January 10, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'11, Monday, January 11, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'12, Tuesday, January 12, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'13, Wednesday, January 13, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'14, Thursday, January 14, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
flags:
<
SemanticsFlag
>[
SemanticsFlag
.
isSelected
],
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'15, Friday, January 15, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'16, Saturday, January 16, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'17, Sunday, January 17, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'18, Monday, January 18, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'19, Tuesday, January 19, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'20, Wednesday, January 20, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'21, Thursday, January 21, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'22, Friday, January 22, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'23, Saturday, January 23, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'24, Sunday, January 24, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'25, Monday, January 25, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'26, Tuesday, January 26, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'27, Wednesday, January 27, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'28, Thursday, January 28, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'29, Friday, January 29, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'30, Saturday, January 30, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'31, Sunday, January 31, 2016'
,
textDirection:
TextDirection
.
ltr
,
),
],
),
],
),
...
...
@@ -615,32 +619,32 @@ void _tests() {
),
],
),
TestSemantics
(
flags:
<
SemanticsFlag
>[
SemanticsFlag
.
isButton
,
SemanticsFlag
.
hasEnabledState
,
SemanticsFlag
.
isEnabled
],
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'Previous month December 2015'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
flags:
<
SemanticsFlag
>[
SemanticsFlag
.
isButton
,
SemanticsFlag
.
hasEnabledState
,
SemanticsFlag
.
isEnabled
],
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'Next month February 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
flags:
<
SemanticsFlag
>[
SemanticsFlag
.
isButton
,
SemanticsFlag
.
hasEnabledState
,
SemanticsFlag
.
isEnabled
],
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'CANCEL'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
flags:
<
SemanticsFlag
>[
SemanticsFlag
.
isButton
,
SemanticsFlag
.
hasEnabledState
,
SemanticsFlag
.
isEnabled
],
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'OK'
,
textDirection:
TextDirection
.
ltr
,
),
],
),
TestSemantics
(
flags:
<
SemanticsFlag
>[
SemanticsFlag
.
isButton
,
SemanticsFlag
.
hasEnabledState
,
SemanticsFlag
.
isEnabled
],
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'Previous month December 2015'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
flags:
<
SemanticsFlag
>[
SemanticsFlag
.
isButton
,
SemanticsFlag
.
hasEnabledState
,
SemanticsFlag
.
isEnabled
],
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'Next month February 2016'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
flags:
<
SemanticsFlag
>[
SemanticsFlag
.
isButton
,
SemanticsFlag
.
hasEnabledState
,
SemanticsFlag
.
isEnabled
],
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'CANCEL'
,
textDirection:
TextDirection
.
ltr
,
),
TestSemantics
(
flags:
<
SemanticsFlag
>[
SemanticsFlag
.
isButton
,
SemanticsFlag
.
hasEnabledState
,
SemanticsFlag
.
isEnabled
],
actions:
<
SemanticsAction
>[
SemanticsAction
.
tap
],
label:
'OK'
,
textDirection:
TextDirection
.
ltr
,
),
],
);
...
...
packages/flutter/test/semantics/semantics_elevation_test.dart
0 → 100644
View file @
e4c8f1b9
// 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/material.dart'
;
import
'package:flutter/rendering.dart'
;
import
'package:flutter/widgets.dart'
;
import
'package:flutter_test/flutter_test.dart'
;
import
'../widgets/semantics_tester.dart'
;
void
main
(
)
{
testWidgets
(
'SemanticsNodes overlapping in z'
,
(
WidgetTester
tester
)
async
{
// Cards are semantic boundaries that always own their own SemanticNode,
// PhysicalModels merge their semantics information into parent.
//
// Side view of the widget tree:
//
// Card('abs. elevation: 30') ---------------
// | 8 ----------- Card('abs. elevation 25')
// Card('abs. elevation: 22') --------------- |
// | 7 |
// PhysicalModel('abs. elevation: 15') --------------- | 15
// | 5 |
// --------------------------------------- Card('abs. elevation: 10')
// | 10
// |
// --------------------------------------- 'ground'
final
SemanticsTester
semantics
=
SemanticsTester
(
tester
);
await
tester
.
pumpWidget
(
MaterialApp
(
home:
Column
(
children:
<
Widget
>[
const
Text
(
'ground'
),
Card
(
elevation:
10.0
,
child:
Column
(
children:
<
Widget
>[
const
Text
(
'absolute elevation: 10'
),
PhysicalModel
(
elevation:
5.0
,
color:
Colors
.
black
,
child:
Column
(
children:
<
Widget
>[
const
Text
(
'absolute elevation: 15'
),
Card
(
elevation:
7.0
,
child:
Column
(
children:
const
<
Widget
>[
Text
(
'absolute elevation: 22'
),
Card
(
elevation:
8.0
,
child:
Text
(
'absolute elevation: 30'
),
)
],
),
)
],
),
),
const
Card
(
elevation:
15.0
,
child:
Text
(
'absolute elevation: 25'
),
)
],
),
)
],
),
));
final
SemanticsNode
ground
=
tester
.
getSemantics
(
find
.
text
(
'ground'
));
expect
(
ground
.
thickness
,
0.0
);
expect
(
ground
.
elevation
,
0.0
);
expect
(
ground
.
label
,
'ground'
);
final
SemanticsNode
elevation10
=
tester
.
getSemantics
(
find
.
text
(
'absolute elevation: 10'
));
final
SemanticsNode
elevation15
=
tester
.
getSemantics
(
find
.
text
(
'absolute elevation: 15'
));
expect
(
elevation10
,
same
(
elevation15
));
// configs got merged into each other.
expect
(
elevation10
.
thickness
,
15.0
);
expect
(
elevation10
.
elevation
,
0.0
);
expect
(
elevation10
.
label
,
'absolute elevation: 10
\n
absolute elevation: 15'
);
final
SemanticsNode
elevation22
=
tester
.
getSemantics
(
find
.
text
(
'absolute elevation: 22'
));
expect
(
elevation22
.
thickness
,
7.0
);
expect
(
elevation22
.
elevation
,
15.0
);
expect
(
elevation22
.
label
,
'absolute elevation: 22'
);
final
SemanticsNode
elevation25
=
tester
.
getSemantics
(
find
.
text
(
'absolute elevation: 25'
));
expect
(
elevation25
.
thickness
,
15.0
);
expect
(
elevation25
.
elevation
,
10.0
);
expect
(
elevation22
.
label
,
'absolute elevation: 22'
);
final
SemanticsNode
elevation30
=
tester
.
getSemantics
(
find
.
text
(
'absolute elevation: 30'
));
expect
(
elevation30
.
thickness
,
8.0
);
expect
(
elevation30
.
elevation
,
7.0
);
expect
(
elevation30
.
label
,
'absolute elevation: 30'
);
semantics
.
dispose
();
});
testWidgets
(
'SemanticsNodes overlapping in z with switched children'
,
(
WidgetTester
tester
)
async
{
// Same as 'SemanticsNodes overlapping in z', but the order of children
// is reversed
final
SemanticsTester
semantics
=
SemanticsTester
(
tester
);
await
tester
.
pumpWidget
(
MaterialApp
(
home:
Column
(
children:
<
Widget
>[
const
Text
(
'ground'
),
Card
(
elevation:
10.0
,
child:
Column
(
children:
<
Widget
>[
const
Card
(
elevation:
15.0
,
child:
Text
(
'absolute elevation: 25'
),
),
PhysicalModel
(
elevation:
5.0
,
color:
Colors
.
black
,
child:
Column
(
children:
<
Widget
>[
const
Text
(
'absolute elevation: 15'
),
Card
(
elevation:
7.0
,
child:
Column
(
children:
const
<
Widget
>[
Text
(
'absolute elevation: 22'
),
Card
(
elevation:
8.0
,
child:
Text
(
'absolute elevation: 30'
),
)
],
),
)
],
),
),
const
Text
(
'absolute elevation: 10'
),
],
),
)
],
),
));
final
SemanticsNode
ground
=
tester
.
getSemantics
(
find
.
text
(
'ground'
));
expect
(
ground
.
thickness
,
0.0
);
expect
(
ground
.
elevation
,
0.0
);
expect
(
ground
.
label
,
'ground'
);
final
SemanticsNode
elevation10
=
tester
.
getSemantics
(
find
.
text
(
'absolute elevation: 10'
));
final
SemanticsNode
elevation15
=
tester
.
getSemantics
(
find
.
text
(
'absolute elevation: 15'
));
expect
(
elevation10
,
same
(
elevation15
));
// configs got merged into each other.
expect
(
elevation10
.
thickness
,
15.0
);
expect
(
elevation10
.
elevation
,
0.0
);
expect
(
elevation10
.
label
,
'absolute elevation: 15
\n
absolute elevation: 10'
);
final
SemanticsNode
elevation22
=
tester
.
getSemantics
(
find
.
text
(
'absolute elevation: 22'
));
expect
(
elevation22
.
thickness
,
7.0
);
expect
(
elevation22
.
elevation
,
15.0
);
expect
(
elevation22
.
label
,
'absolute elevation: 22'
);
final
SemanticsNode
elevation25
=
tester
.
getSemantics
(
find
.
text
(
'absolute elevation: 25'
));
expect
(
elevation25
.
thickness
,
15.0
);
expect
(
elevation25
.
elevation
,
10.0
);
expect
(
elevation22
.
label
,
'absolute elevation: 22'
);
final
SemanticsNode
elevation30
=
tester
.
getSemantics
(
find
.
text
(
'absolute elevation: 30'
));
expect
(
elevation30
.
thickness
,
8.0
);
expect
(
elevation30
.
elevation
,
7.0
);
expect
(
elevation30
.
label
,
'absolute elevation: 30'
);
semantics
.
dispose
();
});
testWidgets
(
'single node thickness'
,
(
WidgetTester
tester
)
async
{
final
SemanticsTester
semantics
=
SemanticsTester
(
tester
);
await
tester
.
pumpWidget
(
const
MaterialApp
(
home:
Center
(
child:
Material
(
elevation:
24.0
,
child:
Text
(
'Hello'
),
)
)
));
final
SemanticsNode
node
=
tester
.
getSemantics
(
find
.
text
(
'Hello'
));
expect
(
node
.
thickness
,
0.0
);
expect
(
node
.
elevation
,
24.0
);
expect
(
node
.
label
,
'Hello'
);
semantics
.
dispose
();
});
testWidgets
(
'force-merge'
,
(
WidgetTester
tester
)
async
{
final
SemanticsTester
semantics
=
SemanticsTester
(
tester
);
await
tester
.
pumpWidget
(
MaterialApp
(
home:
Card
(
elevation:
10.0
,
child:
Column
(
children:
<
Widget
>[
const
Text
(
'abs. elevation: 10.0'
),
MergeSemantics
(
child:
Semantics
(
explicitChildNodes:
true
,
// just to be sure that it's going to be an explicit merge
child:
Column
(
children:
const
<
Widget
>[
Card
(
elevation:
15.0
,
child:
Text
(
'abs. elevation 25.0'
),
),
Card
(
elevation:
5.0
,
child:
Text
(
'abs. elevation 15.0'
),
),
],
),
),
),
],
)
)
));
final
SemanticsNode
elevation10
=
tester
.
getSemantics
(
find
.
text
(
'abs. elevation: 10.0'
));
expect
(
elevation10
.
thickness
,
10.0
);
expect
(
elevation10
.
elevation
,
0.0
);
expect
(
elevation10
.
label
,
'abs. elevation: 10.0'
);
expect
(
elevation10
.
childrenCount
,
1
);
// TODO(goderbauer): remove awkward workaround when accessing force-merged
// SemanticsData becomes easier, https://github.com/flutter/flutter/issues/25669
SemanticsData
mergedChildData
;
elevation10
.
visitChildren
((
SemanticsNode
child
)
{
expect
(
mergedChildData
,
isNull
);
mergedChildData
=
child
.
getSemanticsData
();
return
true
;
});
expect
(
mergedChildData
.
thickness
,
15.0
);
expect
(
mergedChildData
.
elevation
,
10.0
);
expect
(
mergedChildData
.
label
,
'abs. elevation 25.0
\n
abs. elevation 15.0'
);
semantics
.
dispose
();
});
testWidgets
(
'force-merge with inversed children'
,
(
WidgetTester
tester
)
async
{
final
SemanticsTester
semantics
=
SemanticsTester
(
tester
);
await
tester
.
pumpWidget
(
MaterialApp
(
home:
Card
(
elevation:
10.0
,
child:
Column
(
children:
<
Widget
>[
const
Text
(
'abs. elevation: 10.0'
),
MergeSemantics
(
child:
Semantics
(
explicitChildNodes:
true
,
// just to be sure that it's going to be an explicit merge
child:
Column
(
children:
const
<
Widget
>[
Card
(
elevation:
5.0
,
child:
Text
(
'abs. elevation 15.0'
),
),
Card
(
elevation:
15.0
,
child:
Text
(
'abs. elevation 25.0'
),
),
],
),
),
),
],
)
)
));
final
SemanticsNode
elevation10
=
tester
.
getSemantics
(
find
.
text
(
'abs. elevation: 10.0'
));
expect
(
elevation10
.
thickness
,
10.0
);
expect
(
elevation10
.
elevation
,
0.0
);
expect
(
elevation10
.
label
,
'abs. elevation: 10.0'
);
expect
(
elevation10
.
childrenCount
,
1
);
// TODO(goderbauer): remove awkward workaround when accessing force-merged
// SemanticsData becomes easier, https://github.com/flutter/flutter/issues/25669
SemanticsData
mergedChildData
;
elevation10
.
visitChildren
((
SemanticsNode
child
)
{
expect
(
mergedChildData
,
isNull
);
mergedChildData
=
child
.
getSemanticsData
();
return
true
;
});
expect
(
mergedChildData
.
thickness
,
15.0
);
expect
(
mergedChildData
.
elevation
,
10.0
);
expect
(
mergedChildData
.
label
,
'abs. elevation 15.0
\n
abs. elevation 25.0'
);
semantics
.
dispose
();
});
}
packages/flutter/test/semantics/semantics_test.dart
View file @
e4c8f1b9
...
...
@@ -353,6 +353,8 @@ void main() {
' scrollExtentMin: null
\n
'
' scrollPosition: null
\n
'
' scrollExtentMax: null
\n
'
' elevation: 0.0
\n
'
' thicknes: 0.0
\n
'
);
final
SemanticsConfiguration
config
=
SemanticsConfiguration
()
...
...
@@ -445,6 +447,8 @@ void main() {
' scrollExtentMin: null
\n
'
' scrollPosition: null
\n
'
' scrollExtentMax: null
\n
'
' elevation: 0.0
\n
'
' thicknes: 0.0
\n
'
);
});
...
...
packages/flutter/test/widgets/semantics_tester.dart
View file @
e4c8f1b9
...
...
@@ -46,6 +46,8 @@ class TestSemantics {
this
.
textDirection
,
this
.
rect
,
this
.
transform
,
this
.
elevation
,
this
.
thickness
,
this
.
textSelection
,
this
.
children
=
const
<
TestSemantics
>[],
this
.
scrollIndex
,
...
...
@@ -87,6 +89,8 @@ class TestSemantics {
assert
(
value
!=
null
),
assert
(
hint
!=
null
),
rect
=
TestSemantics
.
rootRect
,
elevation
=
0.0
,
thickness
=
0.0
,
assert
(
children
!=
null
),
tags
=
tags
?.
toSet
()
??
Set
<
SemanticsTag
>();
...
...
@@ -111,6 +115,8 @@ class TestSemantics {
this
.
textDirection
,
this
.
rect
,
Matrix4
transform
,
this
.
elevation
,
this
.
thickness
,
this
.
textSelection
,
this
.
children
=
const
<
TestSemantics
>[],
this
.
scrollIndex
,
...
...
@@ -206,6 +212,21 @@ class TestSemantics {
/// parent).
final
Matrix4
transform
;
/// The elevation of this node reative to the parent node.
///
/// See also:
///
/// * [SemanticsConfiguration.elevation] for a detailed discussion regarding
/// elevation and semantics.
final
double
elevation
;
/// The extend that this node occupies in z-direction starting at [elevation].
///
/// See also:
///
/// * [SemanticsConfiguration.thickness] for a more detailed definition.
final
double
thickness
;
/// The index of the first visible semantic node within a scrollable.
final
int
scrollIndex
;
...
...
@@ -279,6 +300,12 @@ class TestSemantics {
return
fail
(
'expected node id
$id
to have rect
$rect
but found rect
${nodeData.rect}
.'
);
if
(!
ignoreTransform
&&
transform
!=
nodeData
.
transform
)
return
fail
(
'expected node id
$id
to have transform
$transform
but found transform:
\n
${nodeData.transform}
.'
);
if
(
elevation
!=
null
&&
elevation
!=
nodeData
.
elevation
)
{
return
fail
(
'expected node id
$id
to have elevation
$elevation
but found elevation:
\n
${nodeData.elevation}
.'
);
}
if
(
thickness
!=
null
&&
thickness
!=
nodeData
.
thickness
)
{
return
fail
(
'expected node id
$id
to have thickness
$thickness
but found thickness:
\n
${nodeData.thickness}
.'
);
}
if
(
textSelection
?.
baseOffset
!=
nodeData
.
textSelection
?.
baseOffset
||
textSelection
?.
extentOffset
!=
nodeData
.
textSelection
?.
extentOffset
)
{
return
fail
(
'expected node id
$id
to have textSelection [
${textSelection?.baseOffset}
,
${textSelection?.end}
] but found: [
${nodeData.textSelection?.baseOffset}
,
${nodeData.textSelection?.extentOffset}
].'
);
}
...
...
@@ -346,6 +373,10 @@ class TestSemantics {
buf
.
writeln
(
'
$indent
rect:
$rect
,'
);
if
(
transform
!=
null
)
buf
.
writeln
(
'
$indent
transform:
\n
${transform.toString().trim().split('\n').map<String>((String line) => '$indent $line').join('\n')}
,'
);
if
(
elevation
!=
null
)
buf
.
writeln
(
'
$indent
elevation:
$elevation
,'
);
if
(
thickness
!=
null
)
buf
.
writeln
(
'
$indent
thickness:
$thickness
,'
);
buf
.
writeln
(
'
$indent
children: <TestSemantics>['
);
for
(
TestSemantics
child
in
children
)
{
buf
.
writeln
(
'
${child.toString(indentAmount + 2)}
,'
);
...
...
packages/flutter_test/lib/src/matchers.dart
View file @
e4c8f1b9
...
...
@@ -355,6 +355,8 @@ Matcher matchesSemantics({
TextDirection
textDirection
,
Rect
rect
,
Size
size
,
double
elevation
,
double
thickness
,
// Flags //
bool
hasCheckedState
=
false
,
bool
isChecked
=
false
,
...
...
@@ -503,6 +505,8 @@ Matcher matchesSemantics({
textDirection:
textDirection
,
rect:
rect
,
size:
size
,
elevation:
elevation
,
thickness:
thickness
,
customActions:
customActions
,
hintOverrides:
hintOverrides
,
children:
children
,
...
...
@@ -1685,6 +1689,8 @@ class _MatchesSemanticsData extends Matcher {
this
.
textDirection
,
this
.
rect
,
this
.
size
,
this
.
elevation
,
this
.
thickness
,
this
.
customActions
,
this
.
hintOverrides
,
this
.
children
,
...
...
@@ -1702,6 +1708,8 @@ class _MatchesSemanticsData extends Matcher {
final
TextDirection
textDirection
;
final
Rect
rect
;
final
Size
size
;
final
double
elevation
;
final
double
thickness
;
final
List
<
Matcher
>
children
;
@override
...
...
@@ -1727,6 +1735,10 @@ class _MatchesSemanticsData extends Matcher {
description
.
add
(
' with rect:
$rect
'
);
if
(
size
!=
null
)
description
.
add
(
' with size:
$size
'
);
if
(
elevation
!=
null
)
description
.
add
(
' with elevation:
$elevation
'
);
if
(
thickness
!=
null
)
description
.
add
(
' with thickness:
$thickness
'
);
if
(
customActions
!=
null
)
description
.
add
(
' with custom actions:
$customActions
'
);
if
(
hintOverrides
!=
null
)
...
...
@@ -1763,6 +1775,10 @@ class _MatchesSemanticsData extends Matcher {
return
failWithDescription
(
matchState
,
'rect was:
${data.rect}
'
);
if
(
size
!=
null
&&
size
!=
data
.
rect
.
size
)
return
failWithDescription
(
matchState
,
'size was:
${data.rect.size}
'
);
if
(
elevation
!=
null
&&
elevation
!=
data
.
elevation
)
return
failWithDescription
(
matchState
,
'elevation was:
${data.elevation}
'
);
if
(
thickness
!=
null
&&
thickness
!=
data
.
thickness
)
return
failWithDescription
(
matchState
,
'thickness was:
${data.thickness}
'
);
if
(
actions
!=
null
)
{
int
actionBits
=
0
;
for
(
SemanticsAction
action
in
actions
)
...
...
packages/flutter_test/test/matchers_test.dart
View file @
e4c8f1b9
...
...
@@ -494,6 +494,8 @@ void main() {
hint:
'e'
,
textDirection:
TextDirection
.
ltr
,
rect:
Rect
.
fromLTRB
(
0.0
,
0.0
,
10.0
,
10.0
),
elevation:
3.0
,
thickness:
4.0
,
textSelection:
null
,
scrollIndex:
null
,
scrollChildCount:
null
,
...
...
@@ -508,6 +510,8 @@ void main() {
expect
(
node
,
matchesSemantics
(
rect:
Rect
.
fromLTRB
(
0.0
,
0.0
,
10.0
,
10.0
),
size:
const
Size
(
10.0
,
10.0
),
elevation:
3.0
,
thickness:
4.0
,
/* Flags */
hasCheckedState:
true
,
isChecked:
true
,
...
...
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