Context:
I created my own wrapper for CupertinoSlidingSegmentedControl with the help of a generic item builder.
The primary purpose of this is to group alot of similiar functionality with the addition of an easy to use "custom item builder" if I want additional icons, etc in the slider items.
I wish to make this generic using a custom typedef generic function as my item builder, I define like this:
Problem:
The problem I have is as follows:
typedef ItemValueWidgetBuilder<T> = Widget Function(BuildContext context, T key, bool active);
According to this post, my function (interface) is implemented correctly;
My implementation results in:
(BuildContext context, SexualPreference key, bool active) => Widget (*Text specifically*)
Shown the error below, I am unable to use this.
The following _TypeError was thrown building SegmentedSlider<SexualPreference>(dirty, dependencies: [_LocalizationsScope-[GlobalKey#f3e39], _InheritedTheme], state: _SegmentedSliderState<SexualPreference>#ab773):
type '(BuildContext, SexualPreference, bool) => Text' is not a subtype of type '(BuildContext, dynamic, bool) => Widget'
Question:
The only way I can get it (typedef + generics) to work is removing any trace of generics which is quite pointless.
What am I missing/doing wrong?
======== Exception caught by widgets library =======================================================
The following _TypeError was thrown building SegmentedSlider<SexualPreference>(dirty, dependencies: [_LocalizationsScope-[GlobalKey#f3e39], _InheritedTheme], state: _SegmentedSliderState<SexualPreference>#ab773):
type '(BuildContext, SexualPreference, bool) => Text' is not a subtype of type '(BuildContext, dynamic, bool) => Widget'
The relevant error-causing widget was:
SegmentedSlider<SexualPreference> file:///...mobile-flutter/lib/viewcontrollers/register/user/ui_register_details.dart:197:11
When the exception was thrown, this was the stack:
#0 _SegmentedSliderState.build.<anonymous closure> (package:my-awesome-app/framework/ui/components/slider.dart:35:28)
#1 MappedListIterable.elementAt (dart:_internal/iterable.dart:412:31)
#2 ListIterator.moveNext (dart:_internal/iterable.dart:341:26)
#3 MapMixin.addEntries (dart:collection/maps.dart:177:23)
#4 new Map.fromEntries (dart:core/map.dart:182:17)
CupertinoSlider wrapper usage example:
SegmentedSlider<SexualPreference>(
thumbColor: themeService.getAccentSwatchTheme(),
onValueChanged: (value) {
profile!.preferences.sexualOrientation = value!;
profileRef.update(profile!.toJson());
setState(() {});
},
itemBuilder: (context, key, active) => Text(
SexualPreferenceExt.asString(key),
style: Theme.of(context).textTheme.subtitle2!.copyWith(
color: active
? Colors.white
: themeService.getAccentSwatchTheme(),
),
),
selectedValue: SexualPreference.None,
values: SexualPreference.values
),
CupertinoSlider wrapper code:
// typedef ItemValueWidgetBuilder<T> = Widget Function(BuildContext context, T key, bool active);
class SegmentedSlider<T> extends StatefulWidget {
final Color backgroundColor;
final Color thumbColor;
final ValueChanged<T?> onValueChanged;
final T selectedValue;
final List<T> values;
final ItemValueWidgetBuilder<T> itemBuilder;
const SegmentedSlider({Key? key, this.thumbColor = Colors.grey, this.backgroundColor = Colors.white, required this.onValueChanged, required this.itemBuilder, required this.selectedValue, required this.values}) : super(key: key);
@override
_SegmentedSliderState<T> createState() => new _SegmentedSliderState<T>();
}
class _SegmentedSliderState<T> extends State<SegmentedSlider> {
late T activeValue;
@override
void initState() {
// TODO: implement initState
super.initState();
activeValue = widget.selectedValue;
}
@override
Widget build(BuildContext context) {
var map = widget.values.map((e) {
var _widget = widget.itemBuilder(context, e, e == activeValue);
print(_widget);
return MapEntry<T, Widget>(e, _widget);
});
Map<T, Widget> children = Map.fromEntries(map);
return CupertinoSlidingSegmentedControl<T>(
backgroundColor: widget.backgroundColor,
thumbColor: widget.thumbColor,
onValueChanged: (value) {
activeValue = value!;
widget.onValueChanged(value);
},
children: children,
groupValue: widget.selectedValue,
);
}
}