app_dropdown_search.dart 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. import 'dart:async';
  2. import 'package:dropdown_search/dropdown_search.dart';
  3. import 'package:flutter/material.dart';
  4. import '../themes/themes.dart';
  5. class AppDropdownSearch<T> extends StatelessWidget {
  6. final void Function(dynamic)? onChanged;
  7. final dynamic selectedItem;
  8. final String? etiqueta;
  9. final TextEditingController controller;
  10. final String Function(dynamic)? itemAsString;
  11. final Future<List<dynamic>> Function(String)? asyncItems;
  12. final bool enabled;
  13. final List<dynamic> items;
  14. final String? Function(dynamic)? validator;
  15. final dynamic Function()? onPressedClear;
  16. final DropdownSearchCompareFn? compareFn;
  17. const AppDropdownSearch({
  18. super.key,
  19. required this.controller,
  20. this.itemAsString,
  21. this.asyncItems,
  22. this.etiqueta,
  23. this.selectedItem,
  24. this.onChanged,
  25. this.onPressedClear,
  26. this.validator,
  27. this.enabled = true,
  28. this.items = const [],
  29. this.compareFn,
  30. });
  31. double _getFontSize(BuildContext context) {
  32. double screenWidth = MediaQuery.of(context).size.width;
  33. if (screenWidth < 480) {
  34. return 12;
  35. } else if (screenWidth < 800) {
  36. return 15;
  37. }
  38. return 16;
  39. }
  40. @override
  41. Widget build(BuildContext context) {
  42. double fontSize = _getFontSize(context);
  43. TextStyle dropdownTextStyle = TextStyle(fontSize: fontSize);
  44. return Column(
  45. crossAxisAlignment: CrossAxisAlignment.start,
  46. children: [
  47. if (etiqueta != null)
  48. Text(
  49. etiqueta.toString(),
  50. style: TextStyle(fontSize: fontSize, fontWeight: FontWeight.bold),
  51. ),
  52. if (etiqueta != null) const SizedBox(height: 5),
  53. DropdownSearch(
  54. suffixProps: const DropdownSuffixProps(
  55. clearButtonProps: ClearButtonProps(
  56. isVisible: true,
  57. icon: const Icon(Icons.clear),
  58. iconSize: 20,
  59. ),
  60. ),
  61. compareFn: compareFn,
  62. validator: validator,
  63. onChanged: onChanged,
  64. // asyncItems: asyncItems,
  65. items: (filter, infiniteScrollProps) => items,
  66. itemAsString: itemAsString,
  67. selectedItem: selectedItem,
  68. enabled: enabled,
  69. popupProps: PopupProps.menu(
  70. emptyBuilder: (context, searchEntry) => Center(
  71. child: Column(
  72. mainAxisAlignment: MainAxisAlignment.center,
  73. children: [
  74. Icon(Icons.inbox, size: 60, color: Colors.grey),
  75. const SizedBox(height: 10),
  76. Text(
  77. 'No se encontró información',
  78. style: dropdownTextStyle,
  79. ),
  80. ],
  81. ),
  82. ),
  83. // isFilterOnline: true,
  84. showSearchBox: true,
  85. searchFieldProps: TextFieldProps(
  86. controller: controller,
  87. autofocus: true,
  88. decoration: InputDecoration(
  89. hintText: 'Teclee para buscar',
  90. hintStyle: dropdownTextStyle,
  91. suffixIcon: const Icon(Icons.search, color: Colors.grey),
  92. fillColor: Colors.white,
  93. focusedBorder: UnderlineInputBorder(
  94. borderSide: BorderSide(color: AppTheme.primary),
  95. ),
  96. enabledBorder: const UnderlineInputBorder(
  97. borderSide: BorderSide(color: Colors.grey),
  98. ),
  99. errorBorder: UnderlineInputBorder(
  100. borderSide: BorderSide(
  101. color: Colors.grey[400]!,
  102. ),
  103. ),
  104. focusedErrorBorder: UnderlineInputBorder(
  105. borderSide: BorderSide(
  106. color: AppTheme.primary,
  107. ),
  108. ),
  109. floatingLabelStyle: TextStyle(
  110. color: AppTheme.primary,
  111. fontSize: fontSize,
  112. ),
  113. ),
  114. ),
  115. ),
  116. decoratorProps: DropDownDecoratorProps(
  117. baseStyle: dropdownTextStyle,
  118. decoration: InputDecoration(
  119. fillColor: Colors.white,
  120. suffixIcon: Icon(
  121. Icons.arrow_drop_down_circle,
  122. color: AppTheme.primary,
  123. ),
  124. focusedBorder: OutlineInputBorder(
  125. borderRadius: BorderRadius.circular(10),
  126. borderSide: BorderSide(
  127. color: AppTheme.primary,
  128. ),
  129. ),
  130. enabledBorder: OutlineInputBorder(
  131. borderRadius: BorderRadius.circular(10),
  132. borderSide: BorderSide(
  133. color: Colors.grey[400]!,
  134. ),
  135. ),
  136. errorBorder: OutlineInputBorder(
  137. borderRadius: BorderRadius.circular(10),
  138. borderSide: BorderSide(
  139. color: Colors.grey[300]!,
  140. ),
  141. ),
  142. focusedErrorBorder: OutlineInputBorder(
  143. borderRadius: BorderRadius.circular(10),
  144. borderSide: BorderSide(
  145. color: AppTheme.primary,
  146. ),
  147. ),
  148. disabledBorder: OutlineInputBorder(
  149. borderRadius: BorderRadius.circular(10),
  150. borderSide: BorderSide(
  151. color: Colors.grey[300]!,
  152. ),
  153. ),
  154. ),
  155. ),
  156. ),
  157. ],
  158. );
  159. }
  160. }