[ExpansionPanelList] adds elevation property (#62840)
This commit is contained in:
parent
71aa7395b9
commit
263de65f48
@ -12,6 +12,7 @@ import 'expand_icon.dart';
|
||||
import 'ink_well.dart';
|
||||
import 'material_localizations.dart';
|
||||
import 'mergeable_material.dart';
|
||||
import 'shadows.dart';
|
||||
import 'theme.dart';
|
||||
|
||||
const double _kPanelHeaderCollapsedHeight = kMinInteractiveDimension;
|
||||
@ -231,6 +232,7 @@ class ExpansionPanelList extends StatefulWidget {
|
||||
this.animationDuration = kThemeAnimationDuration,
|
||||
this.expandedHeaderPadding = _kPanelHeaderExpandedDefaultPadding,
|
||||
this.dividerColor,
|
||||
this.elevation = 2,
|
||||
}) : assert(children != null),
|
||||
assert(animationDuration != null),
|
||||
_allowOnlyOnePanelOpen = false,
|
||||
@ -321,6 +323,7 @@ class ExpansionPanelList extends StatefulWidget {
|
||||
this.initialOpenPanelValue,
|
||||
this.expandedHeaderPadding = _kPanelHeaderExpandedDefaultPadding,
|
||||
this.dividerColor,
|
||||
this.elevation = 2,
|
||||
}) : assert(children != null),
|
||||
assert(animationDuration != null),
|
||||
_allowOnlyOnePanelOpen = true,
|
||||
@ -371,6 +374,17 @@ class ExpansionPanelList extends StatefulWidget {
|
||||
/// is null, then [ThemeData.dividerColor] is used.
|
||||
final Color dividerColor;
|
||||
|
||||
/// Defines elevation for the [ExpansionPanel] while it's expanded.
|
||||
///
|
||||
/// This uses [kElevationToShadow] to simulate shadows, it does not use
|
||||
/// [Material]'s arbitrary elevation feature.
|
||||
///
|
||||
/// The following values can be used to define the elevation: 0, 1, 2, 3, 4, 6,
|
||||
/// 8, 9, 12, 16, 24.
|
||||
///
|
||||
/// By default, the value of elevation is 2.
|
||||
final int elevation;
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _ExpansionPanelListState();
|
||||
}
|
||||
@ -456,6 +470,11 @@ class _ExpansionPanelListState extends State<ExpansionPanelList> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
assert(kElevationToShadow.containsKey(widget.elevation),
|
||||
'Invalid value for elevation. See the kElevationToShadow constant for'
|
||||
' possible elevation values.'
|
||||
);
|
||||
|
||||
final List<MergeableMaterialItem> items = <MergeableMaterialItem>[];
|
||||
|
||||
for (int index = 0; index < widget.children.length; index += 1) {
|
||||
@ -537,6 +556,7 @@ class _ExpansionPanelListState extends State<ExpansionPanelList> {
|
||||
return MergeableMaterial(
|
||||
hasDividers: true,
|
||||
dividerColor: widget.dividerColor,
|
||||
elevation: widget.elevation,
|
||||
children: items,
|
||||
);
|
||||
}
|
||||
|
@ -33,6 +33,9 @@ const Color _kKeyUmbraOpacity = Color(0x33000000); // alpha = 0.2
|
||||
const Color _kKeyPenumbraOpacity = Color(0x24000000); // alpha = 0.14
|
||||
const Color _kAmbientShadowOpacity = Color(0x1F000000); // alpha = 0.12
|
||||
const Map<int, List<BoxShadow>> _elevationToShadow = <int, List<BoxShadow>>{
|
||||
// The empty list depicts no elevation.
|
||||
0: <BoxShadow>[],
|
||||
|
||||
1: <BoxShadow>[
|
||||
BoxShadow(offset: Offset(0.0, 2.0), blurRadius: 1.0, spreadRadius: -1.0, color: _kKeyUmbraOpacity),
|
||||
BoxShadow(offset: Offset(0.0, 1.0), blurRadius: 1.0, spreadRadius: 0.0, color: _kKeyPenumbraOpacity),
|
||||
|
@ -15,12 +15,14 @@ class SimpleExpansionPanelListTestWidget extends StatefulWidget {
|
||||
this.canTapOnHeader = false,
|
||||
this.expandedHeaderPadding,
|
||||
this.dividerColor,
|
||||
this.elevation = 2,
|
||||
}) : super(key: key);
|
||||
|
||||
final Key firstPanelKey;
|
||||
final Key secondPanelKey;
|
||||
final bool canTapOnHeader;
|
||||
final Color dividerColor;
|
||||
final int elevation;
|
||||
|
||||
/// If null, the default [ExpansionPanelList]'s expanded header padding value is applied via [defaultExpandedHeaderPadding]
|
||||
final EdgeInsets expandedHeaderPadding;
|
||||
@ -48,6 +50,7 @@ class _SimpleExpansionPanelListTestWidgetState extends State<SimpleExpansionPane
|
||||
});
|
||||
},
|
||||
dividerColor: widget.dividerColor,
|
||||
elevation: widget.elevation,
|
||||
children: <ExpansionPanel>[
|
||||
ExpansionPanel(
|
||||
headerBuilder: (BuildContext context, bool isExpanded) {
|
||||
@ -1396,4 +1399,65 @@ void main() {
|
||||
// For the last DecoratedBox, we will have a Border.top with the provided dividerColor.
|
||||
expect(boxDecoration.border.top.color, dividerColor);
|
||||
});
|
||||
|
||||
testWidgets('elevation is propagated properly to MergeableMaterial', (WidgetTester tester) async {
|
||||
const int _elevation = 8;
|
||||
|
||||
// Test for ExpansionPanelList.
|
||||
await tester.pumpWidget(const MaterialApp(
|
||||
home: SingleChildScrollView(
|
||||
child: SimpleExpansionPanelListTestWidget(
|
||||
elevation: _elevation,
|
||||
),
|
||||
),
|
||||
));
|
||||
|
||||
expect(tester.widget<MergeableMaterial>(find.byType(MergeableMaterial)).elevation, _elevation);
|
||||
|
||||
// Test for ExpansionPanelList.radio.
|
||||
await tester.pumpWidget(MaterialApp(
|
||||
home: SingleChildScrollView(
|
||||
child: ExpansionPanelList.radio(
|
||||
elevation: _elevation,
|
||||
children: <ExpansionPanelRadio>[
|
||||
ExpansionPanelRadio(
|
||||
headerBuilder: (BuildContext context, bool isExpanded) {
|
||||
return Text(isExpanded ? 'B' : 'A', key: const Key('firstKey'));
|
||||
},
|
||||
body: const SizedBox(height: 100.0),
|
||||
value: 0,
|
||||
),
|
||||
ExpansionPanelRadio(
|
||||
headerBuilder: (BuildContext context, bool isExpanded) {
|
||||
return Text(isExpanded ? 'D' : 'C', key: const Key('secondKey'));
|
||||
},
|
||||
body: const SizedBox(height: 100.0),
|
||||
value: 1,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
));
|
||||
|
||||
expect(tester.widget<MergeableMaterial>(find.byType(MergeableMaterial)).elevation, _elevation);
|
||||
});
|
||||
|
||||
testWidgets('Using a value non defined value throws assertion error', (WidgetTester tester) async {
|
||||
|
||||
// It should throw an AssertionError since, 19 is not defined in kElevationToShadow.
|
||||
await tester.pumpWidget(const MaterialApp(
|
||||
home: SingleChildScrollView(
|
||||
child: SimpleExpansionPanelListTestWidget(
|
||||
elevation: 19,
|
||||
),
|
||||
),
|
||||
));
|
||||
|
||||
final dynamic exception = tester.takeException();
|
||||
expect(exception, isAssertionError);
|
||||
expect((exception as AssertionError).toString(), contains(
|
||||
'Invalid value for elevation. See the kElevationToShadow constant for'
|
||||
' possible elevation values.'
|
||||
));
|
||||
});
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user