diff --git a/CHANGELOG.md b/CHANGELOG.md index 76a8fa3..92e21d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 2.2.0 +* New Feature: + - Only trailing can toggle the state: `isOnlyTrailingDoToggle` [#42](https://github.com/congthanhng/Expansion-Tile-Group/pull/42) +* Update + - Example with new feature + ## 2.1.0 * New Feature: - Add new way to implement *group* feature: ExpansionGroupController diff --git a/example/lib/use_cases/item/interaction_view.dart b/example/lib/use_cases/item/interaction_view.dart index 30360e7..7209353 100644 --- a/example/lib/use_cases/item/interaction_view.dart +++ b/example/lib/use_cases/item/interaction_view.dart @@ -13,6 +13,7 @@ class _InteractionViewState extends State { bool isHideSubtitle = false; bool isHasTrailing = true; bool isDefaultVerticalPadding = true; + bool isOnlyTrailingDoToggle = false; final GlobalKey key0 = GlobalKey(); final listIcon = [ @@ -45,13 +46,13 @@ class _InteractionViewState extends State { fontSize: 16, color: Colors.red, fontWeight: FontWeight.w600)), ExpansionTileItem.outlined( expansionKey: key0, - expandedAlignment: Alignment.topLeft, isEnableExpanded: isEnableExpanded, isHideSubtitleOnExpanded: isHideSubtitle, isHasTrailing: isHasTrailing, isDefaultVerticalPadding: isDefaultVerticalPadding, trailingIcon: listIcon[currentIcon % listIcon.length], expendedBorderColor: Colors.grey, + isOnlyTrailingDoToggle: isOnlyTrailingDoToggle, title: const Text('ExpansionTileItem Results'), subtitle: const Text( 'Subtitle', @@ -70,63 +71,69 @@ class _InteractionViewState extends State { return Column(children: [ const Divider(), _buildRow(context, - title: 'Lock expanded state so that you can NOT expand anymore', - button: ElevatedButton.icon( - icon: Icon(isEnableExpanded ? Icons.lock_outline : Icons.lock_open), - label: Text(isEnableExpanded ? 'Do Lock' : 'Do Unlock'), - onPressed: () { + title: 'Do I need to enable expanded state?', + button: Checkbox( + value: isEnableExpanded, + onChanged: (value) { setState(() { - isEnableExpanded = !isEnableExpanded; + isEnableExpanded = value ?? false; }); }, )), const Divider(), _buildRow(context, - title: 'Hide the subtitle whenever you expand the view', - button: ElevatedButton.icon( - icon: Icon(isHideSubtitle - ? Icons.visibility_outlined - : Icons.visibility_off_outlined), - label: Text(isHideSubtitle ? 'Do Show' : 'Do Hide'), - onPressed: () { + title: 'Do I need to hide the subtitle whenever I expanded the view?', + button: Checkbox( + value: isHideSubtitle, + onChanged: (value) { setState(() { - isHideSubtitle = !isHideSubtitle; + isHideSubtitle = value ?? false; }); }, )), const Divider(), _buildRow(context, - title: 'Remove completely trailing not like ExpansionTile', - button: ElevatedButton.icon( - icon: Icon(isHasTrailing ? Icons.remove : Icons.add), - label: Text(isHasTrailing ? 'Remove trailing' : 'Add trailing'), - onPressed: () { + title: + 'Do I need to use ExpansionTile default trailing or remove completely it?', + button: Checkbox( + value: isHasTrailing, + onChanged: (value) { setState(() { - isHasTrailing = !isHasTrailing; + isHasTrailing = value ?? false; }); }, )), const Divider(), _buildRow(context, - title: 'Remove completely default vertical padding of ExpansionTile', - button: ElevatedButton.icon( - icon: Icon(isDefaultVerticalPadding ? Icons.remove : Icons.add), - label: Text(isDefaultVerticalPadding - ? 'Remove Default Padding' - : 'Add Default Padding'), - onPressed: () { + title: + 'Do I need to use ExpansionTile default vertical padding or remove it?', + button: Checkbox( + value: isDefaultVerticalPadding, + onChanged: (value) { + setState(() { + isDefaultVerticalPadding = value ?? false; + }); + }, + )), + const Divider(), + _buildRow(context, + title: 'Do I need to use just the trailing to toggle the state?', + button: Checkbox( + value: isOnlyTrailingDoToggle, + onChanged: (value) { setState(() { - isDefaultVerticalPadding = !isDefaultVerticalPadding; + isOnlyTrailingDoToggle = value ?? false; }); }, )), const Divider(), _buildRow(context, - title: 'Change Trailing Icon with keeping rotate animation', + title: + 'Do I need to change trailing icon with keeping rotate animation?', button: ElevatedButton.icon( icon: listIcon[currentIcon % listIcon.length], iconAlignment: IconAlignment.end, - label: const Text('Change icon'), + label: const Text('Tap to change'), onPressed: () { setState(() { currentIcon = currentIcon + 1; diff --git a/example/lib/use_cases/item/more_example_view.dart b/example/lib/use_cases/item/more_example_view.dart index 583aee9..5a9e005 100644 --- a/example/lib/use_cases/item/more_example_view.dart +++ b/example/lib/use_cases/item/more_example_view.dart @@ -162,6 +162,32 @@ class MoreCustomView extends StatelessWidget { const SizedBox( height: 16, ), + ExpansionTileItem( + initiallyExpanded: false, + title: const Text( + 'Title does not toggle the expansion state, but trail icon does #42'), + backgroundColor: Colors.red, + collapsedBackgroundColor: Colors.yellow, + textColor: Colors.white, + collapsedBorderColor: Colors.pink, + expendedBorderColor: Colors.blue, + iconColor: Colors.greenAccent, + collapsedIconColor: Colors.green, + isHasLeftBorder: true, + isHasTopBorder: true, + isHasRightBorder: true, + isHasBottomBorder: true, + borderRadius: BorderRadius.circular(8), + isOnlyTrailingDoToggle: true, + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.5), + spreadRadius: 5, + blurRadius: 7, + offset: const Offset(0, 3), // changes position of shadow + ), + ], + children: _buildDefaultChildren(context)), const SizedBox( height: 32, ), diff --git a/example/pubspec.lock b/example/pubspec.lock index e15574b..d117b10 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -55,7 +55,7 @@ packages: path: ".." relative: true source: path - version: "2.1.0" + version: "2.2.0" fake_async: dependency: transitive description: diff --git a/lib/src/core/expansion_tile_core.dart b/lib/src/core/expansion_tile_core.dart index d2f2967..3b435a7 100644 --- a/lib/src/core/expansion_tile_core.dart +++ b/lib/src/core/expansion_tile_core.dart @@ -70,6 +70,7 @@ class ExpansionTileCore extends StatefulWidget { this.isEnableExpanded = true, this.isDefaultVerticalPadding = true, this.isHideSubtitleOnExpanded = false, + this.isOnlyTrailingDoToggle = false, this.trailingIcon, }) : assert( expandedCrossAxisAlignment != CrossAxisAlignment.baseline, @@ -357,6 +358,9 @@ class ExpansionTileCore extends StatefulWidget { ///This property used to override the default trailing icon. final Widget? trailingIcon; + ///The title does NOT toggle the expansion state, but the trailing icon does + final bool isOnlyTrailingDoToggle; + @override State createState() => ExpansionTileCoreState(); } @@ -504,7 +508,8 @@ class ExpansionTileCoreState extends State ListTileControlAffinity.trailing) { return null; } - return _buildIcon(context); + if (!widget.isOnlyTrailingDoToggle) return _buildIcon(context); + return GestureDetector(onTap: _handleTap, child: _buildIcon(context)); } Widget _buildChildren(BuildContext context, Widget? child) { @@ -546,65 +551,7 @@ class ExpansionTileCoreState extends State return Column( mainAxisSize: MainAxisSize.min, children: [ - widget.isDefaultVerticalPadding - ? ListTileTheme.merge( - iconColor: _iconColor.value ?? expansionTileTheme.iconColor, - textColor: _headerColor.value, - child: InkWell( - borderRadius: widget.borderRadius, - onTap: _handleTap, - child: ListTile( - dense: widget.isDefaultVerticalPadding ? null : true, - visualDensity: widget.isDefaultVerticalPadding - ? null - : const VisualDensity(horizontal: 0, vertical: -4), - contentPadding: - widget.tilePadding ?? expansionTileTheme.tilePadding, - leading: widget.leading ?? _buildLeadingIcon(context), - title: widget.title, - subtitle: isHideSubtitle ? null : widget.subtitle, - trailing: widget.isHasTrailing == true - ? widget.trailing ?? _buildTrailingIcon(context) - : null, - ), - ), - ) - : IconTheme.merge( - data: IconThemeData( - color: _iconColor.value ?? expansionTileTheme.iconColor), - child: InkWell( - borderRadius: widget.borderRadius, - onTap: _handleTap, - child: Row( - children: [ - widget.leading ?? - _buildLeadingIcon(context) ?? - const SizedBox.shrink(), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: widget.tilePadding ?? - expansionTileTheme.tilePadding ?? - const EdgeInsets.symmetric(horizontal: 8), - child: DefaultTextStyle( - style: TextStyle(color: _headerColor.value), - child: widget.title), - ), - if (!isHideSubtitle) - widget.subtitle ?? const SizedBox.shrink(), - ], - ), - ), - widget.isHasTrailing == true - ? widget.trailing ?? - _buildTrailingIcon(context) ?? - const SizedBox.shrink() - : const SizedBox.shrink(), - ], - ), - )), + _buildMainTitle(context), ClipRect( child: Align( alignment: widget.expandedAlignment ?? @@ -618,6 +565,72 @@ class ExpansionTileCoreState extends State ); } + Widget _buildMainTitle(BuildContext context) { + final ExpansionTileThemeData expansionTileTheme = + ExpansionTileTheme.of(context); + if (widget.isDefaultVerticalPadding) { + return ListTileTheme.merge( + iconColor: _iconColor.value ?? expansionTileTheme.iconColor, + textColor: _headerColor.value, + child: InkWell( + borderRadius: widget.borderRadius, + onTap: widget.isOnlyTrailingDoToggle ? null : _handleTap, + child: ListTile( + dense: widget.isDefaultVerticalPadding ? null : true, + visualDensity: widget.isDefaultVerticalPadding + ? null + : const VisualDensity(horizontal: 0, vertical: -4), + contentPadding: + widget.tilePadding ?? expansionTileTheme.tilePadding, + leading: widget.leading ?? _buildLeadingIcon(context), + title: widget.title, + subtitle: isHideSubtitle ? null : widget.subtitle, + trailing: widget.isHasTrailing == true + ? widget.trailing ?? _buildTrailingIcon(context) + : null, + ), + ), + ); + } + + return IconTheme.merge( + data: IconThemeData( + color: _iconColor.value ?? expansionTileTheme.iconColor), + child: InkWell( + borderRadius: widget.borderRadius, + onTap: widget.isOnlyTrailingDoToggle ? null : _handleTap, + child: Row( + children: [ + widget.leading ?? + _buildLeadingIcon(context) ?? + const SizedBox.shrink(), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: widget.tilePadding ?? + expansionTileTheme.tilePadding ?? + const EdgeInsets.symmetric(horizontal: 8), + child: DefaultTextStyle( + style: TextStyle(color: _headerColor.value), + child: widget.title), + ), + if (!isHideSubtitle) + widget.subtitle ?? const SizedBox.shrink(), + ], + ), + ), + widget.isHasTrailing == true + ? widget.trailing ?? + _buildTrailingIcon(context) ?? + const SizedBox.shrink() + : const SizedBox.shrink(), + ], + ), + )); + } + @override void didChangeDependencies() { final ThemeData theme = Theme.of(context); diff --git a/lib/src/types/expansion_tile_card.dart b/lib/src/types/expansion_tile_card.dart index 63e4ca6..3285c75 100644 --- a/lib/src/types/expansion_tile_card.dart +++ b/lib/src/types/expansion_tile_card.dart @@ -34,6 +34,7 @@ class ExpansionTileCard extends ExpansionTileItem { super.isEnableExpanded, super.isDefaultVerticalPadding, super.isHideSubtitleOnExpanded, + super.isOnlyTrailingDoToggle, super.trailingIcon, this.elevation = 3.0, super.controller, diff --git a/lib/src/types/expansion_tile_flat.dart b/lib/src/types/expansion_tile_flat.dart index 0866dae..3cdb909 100644 --- a/lib/src/types/expansion_tile_flat.dart +++ b/lib/src/types/expansion_tile_flat.dart @@ -35,6 +35,7 @@ class ExpansionTileFlat extends ExpansionTileItem { super.isEnableExpanded, super.isDefaultVerticalPadding, super.isHideSubtitleOnExpanded, + super.isOnlyTrailingDoToggle, super.trailingIcon, super.controller, super.index, diff --git a/lib/src/types/expansion_tile_item.dart b/lib/src/types/expansion_tile_item.dart index d0e21a7..9558978 100644 --- a/lib/src/types/expansion_tile_item.dart +++ b/lib/src/types/expansion_tile_item.dart @@ -41,6 +41,7 @@ class ExpansionTileItem extends StatelessWidget { this.isDefaultVerticalPadding, this.isHideSubtitleOnExpanded, this.trailingIcon, + this.isOnlyTrailingDoToggle, this.controller, this.index, }) : assert((controller == null) == (index == null), @@ -78,6 +79,7 @@ class ExpansionTileItem extends StatelessWidget { this.isEnableExpanded, this.isDefaultVerticalPadding, this.isHideSubtitleOnExpanded, + this.isOnlyTrailingDoToggle, this.childrenPadding, this.expandedAlignment, this.controller, @@ -120,6 +122,7 @@ class ExpansionTileItem extends StatelessWidget { this.expandedAlignment, this.isHasTrailing, this.isEnableExpanded, + this.isOnlyTrailingDoToggle, this.borderRadius = const BorderRadius.all(Radius.circular(8)), this.collapsedBorderColor = Colors.grey, this.expendedBorderColor = Colors.blue, @@ -162,6 +165,7 @@ class ExpansionTileItem extends StatelessWidget { this.expandedAlignment, this.isHasTrailing, this.isEnableExpanded, + this.isOnlyTrailingDoToggle, this.controller, this.index, Color? collapsedBorderColor, @@ -219,6 +223,7 @@ class ExpansionTileItem extends StatelessWidget { bool? isEnableExpanded, bool? isDefaultVerticalPadding, bool? isHideSubtitleOnExpanded, + bool? isOnlyTrailingDoToggle, Widget? trailingIcon, double? elevation, ExpansionGroupController? controller, @@ -256,6 +261,7 @@ class ExpansionTileItem extends StatelessWidget { isEnableExpanded: isEnableExpanded, isDefaultVerticalPadding: isDefaultVerticalPadding, isHideSubtitleOnExpanded: isHideSubtitleOnExpanded, + isOnlyTrailingDoToggle: isOnlyTrailingDoToggle, trailingIcon: trailingIcon, controller: controller, index: index, @@ -526,6 +532,8 @@ class ExpansionTileItem extends StatelessWidget { ///This property used to override the default trailing icon. final Widget? trailingIcon; + final bool? isOnlyTrailingDoToggle; + final ExpansionGroupController? controller; final int? index; @@ -669,6 +677,7 @@ class ExpansionTileItem extends StatelessWidget { isDefaultVerticalPadding: isDefaultVerticalPadding ?? true, isHideSubtitleOnExpanded: isHideSubtitleOnExpanded ?? false, trailingIcon: trailingIcon, + isOnlyTrailingDoToggle: isOnlyTrailingDoToggle ?? false, children: children ?? [], ), ); diff --git a/lib/src/types/expansion_tile_leaf.dart b/lib/src/types/expansion_tile_leaf.dart index 9cc3744..9f3e0c4 100644 --- a/lib/src/types/expansion_tile_leaf.dart +++ b/lib/src/types/expansion_tile_leaf.dart @@ -34,6 +34,7 @@ class ExpansionTileLeaf extends ExpansionTileItem { super.isDefaultVerticalPadding, super.isEnableExpanded, super.isHideSubtitleOnExpanded, + super.isOnlyTrailingDoToggle, super.controller, super.index, bool isOutlined = false, diff --git a/lib/src/types/expansion_tile_outlined.dart b/lib/src/types/expansion_tile_outlined.dart index 3616b53..df6ead5 100644 --- a/lib/src/types/expansion_tile_outlined.dart +++ b/lib/src/types/expansion_tile_outlined.dart @@ -34,6 +34,7 @@ class ExpansionTileOutlined extends ExpansionTileItem { super.trailingIcon, super.childrenPadding, super.expandedAlignment, + super.isOnlyTrailingDoToggle, super.borderRadius = const BorderRadius.all(Radius.circular(8)), super.collapsedBorderColor = Colors.grey, super.expendedBorderColor = Colors.blue, diff --git a/pubspec.yaml b/pubspec.yaml index 5e953cc..a885747 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -9,11 +9,11 @@ documentation: https://pub.dev/documentation/expansion_tile_group topics: - expansion - expansion-tile - - ui + - view-more - widget - expansion-tile-group -version: 2.1.0 +version: 2.2.0 environment: sdk: '>=2.18.0 <4.0.0' flutter: ">=1.17.0"