Commit 0384c8c4 authored by Marius Meißner's avatar Marius Meißner Committed by Shi-Hao Hong

Flexible padding (header height) for expanded panels (#47951)

* Added property for expanded padding of expansion panel for solving #24071

* #24071: Renamed default const name for being more descriptive

* #24071: Improved comment of property expandedPadding

* #24071: Improved test by expanding the expansion panel by header tap + precise assertion

* #24071: Renamed property to be more descriptive

* #24071: Adjusted property comment and added missing trailing commas

* #24071: Improved test by checking real exact header size

* #24071: Added test for default header padding

* #24071: Improved comment of expandedHeaderPadding + code style adjustments

* #24071: Added missing trailing comma
parent 6b664121
......@@ -13,7 +13,9 @@ import 'mergeable_material.dart';
import 'theme.dart';
const double _kPanelHeaderCollapsedHeight = kMinInteractiveDimension;
const double _kPanelHeaderExpandedHeight = 64.0;
const EdgeInsets _kPanelHeaderExpandedDefaultPadding = EdgeInsets.symmetric(
vertical: 64.0 - _kPanelHeaderCollapsedHeight
);
class _SaltedKey<S, V> extends LocalKey {
const _SaltedKey(this.salt, this.value);
......@@ -225,6 +227,7 @@ class ExpansionPanelList extends StatefulWidget {
this.children = const <ExpansionPanel>[],
this.expansionCallback,
this.animationDuration = kThemeAnimationDuration,
this.expandedHeaderPadding = _kPanelHeaderExpandedDefaultPadding,
}) : assert(children != null),
assert(animationDuration != null),
_allowOnlyOnePanelOpen = false,
......@@ -313,6 +316,7 @@ class ExpansionPanelList extends StatefulWidget {
this.expansionCallback,
this.animationDuration = kThemeAnimationDuration,
this.initialOpenPanelValue,
this.expandedHeaderPadding = _kPanelHeaderExpandedDefaultPadding,
}) : assert(children != null),
assert(animationDuration != null),
_allowOnlyOnePanelOpen = true,
......@@ -351,6 +355,12 @@ class ExpansionPanelList extends StatefulWidget {
/// constructor.)
final Object initialOpenPanelValue;
/// The padding that surrounds the panel header when expanded.
///
/// By default, 16px of space is added to the header vertically (above and below)
/// during expansion.
final EdgeInsets expandedHeaderPadding;
@override
State<StatefulWidget> createState() => _ExpansionPanelListState();
}
......@@ -437,9 +447,6 @@ class _ExpansionPanelListState extends State<ExpansionPanelList> {
@override
Widget build(BuildContext context) {
final List<MergeableMaterialItem> items = <MergeableMaterialItem>[];
const EdgeInsets kExpandedEdgeInsets = EdgeInsets.symmetric(
vertical: _kPanelHeaderExpandedHeight - _kPanelHeaderCollapsedHeight
);
for (int index = 0; index < widget.children.length; index += 1) {
if (_isChildExpanded(index) && index != 0 && !_isChildExpanded(index - 1))
......@@ -475,7 +482,7 @@ class _ExpansionPanelListState extends State<ExpansionPanelList> {
child: AnimatedContainer(
duration: widget.animationDuration,
curve: Curves.fastOutSlowIn,
margin: _isChildExpanded(index) ? kExpandedEdgeInsets : EdgeInsets.zero,
margin: _isChildExpanded(index) ? widget.expandedHeaderPadding : EdgeInsets.zero,
child: ConstrainedBox(
constraints: const BoxConstraints(minHeight: _kPanelHeaderCollapsedHeight),
child: headerWidget,
......
......@@ -11,12 +11,22 @@ class SimpleExpansionPanelListTestWidget extends StatefulWidget {
this.firstPanelKey,
this.secondPanelKey,
this.canTapOnHeader = false,
this.expandedHeaderPadding
}) : super(key: key);
final Key firstPanelKey;
final Key secondPanelKey;
final bool canTapOnHeader;
/// If null, the default [ExpansionPanelList]'s expanded header padding value is applied via [defaultExpandedHeaderPadding]
final EdgeInsets expandedHeaderPadding;
/// Mirrors the default expanded header padding as its source constants are private
static EdgeInsets defaultExpandedHeaderPadding()
{
return const ExpansionPanelList().expandedHeaderPadding;
}
@override
_SimpleExpansionPanelListTestWidgetState createState() => _SimpleExpansionPanelListTestWidgetState();
}
......@@ -27,6 +37,7 @@ class _SimpleExpansionPanelListTestWidgetState extends State<SimpleExpansionPane
@override
Widget build(BuildContext context) {
return ExpansionPanelList(
expandedHeaderPadding: widget.expandedHeaderPadding ?? SimpleExpansionPanelListTestWidget.defaultExpandedHeaderPadding(),
expansionCallback: (int _index, bool _isExpanded) {
setState(() {
extendedState[_index] = !extendedState[_index];
......@@ -1255,4 +1266,79 @@ void main() {
expect(find.text('C'), findsOneWidget);
expect(find.text('D'), findsNothing);
});
testWidgets('Correct default header padding', (WidgetTester tester) async {
const Key firstPanelKey = Key('firstPanelKey');
await tester.pumpWidget(
const MaterialApp(
home: SingleChildScrollView(
child: SimpleExpansionPanelListTestWidget(
firstPanelKey: firstPanelKey,
canTapOnHeader: true,
),
),
),
);
// The panel is closed
expect(find.text('A'), findsOneWidget);
expect(find.text('B'), findsNothing);
// No padding applied to closed header
RenderBox box = tester.renderObject(find.ancestor(of: find.byKey(firstPanelKey), matching: find.byType(AnimatedContainer)).first);
expect(box.size.height, equals(48.0)); // _kPanelHeaderCollapsedHeight
expect(box.size.width, equals(736.0));
// Now, expand the child panel.
await tester.tap(find.byKey(firstPanelKey));
await tester.pumpAndSettle();
// The panel is expanded
expect(find.text('A'), findsNothing);
expect(find.text('B'), findsOneWidget);
// Padding is added to expanded header
box = tester.renderObject(find.ancestor(of: find.byKey(firstPanelKey), matching: find.byType(AnimatedContainer)).first);
expect(box.size.height, equals(80.0)); // _kPanelHeaderCollapsedHeight + 32.0 (double default padding)
expect(box.size.width, equals(736.0));
});
testWidgets('Correct custom header padding', (WidgetTester tester) async {
const Key firstPanelKey = Key('firstPanelKey');
await tester.pumpWidget(
const MaterialApp(
home: SingleChildScrollView(
child: SimpleExpansionPanelListTestWidget(
firstPanelKey: firstPanelKey,
canTapOnHeader: true,
expandedHeaderPadding: EdgeInsets.symmetric(vertical: 40.0),
),
),
),
);
// The panel is closed
expect(find.text('A'), findsOneWidget);
expect(find.text('B'), findsNothing);
// No padding applied to closed header
RenderBox box = tester.renderObject(find.ancestor(of: find.byKey(firstPanelKey), matching: find.byType(AnimatedContainer)).first);
expect(box.size.height, equals(48.0)); // _kPanelHeaderCollapsedHeight
expect(box.size.width, equals(736.0));
// Now, expand the child panel.
await tester.tap(find.byKey(firstPanelKey));
await tester.pumpAndSettle();
// The panel is expanded
expect(find.text('A'), findsNothing);
expect(find.text('B'), findsOneWidget);
// Padding is added to expanded header
box = tester.renderObject(find.ancestor(of: find.byKey(firstPanelKey), matching: find.byType(AnimatedContainer)).first);
expect(box.size.height, equals(128.0)); // _kPanelHeaderCollapsedHeight + 80.0 (double padding)
expect(box.size.width, equals(736.0));
});
}
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