繁体   English   中英

ListView.builder 的通用小部件

[英]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
}

而且在上面,

  1. 您不需要@required注释。 它主要用于命名参数
  2. StatefulWidget中,所有实例字段都应该是 final

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM