animation added.

main_production_RSG
Sikander Saleem 1 month ago
parent dc893b7836
commit 729b80d4dc

@ -27,10 +27,11 @@ class MultipleSelectionFullScreenDialog<T extends Base> extends StatefulWidget {
_SelectionBottomSheetState createState() => _SelectionBottomSheetState<T>();
}
class _SelectionBottomSheetState<T extends Base> extends State<MultipleSelectionFullScreenDialog<T>> {
class _SelectionBottomSheetState<T extends Base> extends State<MultipleSelectionFullScreenDialog<T>> with SingleTickerProviderStateMixin {
late List<T> _selectedValue; // Now nullable
String query = "";
late AnimationController _animationController;
List<T>? get filteredList => widget.items?.where((element) => widget.builderString(element).toLowerCase().contains(query.toLowerCase())).toList();
@ -40,12 +41,18 @@ class _SelectionBottomSheetState<T extends Base> extends State<MultipleSelection
// This ensures temporary selections don't affect parent until confirmed
_selectedValue = List<T>.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<T extends Base> extends State<MultipleSelection
itemCount: filteredList?.length,
padding: EdgeInsets.zero,
itemBuilder: (cxt, index) {
// Calculate staggered animation delay
final delay = index * 0.08;
final animation = Tween<double>(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<Offset>(
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,
),
),
),
);
}),

@ -26,10 +26,11 @@ class SelectionFullScreenDialog<T extends Base> extends StatefulWidget {
_SelectionBottomSheetState createState() => _SelectionBottomSheetState<T>();
}
class _SelectionBottomSheetState<T extends Base> extends State<SelectionFullScreenDialog<T>> {
class _SelectionBottomSheetState<T extends Base> extends State<SelectionFullScreenDialog<T>> with SingleTickerProviderStateMixin {
T? _selectedValue; // Now nullable
String query = "";
late AnimationController _animationController;
List<T>? get filteredList => widget.items?.where((element) => widget.builderString(element).toLowerCase().contains(query.toLowerCase())).toList();
@ -37,12 +38,18 @@ class _SelectionBottomSheetState<T extends Base> extends State<SelectionFullScre
void initState() {
_selectedValue = 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();
}
@ -129,39 +136,72 @@ class _SelectionBottomSheetState<T extends Base> extends State<SelectionFullScre
itemCount: filteredList?.length,
padding: EdgeInsets.only(bottom: _selectedValue != null ? 4.toScreenHeight : 48.toScreenHeight),
itemBuilder: (cxt, index) {
bool isDisabledItem = widget.disableItem != null && widget.disableItem?.identifier == filteredList![index].identifier;
return 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);
}),
// Calculate staggered animation delay
final delay = index * 0.08;
final animation = Tween<double>(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<T>(
// 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<Offset>(
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<T>(
// 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),
),
),
),
),
);

Loading…
Cancel
Save