我试图为ListView制作一个通用的有状态小部件,主要思想是通过将数据定义为通用的,从而将数据作为参数提供给ListView。
class DynamicListView<T> extends StatefulWidget {
Axis direction = Axis.vertical;
int defaultSelectedIndex = 0;
final List<T> data;
final Widget Function(T, bool) item;
DynamicListView(@required this.data, @required this.item, {this.direction, this.defaultSelectedIndex});
@override
_DynamicListViewState createState() => _DynamicListViewState();
}
class _DynamicListViewState<T> extends State<DynamicListView> {
int _selectedIndex;
Widget Function(T, bool) item;
@override
void initState() {
super.initState();
this._selectedIndex = widget.defaultSelectedIndex;
}
@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: widget.data.length,
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) {
return GestureDetector(
onTap: () {
setState(() {
_selectedIndex = index;
});
},
child: widget.item(widget.data[index], _selectedIndex == index));
}
);
}
}
我正在使用DynamicListView,如下所示: 1-对于DateTime数据
DynamicListView<DateTime>(dates,
(date, isActive) => DateItem(dateTime: date,isActive: isActive,),
defaultSelectedIndex: 0,
2-对于字符串数据
DynamicListView<String>(leagues,
(name, isActive) => TextItem(name: name, isActive: isActive,),
defaultSelectedIndex: 0,
),
但我遇到以下异常:
════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
The following _TypeError was thrown building:
type '(String, bool) => TextItem' is not a subtype of type '(dynamic, bool) => Widget'
When the exception was thrown, this was the stack:
#0 _DynamicListViewState.build.<anonymous closure> (package:app/src/screens/home/Test.dart:143:29)
#1 SliverChildBuilderDelegate.build (package:flutter/src/widgets/sliver.dart:446:22)
#2 SliverMultiBoxAdaptorElement._build.<anonymous closure> (package:flutter/src/widgets/sliver.dart:1134:67)
#3 _HashMap.putIfAbsent (dart:collection-patch/collection_patch.dart:139:29)
#4 SliverMultiBoxAdaptorElement._build (package:flutter/src/widgets/sliver.dart:1134:26)
...
════════════════════════════════════════════════════════════════════════════════════════════════════
════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
type '(DateTime, bool) => DateItem' is not a subtype of type '(dynamic, bool) => Widget'
════════════════════════════════════════════════════════════════════════════════════════════════════
那么,我做错了什么?
答案 0 :(得分:1)
重构一点并添加示例。
import 'package:flutter/material.dart';
typedef ItemBuilder<T> = Widget Function(T item, bool isSelected);
class DynamicListView<T> extends StatefulWidget {
final Axis axis;
final List<T> data;
final int defaultSelectedIndex;
final ItemBuilder<T> itemBuilder;
const DynamicListView({
@required this.data,
this.axis = Axis.vertical,
@required this.itemBuilder,
this.defaultSelectedIndex = 0,
}) : assert(data != null),
assert(itemBuilder != null);
@override
_DynamicListViewState createState() => _DynamicListViewState();
}
class _DynamicListViewState<T> extends State<DynamicListView<T>> {
int _selectedIndex;
@override
Widget build(BuildContext context) {
return ListView.builder(
scrollDirection: widget.axis,
itemCount: widget.data.length,
itemBuilder: (context, index) {
return GestureDetector(
onTap: () => setState(() => _selectedIndex = index),
child: Container(
width: 200,
height: 200,
color: Colors.blue[index * 100],
child: widget.itemBuilder(
widget.data[index],
index == _selectedIndex,
),
),
);
},
);
}
}
class ExampleNumberList extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: DynamicListView(
data: [1, 2, 3],
itemBuilder: (item, isSelected) {
return Container(
color: isSelected ? Colors.red : Colors.green,
child: Text(item.toString()),
);
},
),
),
);
}
}
答案 1 :(得分:0)
可能是因为,您忘记了将泛型从构造器中的StatefulWidget
类传递给State
类。
尝试一下,
class DynamicListView<T> extends StatefulWidget {
Axis direction = Axis.vertical;
int defaultSelectedIndex = 0;
final List<T> data;
final Widget Function(T, bool) item;
DynamicListView(this.data, this.item, {this.direction, this.defaultSelectedIndex});
@override
_DynamicListViewState<T> createState() => _DynamicListViewState<T>(); //TODO: Change here
}
也是在上面
@required
注释。它主要用于命名参数StatefulWidget
中,所有实例字段都应为最终字段