24
this.isGridView = false,
25
this.isSeparated = true,
26
this.hintText,
27
+ this.headerEnabled = true,
28
+ this.closeOnItemSelected = true,
29
+ this.sliderValue,
30
+ this.customItemIndex,
31
+ this.isWrapped = true,
32
+ this.borderColor,
33
+ this.onSliderChanged,
34
this.matchingCriteria,
35
}) : assert(hintText == null ||
36
matchingCriteria !=
47
final bool isGridView;
48
final bool isSeparated;
49
final String? hintText;
50
+ final bool headerEnabled;
51
+ final bool closeOnItemSelected;
52
+ final double? sliderValue;
53
+ final int? customItemIndex;
54
+ final bool isWrapped;
55
+ final Color? borderColor;
56
+ final Function(double)? onSliderChanged;
57
final bool Function(Item, String)? matchingCriteria;
58
59
@override
138
containerHeight = height * 0.75;
139
}
140
127
- return PickerWrapperWidget(
128
- hasTitle: widget.title?.isNotEmpty ?? false,
141
+ final content = Column (
142
children: [
143
if (widget.title?.isNotEmpty ?? false)
144
Container(
157
),
158
Padding(
159
padding: EdgeInsets.symmetric(horizontal: padding),
147
- child: ClipRRect(
148
- borderRadius: BorderRadius.all(Radius.circular(30)),
149
- child: Container(
150
- color: Theme.of(context).dialogTheme.backgroundColor,
151
- child: ConstrainedBox(
152
- constraints: BoxConstraints(
153
- maxHeight: containerHeight,
154
- maxWidth: ResponsiveLayoutUtilBase.kPopupWidth,
155
- ),
156
- child: Column(
157
- mainAxisSize: MainAxisSize.min,
158
- children: [
159
- if (widget.hintText != null)
160
- Padding(
161
- padding: const EdgeInsets.all(16),
162
- child: SearchBarWidget(searchController: searchController),
160
+ child: Container(
161
+ decoration: BoxDecoration(
162
+ borderRadius: BorderRadius.circular(30),
163
+ border: Border.all(
164
+ color: widget.borderColor ?? Colors.transparent,
165
+ ),
166
+ ),
167
+ child: ClipRRect(
168
+ borderRadius: BorderRadius.all(Radius.circular(30)),
169
+ child: Container(
170
+ color: Theme.of(context).dialogTheme.backgroundColor,
171
+ child: ConstrainedBox(
172
+ constraints: BoxConstraints(
173
+ maxHeight: containerHeight,
174
+ maxWidth: ResponsiveLayoutUtilBase.kPopupWidth,
175
+ ),
176
+ child: Column(
177
+ mainAxisSize: MainAxisSize.min,
178
+ children: [
179
+ if (widget.hintText != null)
180
+ Padding(
181
+ padding: const EdgeInsets.all(16),
182
+ child: SearchBarWidget(
183
+ searchController: searchController, hintText: widget.hintText),
184
+ ),
185
+ Divider(
186
+ color: Theme.of(context).extension<PickerTheme>()!.dividerColor,
187
+ height: 1,
188
),
164
- Divider(
165
- color: Theme.of(context).extension<PickerTheme>()!.dividerColor,
166
- height: 1,
167
- ),
168
- if (widget.selectedAtIndex != -1) buildSelectedItem(widget.selectedAtIndex),
169
- Flexible(
170
- child: Stack(
171
- alignment: Alignment.center,
172
- children: <Widget>[
173
- filteredItems.length > 3
174
- ? Scrollbar(
175
- controller: controller,
176
- child: itemsList(),
177
- )
178
- : itemsList(),
179
- (widget.description?.isNotEmpty ?? false)
180
- ? Positioned(
181
- bottom: padding,
182
- left: padding,
183
- right: padding,
184
- child: Text(
185
- widget.description!,
186
- textAlign: TextAlign.center,
187
- style: TextStyle(
188
- fontSize: 12,
189
- fontWeight: FontWeight.w500,
190
- fontFamily: 'Lato',
191
- decoration: TextDecoration.none,
192
- color:
193
- Theme.of(context).extension<CakeTextTheme>()!.titleColor,
189
+ if (widget.selectedAtIndex != -1 && widget.headerEnabled)
190
+ buildSelectedItem(widget.selectedAtIndex),
191
+ Flexible(
192
+ child: Stack(
193
+ alignment: Alignment.center,
194
+ children: <Widget>[
195
+ filteredItems.length > 3
196
+ ? Scrollbar(
197
+ controller: controller,
198
+ child: itemsList(),
199
+ )
200
+ : itemsList(),
201
+ (widget.description?.isNotEmpty ?? false)
202
+ ? Positioned(
203
+ bottom: padding,
204
+ left: padding,
205
+ right: padding,
206
+ child: Text(
207
+ widget.description!,
208
+ textAlign: TextAlign.center,
209
+ style: TextStyle(
210
+ fontSize: 12,
211
+ fontWeight: FontWeight.w500,
212
+ fontFamily: 'Lato',
213
+ decoration: TextDecoration.none,
214
+ color:
215
+ Theme.of(context).extension<CakeTextTheme>()!.titleColor,
216
+ ),
217
),
195
- ),
196
- )
197
- : Offstage(),
198
- ],
218
+ )
219
+ : Offstage(),
220
+ ],
221
+ ),
222
),
200
- ),
201
- ],
223
+ ],
224
+ ),
225
),
226
),
227
),
229
)
230
],
231
);
232
+
233
+ if (widget.isWrapped) {
234
+ return PickerWrapperWidget(
235
+ hasTitle: widget.title?.isNotEmpty ?? false,
236
+ children: [content],
237
+ );
238
+ } else {
239
+ return content;
240
+ }
241
}
242
243
Widget itemsList() {
244
+ final itemCount = !widget.headerEnabled
245
+ ? items.length
246
+ : filteredItems.isEmpty
247
+ ? 0
248
+ : filteredItems.length;
249
return Container(
250
color: Theme.of(context).extension<PickerTheme>()!.dividerColor,
251
child: widget.isGridView
253
padding: EdgeInsets.zero,
254
controller: controller,
255
shrinkWrap: true,
219
- itemCount: filteredItems.isEmpty ? 0 : filteredItems.length,
256
+ itemCount: itemCount,
257
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
258
crossAxisCount: 2,
259
crossAxisSpacing: 2,
260
childAspectRatio: 3,
261
),
225
- itemBuilder: (context, index) => buildItem(index),
262
+ itemBuilder: (context, index) =>
263
+ !widget.headerEnabled && widget.selectedAtIndex == index
264
+ ? buildSelectedItem(index)
265
+ : buildItem(index),
266
)
267
: ListView.separated(
268
padding: EdgeInsets.zero,
274
height: 1,
275
)
276
: const SizedBox(),
237
- itemCount: filteredItems.isEmpty ? 0 : filteredItems.length,
238
- itemBuilder: (context, index) => buildItem(index),
277
+ itemCount: itemCount,
278
+ itemBuilder: (context, index) =>
279
+ !widget.headerEnabled && widget.selectedAtIndex == index
280
+ ? buildSelectedItem(index)
281
+ : buildItem(index),
282
),
283
);
284
}
285
286
Widget buildItem(int index) {
244
- final item = filteredItems[index];
287
+ final item = widget.headerEnabled ? filteredItems[index] : items[index];
288
289
final tag = item is Currency ? item.tag : null;
290
final icon = _getItemIcon(item);
291
292
final image = images.isNotEmpty ? filteredImages[index] : icon;
293
294
+ final isCustomItem = widget.customItemIndex != null && index == widget.customItemIndex;
295
+
296
+ final itemContent = Row(
297
+ mainAxisSize: MainAxisSize.max,
298
+ mainAxisAlignment: widget.mainAxisAlignment,
299
+ crossAxisAlignment: CrossAxisAlignment.center,
300
+ children: <Widget>[
301
+ image ?? Offstage(),
302
+ Expanded(
303
+ child: Padding(
304
+ padding: EdgeInsets.only(left: image != null ? 12 : 0),
305
+ child: Row(
306
+ children: [
307
+ Flexible(
308
+ child: Text(
309
+ widget.displayItem?.call(item) ?? item.toString(),
310
+ softWrap: true,
311
+ style: TextStyle(
312
+ fontSize: 14,
313
+ fontFamily: 'Lato',
314
+ fontWeight: FontWeight.w600,
315
+ color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
316
+ decoration: TextDecoration.none,
317
+ ),
318
+ ),
319
+ ),
320
+ if (tag != null)
321
+ Align(
322
+ alignment: Alignment.topCenter,
323
+ child: Container(
324
+ width: 35.0,
325
+ height: 18.0,
326
+ child: Center(
327
+ child: Text(
328
+ tag,
329
+ style: TextStyle(
330
+ fontSize: 7.0,
331
+ fontFamily: 'Lato',
332
+ color: Theme.of(context).extension<CakeScrollbarTheme>()!.thumbColor,
333
+ ),
334
+ ),
335
+ ),
336
+ decoration: BoxDecoration(
337
+ borderRadius: BorderRadius.circular(6.0),
338
+ //border: Border.all(color: ),
339
+ color: Theme.of(context).extension<CakeScrollbarTheme>()!.trackColor,
340
+ ),
341
+ ),
342
+ ),
343
+ ],
344
+ ),
345
+ ),
346
+ ),
347
+ ],
348
+ );
349
+
350
return GestureDetector(
351
onTap: () {
253
- Navigator.of(context).pop();
352
+ if (widget.closeOnItemSelected) Navigator.of(context).pop();
353
onItemSelected(item!);
354
},
355
child: Container(
257
- height: 55,
356
+ height: isCustomItem ? 95 : 55,
357
color: Theme.of(context).dialogTheme.backgroundColor,
358
padding: EdgeInsets.symmetric(horizontal: 24),
260
- child: Row(
261
- mainAxisSize: MainAxisSize.max,
262
- mainAxisAlignment: widget.mainAxisAlignment,
263
- crossAxisAlignment: CrossAxisAlignment.center,
264
- children: <Widget>[
265
- image ?? Offstage(),
266
- Expanded(
267
- child: Padding(
268
- padding: EdgeInsets.only(left: image != null ? 12 : 0),
269
- child: Row(
270
- children: [
271
- Flexible(
272
- child: Text(
273
- widget.displayItem?.call(item) ?? item.toString(),
274
- softWrap: true,
275
- style: TextStyle(
276
- fontSize: 14,
277
- fontFamily: 'Lato',
278
- fontWeight: FontWeight.w600,
279
- color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
280
- decoration: TextDecoration.none,
281
- ),
282
- ),
283
- ),
284
- if (tag != null)
285
- Align(
286
- alignment: Alignment.topCenter,
287
- child: Container(
288
- width: 35.0,
289
- height: 18.0,
290
- child: Center(
291
- child: Text(
292
- tag,
293
- style: TextStyle(
294
- fontSize: 7.0,
295
- fontFamily: 'Lato',
296
- color:
297
- Theme.of(context).extension<CakeScrollbarTheme>()!.thumbColor,
298
- ),
299
- ),
300
- ),
301
- decoration: BoxDecoration(
302
- borderRadius: BorderRadius.circular(6.0),
303
- //border: Border.all(color: ),
304
- color: Theme.of(context).extension<CakeScrollbarTheme>()!.trackColor,
305
- ),
306
- ),
307
- ),
308
- ],
309
- ),
310
- ),
311
- ),
312
- ],
313
- ),
359
+ child: isCustomItem
360
+ ? Column(
361
+ mainAxisAlignment: MainAxisAlignment.spaceAround,
362
+ children: [
363
+ itemContent,
364
+ buildSlider(index: index, isActivated: widget.selectedAtIndex == index)
365
+ ],
366
+ )
367
+ : itemContent,
368
),
369
);
370
}
377
378
final image = images.isNotEmpty ? images[index] : icon;
379
326
- return GestureDetector(
327
- onTap: () {
328
- Navigator.of(context).pop();
329
- },
330
- child: Container(
331
- height: 55,
332
- color: Theme.of(context).dialogTheme.backgroundColor,
333
- padding: EdgeInsets.symmetric(horizontal: 24),
334
- child: Row(
335
- mainAxisSize: MainAxisSize.max,
336
- mainAxisAlignment: widget.mainAxisAlignment,
337
- crossAxisAlignment: CrossAxisAlignment.center,
338
- children: <Widget>[
339
- image ?? Offstage(),
340
- Expanded(
341
- child: Padding(
342
- padding: EdgeInsets.only(left: image != null ? 12 : 0),
343
- child: Row(
344
- children: [
345
- Flexible(
346
- child: Text(
347
- widget.displayItem?.call(item) ?? item.toString(),
348
- softWrap: true,
349
- style: TextStyle(
350
- fontSize: 16,
351
- fontFamily: 'Lato',
352
- fontWeight: FontWeight.w700,
353
- color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
354
- decoration: TextDecoration.none,
355
- ),
356
- ),
380
+ final isCustomItem = widget.customItemIndex != null && index == widget.customItemIndex;
381
+
382
+ final itemContent = Row(
383
+ mainAxisSize: MainAxisSize.max,
384
+ mainAxisAlignment: widget.mainAxisAlignment,
385
+ crossAxisAlignment: CrossAxisAlignment.center,
386
+ children: <Widget>[
387
+ image ?? Offstage(),
388
+ Expanded(
389
+ child: Padding(
390
+ padding: EdgeInsets.only(left: image != null ? 12 : 0),
391
+ child: Row(
392
+ children: [
393
+ Flexible(
394
+ child: Text(
395
+ widget.displayItem?.call(item) ?? item.toString(),
396
+ softWrap: true,
397
+ style: TextStyle(
398
+ fontSize: 16,
399
+ fontFamily: 'Lato',
400
+ fontWeight: FontWeight.w700,
401
+ color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
402
+ decoration: TextDecoration.none,
403
),
358
- if (tag != null)
359
- Align(
360
- alignment: Alignment.topCenter,
361
- child: Container(
362
- width: 35.0,
363
- height: 18.0,
364
- child: Center(
365
- child: Text(
366
- tag,
367
- style: TextStyle(
368
- fontSize: 7.0,
369
- fontFamily: 'Lato',
370
- color:
371
- Theme.of(context).extension<CakeScrollbarTheme>()!.thumbColor,
372
- ),
373
- ),
374
- ),
375
- decoration: BoxDecoration(
376
- borderRadius: BorderRadius.circular(6.0),
377
- //border: Border.all(color: ),
378
- color: Theme.of(context).extension<CakeScrollbarTheme>()!.trackColor,
404
+ ),
405
+ ),
406
+ if (tag != null)
407
+ Align(
408
+ alignment: Alignment.topCenter,
409
+ child: Container(
410
+ width: 35.0,
411
+ height: 18.0,
412
+ child: Center(
413
+ child: Text(
414
+ tag,
415
+ style: TextStyle(
416
+ fontSize: 7.0,
417
+ fontFamily: 'Lato',
418
+ color: Theme.of(context).extension<CakeScrollbarTheme>()!.thumbColor,
419
),
420
),
421
),
382
- ],
383
- ),
384
- ),
422
+ decoration: BoxDecoration(
423
+ borderRadius: BorderRadius.circular(6.0),
424
+ //border: Border.all(color: ),
425
+ color: Theme.of(context).extension<CakeScrollbarTheme>()!.trackColor,
426
+ ),
427
+ ),
428
+ ),
429
+ ],
430
),
386
- Icon(Icons.check_circle, color: Theme.of(context).primaryColor),
387
- ],
431
+ ),
432
),
433
+ Icon(Icons.check_circle, color: Theme.of(context).primaryColor),
434
+ ],
435
+ );
436
+
437
+ return GestureDetector(
438
+ onTap: () {
439
+ if (widget.closeOnItemSelected) Navigator.of(context).pop();
440
+ },
441
+ child: Container(
442
+ height: isCustomItem ? 95 : 55,
443
+ color: Theme.of(context).dialogTheme.backgroundColor,
444
+ padding: EdgeInsets.symmetric(horizontal: 24),
445
+ child: isCustomItem
446
+ ? Column(
447
+ mainAxisAlignment: MainAxisAlignment.spaceAround,
448
+ children: [
449
+ itemContent,
450
+ buildSlider(index: index, isActivated: widget.selectedAtIndex == index)
451
+ ],
452
+ )
453
+ : itemContent,
454
),
455
);
456
}
483
484
return null;
485
}
486
+
487
+ Widget buildSlider({required int index, required bool isActivated}) {
488
+ return Row(
489
+ children: <Widget>[
490
+ Expanded(
491
+ child: Slider(
492
+ value: widget.sliderValue ?? 1,
493
+ onChanged: isActivated ? widget.onSliderChanged : null,
494
+ min: 1,
495
+ max: 100,
496
+ divisions: 100,
497
+ ),
498
+ ),
499
+ ],
500
+ );
501
+ }
502
}