From 729b80d4dcb1fa8d120ea57a8f39f00c3ea171ac Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Wed, 20 May 2026 16:19:39 +0300 Subject: [PATCH] animation added. --- .../multiple_selection_fullscreen_dialog.dart | 96 ++++++++++++----- .../selection_fullscreen_dialog.dart | 102 ++++++++++++------ 2 files changed, 139 insertions(+), 59 deletions(-) diff --git a/lib/views/widgets/fullscreen_dialogs/multiple_selection_fullscreen_dialog.dart b/lib/views/widgets/fullscreen_dialogs/multiple_selection_fullscreen_dialog.dart index 2bb2cd87..7125db0a 100644 --- a/lib/views/widgets/fullscreen_dialogs/multiple_selection_fullscreen_dialog.dart +++ b/lib/views/widgets/fullscreen_dialogs/multiple_selection_fullscreen_dialog.dart @@ -27,10 +27,11 @@ class MultipleSelectionFullScreenDialog extends StatefulWidget { _SelectionBottomSheetState createState() => _SelectionBottomSheetState(); } -class _SelectionBottomSheetState extends State> { +class _SelectionBottomSheetState extends State> with SingleTickerProviderStateMixin { late List _selectedValue; // Now nullable String query = ""; + late AnimationController _animationController; List? get filteredList => widget.items?.where((element) => widget.builderString(element).toLowerCase().contains(query.toLowerCase())).toList(); @@ -40,12 +41,18 @@ class _SelectionBottomSheetState extends State.from(widget.selectedItem); super.initState(); + _animationController = AnimationController( + duration: const Duration(milliseconds: 1200), + vsync: this, + ); + _animationController.forward(); } FocusNode searchFocusNode = FocusNode(); @override void dispose() { + _animationController.dispose(); searchFocusNode.dispose(); super.dispose(); } @@ -132,34 +139,67 @@ class _SelectionBottomSheetState extends State(begin: 0.0, end: 1.0).animate( + CurvedAnimation( + parent: _animationController, + curve: Interval( + delay.clamp(0.0, 0.8), + (delay + 0.3).clamp(0.0, 1.0), + curve: Curves.easeOut, + ), + ), + ); + + final slideAnimation = Tween( + begin: const Offset(0.0, 0.3), + end: Offset.zero, + ).animate( + CurvedAnimation( + parent: _animationController, + curve: Interval( + delay.clamp(0.0, 0.8), + (delay + 0.3).clamp(0.0, 1.0), + curve: Curves.easeOutCubic, + ), + ), + ); + bool isDisabledItem = widget.disableItem != null && widget.disableItem?.identifier == filteredList![index].identifier; - return CheckboxListTile( - value: checkItContains(filteredList![index]), - dense: true, - controlAffinity: ListTileControlAffinity.leading, - activeColor: AppColor.primary10, - checkColor: AppColor.white10, - // fillColor: WidgetStateProperty.all(AppColor.background(context)), - contentPadding: const EdgeInsets.only(left: 16, right: 16), - // activeColor: AppColor.blueStatus(context), - side: BorderSide(color: AppColor.icon2Color(context).withValues(alpha: .3), width: 1.0), - onChanged: (value) { - // if (checkItContains(filteredList![index]) ?? false) { - // _selectedValue.remove(filteredList![index]); - // } else { - // _selectedValue.add(filteredList![index]); - // } - if (value == true) { - _selectedValue.add(filteredList![index]); - } else if (value == false) { - _selectedValue.remove(filteredList![index]); - } - searchFocusNode.unfocus(); - setState(() {}); - }, - title: Text( - widget.builderString(filteredList![index]).cleanupWhitespace.capitalizeFirstOfEach ?? "", - style: Theme.of(context).textTheme.bodyLarge, + return FadeTransition( + opacity: animation, + child: SlideTransition( + position: slideAnimation, + child: CheckboxListTile( + value: checkItContains(filteredList![index]), + dense: true, + controlAffinity: ListTileControlAffinity.leading, + activeColor: AppColor.primary10, + checkColor: AppColor.white10, + // fillColor: WidgetStateProperty.all(AppColor.background(context)), + contentPadding: const EdgeInsets.only(left: 16, right: 16), + // activeColor: AppColor.blueStatus(context), + side: BorderSide(color: AppColor.icon2Color(context).withValues(alpha: .3), width: 1.0), + onChanged: (value) { + // if (checkItContains(filteredList![index]) ?? false) { + // _selectedValue.remove(filteredList![index]); + // } else { + // _selectedValue.add(filteredList![index]); + // } + if (value == true) { + _selectedValue.add(filteredList![index]); + } else if (value == false) { + _selectedValue.remove(filteredList![index]); + } + searchFocusNode.unfocus(); + setState(() {}); + }, + title: Text( + widget.builderString(filteredList![index]).cleanupWhitespace.capitalizeFirstOfEach ?? "", + style: Theme.of(context).textTheme.bodyLarge, + ), + ), ), ); }), diff --git a/lib/views/widgets/fullscreen_dialogs/selection_fullscreen_dialog.dart b/lib/views/widgets/fullscreen_dialogs/selection_fullscreen_dialog.dart index a102e230..95ffa91b 100644 --- a/lib/views/widgets/fullscreen_dialogs/selection_fullscreen_dialog.dart +++ b/lib/views/widgets/fullscreen_dialogs/selection_fullscreen_dialog.dart @@ -26,10 +26,11 @@ class SelectionFullScreenDialog extends StatefulWidget { _SelectionBottomSheetState createState() => _SelectionBottomSheetState(); } -class _SelectionBottomSheetState extends State> { +class _SelectionBottomSheetState extends State> with SingleTickerProviderStateMixin { T? _selectedValue; // Now nullable String query = ""; + late AnimationController _animationController; List? get filteredList => widget.items?.where((element) => widget.builderString(element).toLowerCase().contains(query.toLowerCase())).toList(); @@ -37,12 +38,18 @@ class _SelectionBottomSheetState extends State extends State(begin: 0.0, end: 1.0).animate( + CurvedAnimation( + parent: _animationController, + curve: Interval( + delay.clamp(0.0, 0.8), + (delay + 0.3).clamp(0.0, 1.0), + curve: Curves.easeOut, ), ), - child: RadioListTile( - // Specify type for RadioListTile - value: filteredList![index], - dense: true, - contentPadding: const EdgeInsets.only(left: 16, right: 16), - groupValue: _selectedValue, - // activeColor: AppColor.iconColor(context), - // activeColor: AppColor.primary10,colo + ); + + final slideAnimation = Tween( + begin: const Offset(0.0, 0.3), + end: Offset.zero, + ).animate( + CurvedAnimation( + parent: _animationController, + curve: Interval( + delay.clamp(0.0, 0.8), + (delay + 0.3).clamp(0.0, 1.0), + curve: Curves.easeOutCubic, + ), + ), + ); + + bool isDisabledItem = widget.disableItem != null && widget.disableItem?.identifier == filteredList![index].identifier; + return FadeTransition( + opacity: animation, + child: SlideTransition( + position: slideAnimation, + child: Theme( + data: Theme.of(context).copyWith( + radioTheme: RadioThemeData( + fillColor: MaterialStateColor.resolveWith((states) { + if (states.contains(MaterialState.selected)) { + return AppColor.primary10; // Active color + } + return AppColor.icon2Color(context).withValues(alpha: .5); + }), + ), + ), + child: RadioListTile( + // Specify type for RadioListTile + value: filteredList![index], + dense: true, + contentPadding: const EdgeInsets.only(left: 16, right: 16), + groupValue: _selectedValue, + // activeColor: AppColor.iconColor(context), + // activeColor: AppColor.primary10,colo - // checkColor: AppColor.white10, - hoverColor: Colors.transparent, - onChanged: isDisabledItem - ? null - : (value) { - _selectedValue = value; - searchFocusNode.unfocus(); - setState(() {}); - }, - title: Text( - widget.builderString(filteredList![index]).cleanupWhitespace.capitalizeFirstOfEach ?? "", - style: Theme.of(context).textTheme.bodyLarge?.copyWith(color: isDisabledItem ? AppColor.neutral20 : null), + // checkColor: AppColor.white10, + hoverColor: Colors.transparent, + onChanged: isDisabledItem + ? null + : (value) { + _selectedValue = value; + searchFocusNode.unfocus(); + setState(() {}); + }, + title: Text( + widget.builderString(filteredList![index]).cleanupWhitespace.capitalizeFirstOfEach ?? "", + style: Theme.of(context).textTheme.bodyLarge?.copyWith(color: isDisabledItem ? AppColor.neutral20 : null), + ), + ), ), ), );