Unverified Commit e4c8f1b9 authored by Michael Goderbauer's avatar Michael Goderbauer Committed by GitHub

3D SemanticsTree (#25670)

parent 14faa8d9
02905560cf2c2132a7adea10943001f29325f3be ecbdcf8d56d3aba0212c2b1b923466023ef09b4e
...@@ -524,13 +524,15 @@ class _AppBarState extends State<AppBar> { ...@@ -524,13 +524,15 @@ class _AppBarState extends State<AppBar> {
return Semantics( return Semantics(
container: true, container: true,
explicitChildNodes: true,
child: AnnotatedRegion<SystemUiOverlayStyle>( child: AnnotatedRegion<SystemUiOverlayStyle>(
value: overlayStyle, value: overlayStyle,
child: Material( child: Material(
color: widget.backgroundColor ?? themeData.primaryColor, color: widget.backgroundColor ?? themeData.primaryColor,
elevation: widget.elevation, elevation: widget.elevation,
child: appBar, child: Semantics(
explicitChildNodes: true,
child: appBar,
),
), ),
), ),
); );
......
...@@ -567,43 +567,30 @@ class _BottomNavigationBarState extends State<BottomNavigationBar> with TickerPr ...@@ -567,43 +567,30 @@ class _BottomNavigationBarState extends State<BottomNavigationBar> with TickerPr
break; break;
} }
return Semantics( return Semantics(
container: true,
explicitChildNodes: true, explicitChildNodes: true,
child: Stack( child: Material(
children: <Widget>[ elevation: 8.0,
Positioned.fill( color: backgroundColor,
child: Material( // Casts shadow. child: ConstrainedBox(
elevation: 8.0, constraints: BoxConstraints(minHeight: kBottomNavigationBarHeight + additionalBottomPadding),
color: backgroundColor, child: CustomPaint(
painter: _RadialPainter(
circles: _circles.toList(),
textDirection: Directionality.of(context),
), ),
), child: Material( // Splashes.
ConstrainedBox( type: MaterialType.transparency,
constraints: BoxConstraints(minHeight: kBottomNavigationBarHeight + additionalBottomPadding), child: Padding(
child: Stack( padding: EdgeInsets.only(bottom: additionalBottomPadding),
children: <Widget>[ child: MediaQuery.removePadding(
Positioned.fill( context: context,
child: CustomPaint( removeBottom: true,
painter: _RadialPainter( child: _createContainer(_createTiles()),
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()),
),
),
), ),
], ),
), ),
), ),
], ),
), ),
); );
} }
......
...@@ -135,7 +135,6 @@ class Card extends StatelessWidget { ...@@ -135,7 +135,6 @@ class Card extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Semantics( return Semantics(
container: semanticContainer, container: semanticContainer,
explicitChildNodes: !semanticContainer,
child: Container( child: Container(
margin: margin ?? const EdgeInsets.all(4.0), margin: margin ?? const EdgeInsets.all(4.0),
child: Material( child: Material(
...@@ -146,7 +145,10 @@ class Card extends StatelessWidget { ...@@ -146,7 +145,10 @@ class Card extends StatelessWidget {
borderRadius: BorderRadius.all(Radius.circular(4.0)), borderRadius: BorderRadius.all(Radius.circular(4.0)),
), ),
clipBehavior: clipBehavior, clipBehavior: clipBehavior,
child: child, child: Semantics(
explicitChildNodes: !semanticContainer,
child: child,
),
), ),
), ),
); );
......
...@@ -311,7 +311,11 @@ class AlertDialog extends StatelessWidget { ...@@ -311,7 +311,11 @@ class AlertDialog extends StatelessWidget {
padding: titlePadding ?? EdgeInsets.fromLTRB(24.0, 24.0, 24.0, content == null ? 20.0 : 0.0), padding: titlePadding ?? EdgeInsets.fromLTRB(24.0, 24.0, 24.0, content == null ? 20.0 : 0.0),
child: DefaultTextStyle( child: DefaultTextStyle(
style: titleTextStyle ?? dialogTheme.titleTextStyle ?? theme.textTheme.title, style: titleTextStyle ?? dialogTheme.titleTextStyle ?? theme.textTheme.title,
child: Semantics(child: title, namesRoute: true), child: Semantics(
child: title,
namesRoute: true,
container: true,
),
), ),
)); ));
} else { } else {
......
...@@ -2406,6 +2406,7 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im ...@@ -2406,6 +2406,7 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im
final SemanticsNode node = interestingFragment.compileChildren( final SemanticsNode node = interestingFragment.compileChildren(
parentSemanticsClipRect: _semantics?.parentSemanticsClipRect, parentSemanticsClipRect: _semantics?.parentSemanticsClipRect,
parentPaintClipRect: _semantics?.parentPaintClipRect, parentPaintClipRect: _semantics?.parentPaintClipRect,
elevationAdjustment: _semantics?.elevationAdjustment ?? 0.0,
).single; ).single;
// Fragment only wants to add this node's SemanticsNode to the parent. // Fragment only wants to add this node's SemanticsNode to the parent.
assert(interestingFragment.config == null && node == _semantics); assert(interestingFragment.config == null && node == _semantics);
...@@ -3193,9 +3194,19 @@ abstract class _InterestingSemanticsFragment extends _SemanticsFragment { ...@@ -3193,9 +3194,19 @@ abstract class _InterestingSemanticsFragment extends _SemanticsFragment {
final List<RenderObject> _ancestorChain; final List<RenderObject> _ancestorChain;
/// The children to be added to the parent. /// 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({ Iterable<SemanticsNode> compileChildren({
@required Rect parentSemanticsClipRect, @required Rect parentSemanticsClipRect,
@required Rect parentPaintClipRect @required Rect parentPaintClipRect,
@required double elevationAdjustment,
}); });
/// The [SemanticsConfiguration] the child wants to merge into the parent's /// The [SemanticsConfiguration] the child wants to merge into the parent's
...@@ -3264,11 +3275,12 @@ class _RootSemanticsFragment extends _InterestingSemanticsFragment { ...@@ -3264,11 +3275,12 @@ class _RootSemanticsFragment extends _InterestingSemanticsFragment {
}) : super(owner: owner, dropsSemanticsOfPreviousSiblings: dropsSemanticsOfPreviousSiblings); }) : super(owner: owner, dropsSemanticsOfPreviousSiblings: dropsSemanticsOfPreviousSiblings);
@override @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(_tagsForChildren == null || _tagsForChildren.isEmpty);
assert(parentSemanticsClipRect == null); assert(parentSemanticsClipRect == null);
assert(parentPaintClipRect == null); assert(parentPaintClipRect == null);
assert(_ancestorChain.length == 1); assert(_ancestorChain.length == 1);
assert(elevationAdjustment == 0.0);
owner._semantics ??= SemanticsNode.root( owner._semantics ??= SemanticsNode.root(
showOnScreen: owner.showOnScreen, showOnScreen: owner.showOnScreen,
...@@ -3287,6 +3299,7 @@ class _RootSemanticsFragment extends _InterestingSemanticsFragment { ...@@ -3287,6 +3299,7 @@ class _RootSemanticsFragment extends _InterestingSemanticsFragment {
children.addAll(fragment.compileChildren( children.addAll(fragment.compileChildren(
parentSemanticsClipRect: parentSemanticsClipRect, parentSemanticsClipRect: parentSemanticsClipRect,
parentPaintClipRect: parentPaintClipRect, parentPaintClipRect: parentPaintClipRect,
elevationAdjustment: 0.0,
)); ));
} }
node.updateWith(config: null, childrenInInversePaintOrder: children); node.updateWith(config: null, childrenInInversePaintOrder: children);
...@@ -3352,13 +3365,20 @@ class _SwitchableSemanticsFragment extends _InterestingSemanticsFragment { ...@@ -3352,13 +3365,20 @@ class _SwitchableSemanticsFragment extends _InterestingSemanticsFragment {
final List<_InterestingSemanticsFragment> _children = <_InterestingSemanticsFragment>[]; final List<_InterestingSemanticsFragment> _children = <_InterestingSemanticsFragment>[];
@override @override
Iterable<SemanticsNode> compileChildren({Rect parentSemanticsClipRect, Rect parentPaintClipRect}) sync* { Iterable<SemanticsNode> compileChildren({Rect parentSemanticsClipRect, Rect parentPaintClipRect, double elevationAdjustment}) sync* {
if (!_isExplicit) { if (!_isExplicit) {
owner._semantics = null; owner._semantics = null;
for (_InterestingSemanticsFragment fragment in _children) { for (_InterestingSemanticsFragment fragment in _children) {
assert(_ancestorChain.first == fragment._ancestorChain.last); assert(_ancestorChain.first == fragment._ancestorChain.last);
fragment._ancestorChain.addAll(_ancestorChain.sublist(1)); 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; return;
} }
...@@ -3375,6 +3395,12 @@ class _SwitchableSemanticsFragment extends _InterestingSemanticsFragment { ...@@ -3375,6 +3395,12 @@ class _SwitchableSemanticsFragment extends _InterestingSemanticsFragment {
..isMergedIntoParent = _mergeIntoParent ..isMergedIntoParent = _mergeIntoParent
..tags = _tagsForChildren; ..tags = _tagsForChildren;
node.elevationAdjustment = elevationAdjustment;
if (elevationAdjustment != 0.0) {
_ensureConfigIsWritable();
_config.elevation += elevationAdjustment;
}
if (geometry != null) { if (geometry != null) {
assert(_needsGeometryUpdate); assert(_needsGeometryUpdate);
node node
...@@ -3389,8 +3415,13 @@ class _SwitchableSemanticsFragment extends _InterestingSemanticsFragment { ...@@ -3389,8 +3415,13 @@ class _SwitchableSemanticsFragment extends _InterestingSemanticsFragment {
} }
final List<SemanticsNode> children = <SemanticsNode>[]; final List<SemanticsNode> children = <SemanticsNode>[];
for (_InterestingSemanticsFragment fragment in _children) for (_InterestingSemanticsFragment fragment in _children) {
children.addAll(fragment.compileChildren(parentSemanticsClipRect: node.parentSemanticsClipRect, parentPaintClipRect: node.parentPaintClipRect)); children.addAll(fragment.compileChildren(
parentSemanticsClipRect: node.parentSemanticsClipRect,
parentPaintClipRect: node.parentPaintClipRect,
elevationAdjustment: 0.0,
));
}
if (_config.isSemanticBoundary) { if (_config.isSemanticBoundary) {
owner.assembleSemanticsNode(node, _config, children); owner.assembleSemanticsNode(node, _config, children);
...@@ -3457,7 +3488,7 @@ class _AbortingSemanticsFragment extends _InterestingSemanticsFragment { ...@@ -3457,7 +3488,7 @@ class _AbortingSemanticsFragment extends _InterestingSemanticsFragment {
} }
@override @override
Iterable<SemanticsNode> compileChildren({Rect parentSemanticsClipRect, Rect parentPaintClipRect}) sync* { Iterable<SemanticsNode> compileChildren({Rect parentSemanticsClipRect, Rect parentPaintClipRect, double elevationAdjustment}) sync* {
yield owner._semantics; yield owner._semantics;
} }
......
...@@ -1571,6 +1571,12 @@ abstract class _RenderPhysicalModelBase<T> extends _RenderCustomClip<T> { ...@@ -1571,6 +1571,12 @@ abstract class _RenderPhysicalModelBase<T> extends _RenderCustomClip<T> {
@override @override
bool get alwaysNeedsCompositing => _elevation != 0.0 && defaultTargetPlatform == TargetPlatform.fuchsia; bool get alwaysNeedsCompositing => _elevation != 0.0 && defaultTargetPlatform == TargetPlatform.fuchsia;
@override
void describeSemanticsConfiguration(SemanticsConfiguration config) {
super.describeSemanticsConfiguration(config);
config.elevation = elevation;
}
@override @override
void debugFillProperties(DiagnosticPropertiesBuilder description) { void debugFillProperties(DiagnosticPropertiesBuilder description) {
super.debugFillProperties(description); super.debugFillProperties(description);
......
...@@ -40,27 +40,34 @@ void main() { ...@@ -40,27 +40,34 @@ void main() {
children: <TestSemantics>[ children: <TestSemantics>[
TestSemantics( TestSemantics(
id: 1, id: 1,
label: 'I am text!', elevation: 1.0,
textDirection: TextDirection.ltr, thickness: 0.0,
), children: <TestSemantics>[
TestSemantics( TestSemantics(
id: 2, id: 2,
label: 'Moar text!!1', label: 'I am text!',
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
), ),
TestSemantics( TestSemantics(
id: 3, id: 3,
label: 'Button', label: 'Moar text!!1',
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
actions: <SemanticsAction>[ ),
SemanticsAction.tap, TestSemantics(
], id: 4,
flags: <SemanticsFlag>[ label: 'Button',
SemanticsFlag.isButton, textDirection: TextDirection.ltr,
SemanticsFlag.hasEnabledState, actions: <SemanticsAction>[
SemanticsFlag.isEnabled, SemanticsAction.tap,
],
flags: <SemanticsFlag>[
SemanticsFlag.isButton,
SemanticsFlag.hasEnabledState,
SemanticsFlag.isEnabled,
],
),
], ],
), )
], ],
), ),
ignoreTransform: true, ignoreTransform: true,
......
This diff is collapsed.
...@@ -353,6 +353,8 @@ void main() { ...@@ -353,6 +353,8 @@ void main() {
' scrollExtentMin: null\n' ' scrollExtentMin: null\n'
' scrollPosition: null\n' ' scrollPosition: null\n'
' scrollExtentMax: null\n' ' scrollExtentMax: null\n'
' elevation: 0.0\n'
' thicknes: 0.0\n'
); );
final SemanticsConfiguration config = SemanticsConfiguration() final SemanticsConfiguration config = SemanticsConfiguration()
...@@ -445,6 +447,8 @@ void main() { ...@@ -445,6 +447,8 @@ void main() {
' scrollExtentMin: null\n' ' scrollExtentMin: null\n'
' scrollPosition: null\n' ' scrollPosition: null\n'
' scrollExtentMax: null\n' ' scrollExtentMax: null\n'
' elevation: 0.0\n'
' thicknes: 0.0\n'
); );
}); });
......
...@@ -46,6 +46,8 @@ class TestSemantics { ...@@ -46,6 +46,8 @@ class TestSemantics {
this.textDirection, this.textDirection,
this.rect, this.rect,
this.transform, this.transform,
this.elevation,
this.thickness,
this.textSelection, this.textSelection,
this.children = const <TestSemantics>[], this.children = const <TestSemantics>[],
this.scrollIndex, this.scrollIndex,
...@@ -87,6 +89,8 @@ class TestSemantics { ...@@ -87,6 +89,8 @@ class TestSemantics {
assert(value != null), assert(value != null),
assert(hint != null), assert(hint != null),
rect = TestSemantics.rootRect, rect = TestSemantics.rootRect,
elevation = 0.0,
thickness = 0.0,
assert(children != null), assert(children != null),
tags = tags?.toSet() ?? Set<SemanticsTag>(); tags = tags?.toSet() ?? Set<SemanticsTag>();
...@@ -111,6 +115,8 @@ class TestSemantics { ...@@ -111,6 +115,8 @@ class TestSemantics {
this.textDirection, this.textDirection,
this.rect, this.rect,
Matrix4 transform, Matrix4 transform,
this.elevation,
this.thickness,
this.textSelection, this.textSelection,
this.children = const <TestSemantics>[], this.children = const <TestSemantics>[],
this.scrollIndex, this.scrollIndex,
...@@ -206,6 +212,21 @@ class TestSemantics { ...@@ -206,6 +212,21 @@ class TestSemantics {
/// parent). /// parent).
final Matrix4 transform; 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. /// The index of the first visible semantic node within a scrollable.
final int scrollIndex; final int scrollIndex;
...@@ -279,6 +300,12 @@ class TestSemantics { ...@@ -279,6 +300,12 @@ class TestSemantics {
return fail('expected node id $id to have rect $rect but found rect ${nodeData.rect}.'); return fail('expected node id $id to have rect $rect but found rect ${nodeData.rect}.');
if (!ignoreTransform && transform != nodeData.transform) if (!ignoreTransform && transform != nodeData.transform)
return fail('expected node id $id to have transform $transform but found transform:\n${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) { 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}].'); 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 { ...@@ -346,6 +373,10 @@ class TestSemantics {
buf.writeln('$indent rect: $rect,'); buf.writeln('$indent rect: $rect,');
if (transform != null) if (transform != null)
buf.writeln('$indent transform:\n${transform.toString().trim().split('\n').map<String>((String line) => '$indent $line').join('\n')},'); 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>['); buf.writeln('$indent children: <TestSemantics>[');
for (TestSemantics child in children) { for (TestSemantics child in children) {
buf.writeln('${child.toString(indentAmount + 2)},'); buf.writeln('${child.toString(indentAmount + 2)},');
......
...@@ -355,6 +355,8 @@ Matcher matchesSemantics({ ...@@ -355,6 +355,8 @@ Matcher matchesSemantics({
TextDirection textDirection, TextDirection textDirection,
Rect rect, Rect rect,
Size size, Size size,
double elevation,
double thickness,
// Flags // // Flags //
bool hasCheckedState = false, bool hasCheckedState = false,
bool isChecked = false, bool isChecked = false,
...@@ -503,6 +505,8 @@ Matcher matchesSemantics({ ...@@ -503,6 +505,8 @@ Matcher matchesSemantics({
textDirection: textDirection, textDirection: textDirection,
rect: rect, rect: rect,
size: size, size: size,
elevation: elevation,
thickness: thickness,
customActions: customActions, customActions: customActions,
hintOverrides: hintOverrides, hintOverrides: hintOverrides,
children: children, children: children,
...@@ -1685,6 +1689,8 @@ class _MatchesSemanticsData extends Matcher { ...@@ -1685,6 +1689,8 @@ class _MatchesSemanticsData extends Matcher {
this.textDirection, this.textDirection,
this.rect, this.rect,
this.size, this.size,
this.elevation,
this.thickness,
this.customActions, this.customActions,
this.hintOverrides, this.hintOverrides,
this.children, this.children,
...@@ -1702,6 +1708,8 @@ class _MatchesSemanticsData extends Matcher { ...@@ -1702,6 +1708,8 @@ class _MatchesSemanticsData extends Matcher {
final TextDirection textDirection; final TextDirection textDirection;
final Rect rect; final Rect rect;
final Size size; final Size size;
final double elevation;
final double thickness;
final List<Matcher> children; final List<Matcher> children;
@override @override
...@@ -1727,6 +1735,10 @@ class _MatchesSemanticsData extends Matcher { ...@@ -1727,6 +1735,10 @@ class _MatchesSemanticsData extends Matcher {
description.add(' with rect: $rect'); description.add(' with rect: $rect');
if (size != null) if (size != null)
description.add(' with size: $size'); description.add(' with size: $size');
if (elevation != null)
description.add(' with elevation: $elevation');
if (thickness != null)
description.add(' with thickness: $thickness');
if (customActions != null) if (customActions != null)
description.add(' with custom actions: $customActions'); description.add(' with custom actions: $customActions');
if (hintOverrides != null) if (hintOverrides != null)
...@@ -1763,6 +1775,10 @@ class _MatchesSemanticsData extends Matcher { ...@@ -1763,6 +1775,10 @@ class _MatchesSemanticsData extends Matcher {
return failWithDescription(matchState, 'rect was: ${data.rect}'); return failWithDescription(matchState, 'rect was: ${data.rect}');
if (size != null && size != data.rect.size) if (size != null && size != data.rect.size)
return failWithDescription(matchState, 'size was: ${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) { if (actions != null) {
int actionBits = 0; int actionBits = 0;
for (SemanticsAction action in actions) for (SemanticsAction action in actions)
......
...@@ -494,6 +494,8 @@ void main() { ...@@ -494,6 +494,8 @@ void main() {
hint: 'e', hint: 'e',
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
rect: Rect.fromLTRB(0.0, 0.0, 10.0, 10.0), rect: Rect.fromLTRB(0.0, 0.0, 10.0, 10.0),
elevation: 3.0,
thickness: 4.0,
textSelection: null, textSelection: null,
scrollIndex: null, scrollIndex: null,
scrollChildCount: null, scrollChildCount: null,
...@@ -508,6 +510,8 @@ void main() { ...@@ -508,6 +510,8 @@ void main() {
expect(node, matchesSemantics( expect(node, matchesSemantics(
rect: Rect.fromLTRB(0.0, 0.0, 10.0, 10.0), rect: Rect.fromLTRB(0.0, 0.0, 10.0, 10.0),
size: const Size(10.0, 10.0), size: const Size(10.0, 10.0),
elevation: 3.0,
thickness: 4.0,
/* Flags */ /* Flags */
hasCheckedState: true, hasCheckedState: true,
isChecked: true, isChecked: true,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment