|
@@ -5,7 +5,6 @@
|
|
|
import 'package:flutter/material.dart';
|
|
|
import 'package:flutter/widgets.dart';
|
|
|
|
|
|
-
|
|
|
const double _kPanelHeaderCollapsedHeight = kMinInteractiveDimension;
|
|
|
const EdgeInsets _kPanelHeaderExpandedDefaultPadding = EdgeInsets.symmetric(
|
|
|
vertical: 64.0 - _kPanelHeaderCollapsedHeight,
|
|
@@ -19,11 +18,10 @@ class _SaltedKey<S, V> extends LocalKey {
|
|
|
|
|
|
@override
|
|
|
bool operator ==(Object other) {
|
|
|
- if (other.runtimeType != runtimeType)
|
|
|
- return false;
|
|
|
- return other is _SaltedKey<S, V>
|
|
|
- && other.salt == salt
|
|
|
- && other.value == value;
|
|
|
+ if (other.runtimeType != runtimeType) return false;
|
|
|
+ return other is _SaltedKey<S, V> &&
|
|
|
+ other.salt == salt &&
|
|
|
+ other.value == value;
|
|
|
}
|
|
|
|
|
|
@override
|
|
@@ -38,8 +36,10 @@ class _SaltedKey<S, V> extends LocalKey {
|
|
|
}
|
|
|
|
|
|
typedef ExpansionPanelCallback = void Function(int panelIndex, bool isExpanded);
|
|
|
-typedef ExpansionPanelHeaderBuilder = Widget Function(BuildContext context, bool isExpanded);
|
|
|
+typedef ExpansionPanelHeaderBuilder = Widget Function(
|
|
|
+ BuildContext context, bool isExpanded);
|
|
|
|
|
|
+/// 折叠列表
|
|
|
class ChznExpansionPanelList extends StatefulWidget {
|
|
|
const ChznExpansionPanelList({
|
|
|
Key? key,
|
|
@@ -49,7 +49,7 @@ class ChznExpansionPanelList extends StatefulWidget {
|
|
|
this.expandedHeaderPadding = _kPanelHeaderExpandedDefaultPadding,
|
|
|
this.dividerColor,
|
|
|
this.elevation = 2,
|
|
|
- }) : assert(children != null),
|
|
|
+ }) : assert(children != null),
|
|
|
assert(animationDuration != null),
|
|
|
_allowOnlyOnePanelOpen = false,
|
|
|
initialOpenPanelValue = null,
|
|
@@ -63,7 +63,7 @@ class ChznExpansionPanelList extends StatefulWidget {
|
|
|
this.expandedHeaderPadding = _kPanelHeaderExpandedDefaultPadding,
|
|
|
this.dividerColor,
|
|
|
this.elevation = 2,
|
|
|
- }) : assert(children != null),
|
|
|
+ }) : assert(children != null),
|
|
|
assert(animationDuration != null),
|
|
|
_allowOnlyOnePanelOpen = true,
|
|
|
super(key: key);
|
|
@@ -87,10 +87,12 @@ class _ExpansionPanelListState extends State<ChznExpansionPanelList> {
|
|
|
void initState() {
|
|
|
super.initState();
|
|
|
if (widget._allowOnlyOnePanelOpen) {
|
|
|
- assert(_allIdentifiersUnique(), 'All ExpansionPanelRadio identifier values must be unique.');
|
|
|
+ assert(_allIdentifiersUnique(),
|
|
|
+ 'All ExpansionPanelRadio identifier values must be unique.');
|
|
|
if (widget.initialOpenPanelValue != null) {
|
|
|
- _currentOpenPanel =
|
|
|
- searchPanelByValue(widget.children.cast<ExpansionPanelRadio>(), widget.initialOpenPanelValue);
|
|
|
+ _currentOpenPanel = searchPanelByValue(
|
|
|
+ widget.children.cast<ExpansionPanelRadio>(),
|
|
|
+ widget.initialOpenPanelValue);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -100,12 +102,12 @@ class _ExpansionPanelListState extends State<ChznExpansionPanelList> {
|
|
|
super.didUpdateWidget(oldWidget);
|
|
|
|
|
|
if (widget._allowOnlyOnePanelOpen) {
|
|
|
- assert(_allIdentifiersUnique(), 'All ExpansionPanelRadio identifier values must be unique.');
|
|
|
- // If the previous widget was non-radio ExpansionPanelList, initialize the
|
|
|
- // open panel to widget.initialOpenPanelValue
|
|
|
+ assert(_allIdentifiersUnique(),
|
|
|
+ 'All ExpansionPanelRadio identifier values must be unique.');
|
|
|
if (!oldWidget._allowOnlyOnePanelOpen) {
|
|
|
- _currentOpenPanel =
|
|
|
- searchPanelByValue(widget.children.cast<ExpansionPanelRadio>(), widget.initialOpenPanelValue);
|
|
|
+ _currentOpenPanel = searchPanelByValue(
|
|
|
+ widget.children.cast<ExpansionPanelRadio>(),
|
|
|
+ widget.initialOpenPanelValue);
|
|
|
}
|
|
|
} else {
|
|
|
_currentOpenPanel = null;
|
|
@@ -114,7 +116,8 @@ class _ExpansionPanelListState extends State<ChznExpansionPanelList> {
|
|
|
|
|
|
bool _allIdentifiersUnique() {
|
|
|
final Map<Object, bool> identifierMap = <Object, bool>{};
|
|
|
- for (final ExpansionPanelRadio child in widget.children.cast<ExpansionPanelRadio>()) {
|
|
|
+ for (final ExpansionPanelRadio child
|
|
|
+ in widget.children.cast<ExpansionPanelRadio>()) {
|
|
|
identifierMap[child.value] = true;
|
|
|
}
|
|
|
return identifierMap.length == widget.children.length;
|
|
@@ -122,7 +125,8 @@ class _ExpansionPanelListState extends State<ChznExpansionPanelList> {
|
|
|
|
|
|
bool _isChildExpanded(int index) {
|
|
|
if (widget._allowOnlyOnePanelOpen) {
|
|
|
- final ExpansionPanelRadio radioWidget = widget.children[index] as ExpansionPanelRadio;
|
|
|
+ final ExpansionPanelRadio radioWidget =
|
|
|
+ widget.children[index] as ExpansionPanelRadio;
|
|
|
return _currentOpenPanel?.value == radioWidget.value;
|
|
|
}
|
|
|
return widget.children[index].isExpanded;
|
|
@@ -132,12 +136,16 @@ class _ExpansionPanelListState extends State<ChznExpansionPanelList> {
|
|
|
widget.expansionCallback?.call(index, isExpanded);
|
|
|
|
|
|
if (widget._allowOnlyOnePanelOpen) {
|
|
|
- final ExpansionPanelRadio pressedChild = widget.children[index] as ExpansionPanelRadio;
|
|
|
+ final ExpansionPanelRadio pressedChild =
|
|
|
+ widget.children[index] as ExpansionPanelRadio;
|
|
|
|
|
|
// If another ExpansionPanelRadio was already open, apply its
|
|
|
// expansionCallback (if any) to false, because it's closing.
|
|
|
- for (int childIndex = 0; childIndex < widget.children.length; childIndex += 1) {
|
|
|
- final ExpansionPanelRadio child = widget.children[childIndex] as ExpansionPanelRadio;
|
|
|
+ for (int childIndex = 0;
|
|
|
+ childIndex < widget.children.length;
|
|
|
+ childIndex += 1) {
|
|
|
+ final ExpansionPanelRadio child =
|
|
|
+ widget.children[childIndex] as ExpansionPanelRadio;
|
|
|
if (widget.expansionCallback != null &&
|
|
|
childIndex != index &&
|
|
|
child.value == _currentOpenPanel?.value)
|
|
@@ -150,19 +158,20 @@ class _ExpansionPanelListState extends State<ChznExpansionPanelList> {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- ExpansionPanelRadio? searchPanelByValue(List<ExpansionPanelRadio> panels, Object? value) {
|
|
|
+ ExpansionPanelRadio? searchPanelByValue(
|
|
|
+ List<ExpansionPanelRadio> panels, Object? value) {
|
|
|
for (final ExpansionPanelRadio panel in panels) {
|
|
|
- if (panel.value == value)
|
|
|
- return panel;
|
|
|
+ if (panel.value == value) return panel;
|
|
|
}
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
@override
|
|
|
Widget build(BuildContext context) {
|
|
|
- assert(kElevationToShadow.containsKey(widget.elevation),
|
|
|
- 'Invalid value for elevation. See the kElevationToShadow constant for'
|
|
|
- ' possible elevation values.',
|
|
|
+ assert(
|
|
|
+ kElevationToShadow.containsKey(widget.elevation),
|
|
|
+ 'Invalid value for elevation. See the kElevationToShadow constant for'
|
|
|
+ ' possible elevation values.',
|
|
|
);
|
|
|
|
|
|
final List<MergeableMaterialItem> items = <MergeableMaterialItem>[];
|
|
@@ -188,9 +197,12 @@ class _ExpansionPanelListState extends State<ChznExpansionPanelList> {
|
|
|
),
|
|
|
);
|
|
|
if (!child.canTapOnHeader) {
|
|
|
- final MaterialLocalizations localizations = MaterialLocalizations.of(context);
|
|
|
+ final MaterialLocalizations localizations =
|
|
|
+ MaterialLocalizations.of(context);
|
|
|
expandIconContainer = Semantics(
|
|
|
- label: _isChildExpanded(index)? localizations.expandedIconTapHint : localizations.collapsedIconTapHint,
|
|
|
+ label: _isChildExpanded(index)
|
|
|
+ ? localizations.expandedIconTapHint
|
|
|
+ : localizations.collapsedIconTapHint,
|
|
|
container: true,
|
|
|
child: expandIconContainer,
|
|
|
);
|
|
@@ -201,9 +213,12 @@ class _ExpansionPanelListState extends State<ChznExpansionPanelList> {
|
|
|
child: AnimatedContainer(
|
|
|
duration: widget.animationDuration,
|
|
|
curve: Curves.fastOutSlowIn,
|
|
|
- margin: _isChildExpanded(index) ? widget.expandedHeaderPadding : EdgeInsets.zero,
|
|
|
+ margin: _isChildExpanded(index)
|
|
|
+ ? widget.expandedHeaderPadding
|
|
|
+ : EdgeInsets.zero,
|
|
|
child: ConstrainedBox(
|
|
|
- constraints: const BoxConstraints(minHeight: _kPanelHeaderCollapsedHeight),
|
|
|
+ constraints: const BoxConstraints(
|
|
|
+ minHeight: _kPanelHeaderCollapsedHeight),
|
|
|
child: headerWidget,
|
|
|
),
|
|
|
),
|
|
@@ -229,19 +244,20 @@ class _ExpansionPanelListState extends State<ChznExpansionPanelList> {
|
|
|
AnimatedCrossFade(
|
|
|
firstChild: Container(height: 0.0),
|
|
|
secondChild: child.body,
|
|
|
- firstCurve: const Interval(0.0, 0.6, curve: Curves.fastOutSlowIn),
|
|
|
- secondCurve: const Interval(0.4, 1.0, curve: Curves.fastOutSlowIn),
|
|
|
+ firstCurve:
|
|
|
+ const Interval(0.0, 0.6, curve: Curves.fastOutSlowIn),
|
|
|
+ secondCurve:
|
|
|
+ const Interval(0.4, 1.0, curve: Curves.fastOutSlowIn),
|
|
|
sizeCurve: Curves.fastOutSlowIn,
|
|
|
- crossFadeState: _isChildExpanded(index) ? CrossFadeState.showSecond : CrossFadeState.showFirst,
|
|
|
+ crossFadeState: _isChildExpanded(index)
|
|
|
+ ? CrossFadeState.showSecond
|
|
|
+ : CrossFadeState.showFirst,
|
|
|
duration: widget.animationDuration,
|
|
|
),
|
|
|
],
|
|
|
),
|
|
|
),
|
|
|
);
|
|
|
-
|
|
|
- // if (_isChildExpanded(index) && index != widget.children.length - 1)
|
|
|
- // items.add(MaterialGap(key: _SaltedKey<BuildContext, int>(context, index * 2 + 1)));
|
|
|
}
|
|
|
|
|
|
return MergeableMaterial(
|