[英]Generic Widget for ListView.builder
我尝试为 ListView 制作一个通用的 Stateful 小部件,主要思想是通过将数据定义为通用的方式将数据作为参数提供给 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'
════════════════════════════════════════════════════════════════════════════════════════════════════
那么,我做错了什么?
稍微重构并添加了一个示例。
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()),
);
},
),
),
);
}
}
可能是因为,您忘记在构造函数中将泛型类型从StatefulWidget
class 传递到State
class 。
尝试这个,
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
中,所有实例字段都应该是 final
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.