268 lines
9.8 KiB
Dart
268 lines
9.8 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
|
import 'package:onufitness/constants/color_constant.dart';
|
|
import 'package:onufitness/utils/helper_function.dart';
|
|
|
|
class CustomDropdownField extends StatefulWidget {
|
|
final String title;
|
|
String? selectedItem;
|
|
final List<String> items;
|
|
final ValueChanged<String?>? onChanged;
|
|
final Color? borderColor;
|
|
final Color? filledColor;
|
|
final double? height;
|
|
final bool isSearchEnabled;
|
|
|
|
CustomDropdownField({
|
|
super.key,
|
|
required this.title,
|
|
required this.items,
|
|
this.selectedItem,
|
|
this.onChanged,
|
|
this.borderColor,
|
|
this.filledColor,
|
|
this.height,
|
|
this.isSearchEnabled = false,
|
|
});
|
|
|
|
@override
|
|
CustomDropdownFieldState createState() => CustomDropdownFieldState();
|
|
}
|
|
|
|
int countryIndex = 0;
|
|
|
|
class CustomDropdownFieldState extends State<CustomDropdownField> {
|
|
final TextEditingController _searchController = TextEditingController();
|
|
|
|
@override
|
|
void dispose() {
|
|
_searchController.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
void _showSearchableDropdown() {
|
|
// Reset search controller when opening dialog
|
|
_searchController.clear();
|
|
List<String> filteredItems = widget.items; // Initialize with all items
|
|
if (widget.items.isEmpty) return;
|
|
showDialog(
|
|
context: context,
|
|
builder: (BuildContext context) {
|
|
return StatefulBuilder(
|
|
builder: (context, setDialogState) {
|
|
void filterItems(String query) {
|
|
setDialogState(() {
|
|
if (query.isEmpty) {
|
|
filteredItems = widget.items;
|
|
} else {
|
|
filteredItems =
|
|
widget.items
|
|
.where(
|
|
(item) => item.toLowerCase().contains(
|
|
query.toLowerCase(),
|
|
),
|
|
)
|
|
.toList();
|
|
}
|
|
});
|
|
}
|
|
|
|
return Dialog(
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(10.r),
|
|
),
|
|
child: Container(
|
|
constraints: BoxConstraints(maxHeight: 400.h),
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
// Search field
|
|
Padding(
|
|
padding: EdgeInsets.all(16.w),
|
|
child: TextField(
|
|
controller: _searchController,
|
|
autofocus: false,
|
|
decoration: InputDecoration(
|
|
hintText: 'Search ${widget.title}',
|
|
prefixIcon: const Icon(Icons.search),
|
|
suffixIcon:
|
|
_searchController.text.isNotEmpty
|
|
? IconButton(
|
|
icon: const Icon(Icons.clear),
|
|
onPressed: () {
|
|
_searchController.clear();
|
|
filterItems('');
|
|
},
|
|
)
|
|
: null,
|
|
border: OutlineInputBorder(
|
|
borderRadius: BorderRadius.circular(10.r),
|
|
),
|
|
contentPadding: EdgeInsets.symmetric(
|
|
horizontal: 16.w,
|
|
vertical: 12.h,
|
|
),
|
|
),
|
|
onChanged: (value) {
|
|
filterItems(value);
|
|
},
|
|
),
|
|
),
|
|
// Items list
|
|
Expanded(
|
|
child:
|
|
filteredItems.isEmpty
|
|
? Center(
|
|
child: Text(
|
|
'No items found',
|
|
style: TextStyle(
|
|
fontSize: 16.sp,
|
|
color: greyTextColor1,
|
|
),
|
|
),
|
|
)
|
|
: ListView.builder(
|
|
shrinkWrap: true,
|
|
itemCount: filteredItems.length,
|
|
itemBuilder: (context, index) {
|
|
final item = filteredItems[index];
|
|
final isSelected =
|
|
widget.selectedItem == item;
|
|
return ListTile(
|
|
title: Text(
|
|
item,
|
|
style: TextStyle(
|
|
fontSize: isTablet ? 14.sp : 16.sp,
|
|
fontWeight:
|
|
isSelected
|
|
? FontWeight.w600
|
|
: FontWeight.normal,
|
|
color:
|
|
isSelected
|
|
? Theme.of(context).primaryColor
|
|
: Colors.black,
|
|
),
|
|
),
|
|
trailing:
|
|
isSelected
|
|
? Icon(
|
|
Icons.check,
|
|
color:
|
|
Theme.of(
|
|
context,
|
|
).primaryColor,
|
|
)
|
|
: null,
|
|
onTap: () {
|
|
widget.selectedItem = item;
|
|
|
|
widget.onChanged?.call(item);
|
|
Navigator.pop(context);
|
|
},
|
|
);
|
|
},
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
},
|
|
);
|
|
},
|
|
);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final Color effectiveBorderColor =
|
|
widget.borderColor ?? textfieldBorderColorSky1;
|
|
|
|
if (widget.isSearchEnabled) {
|
|
return GestureDetector(
|
|
onTap: widget.items.isNotEmpty ? _showSearchableDropdown : null,
|
|
child: Container(
|
|
height: widget.height ?? (isTablet ? 60.h : null),
|
|
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 16.h),
|
|
decoration: BoxDecoration(
|
|
border: Border.all(color: effectiveBorderColor),
|
|
borderRadius: BorderRadius.circular(10.r),
|
|
color: widget.filledColor ?? textFieldFillColor,
|
|
),
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Expanded(
|
|
child: Text(
|
|
widget.selectedItem != null && widget.selectedItem!.isNotEmpty
|
|
? widget.selectedItem!
|
|
: widget.title,
|
|
style: TextStyle(
|
|
fontSize: isTablet ? 17.sp : 16.sp,
|
|
color:
|
|
widget.selectedItem != null &&
|
|
widget.selectedItem!.isNotEmpty
|
|
? Colors.black
|
|
: greyTextColor1,
|
|
fontWeight: FontWeight.w500,
|
|
),
|
|
overflow: TextOverflow.ellipsis,
|
|
),
|
|
),
|
|
SizedBox(width: 8.w),
|
|
Icon(
|
|
Icons.keyboard_arrow_down,
|
|
size: isTablet ? 30.sp : 24.sp,
|
|
color: widget.items.isEmpty ? Colors.grey.shade400 : null,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
return Container(
|
|
height: widget.height ?? (isTablet ? 60.h : null),
|
|
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 3.h),
|
|
decoration: BoxDecoration(
|
|
border: Border.all(color: effectiveBorderColor),
|
|
borderRadius: BorderRadius.circular(10.r),
|
|
color: widget.filledColor ?? textFieldFillColor,
|
|
),
|
|
child: DropdownButtonHideUnderline(
|
|
child: DropdownButton<String>(
|
|
value:
|
|
(widget.selectedItem == null || widget.selectedItem!.isEmpty)
|
|
? null
|
|
: widget.selectedItem,
|
|
hint: Text(
|
|
widget.title,
|
|
style: TextStyle(
|
|
fontSize: isTablet ? 17.sp : 16.sp,
|
|
color: greyTextColor1,
|
|
fontWeight: FontWeight.w500,
|
|
),
|
|
),
|
|
icon: Icon(Icons.keyboard_arrow_down, size: isTablet ? 30.sp : null),
|
|
isExpanded: true,
|
|
items: List.generate(widget.items.length, (index) {
|
|
countryIndex = index;
|
|
final value = widget.items[index];
|
|
return DropdownMenuItem<String>(
|
|
value: value,
|
|
child: Text(
|
|
value,
|
|
style: TextStyle(fontSize: isTablet ? 14.sp : 16.sp),
|
|
),
|
|
);
|
|
}),
|
|
onChanged: widget.onChanged,
|
|
dropdownColor: Colors.white,
|
|
borderRadius: BorderRadius.circular(10.r),
|
|
menuMaxHeight: 200.h,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|