skip to Main Content

I’m encountering an issue while working with my Flutter code. I’m trying to implement a ListView builder within a custom widget, but I’m getting an error message that says: ‘Expected a value of type ‘(Object) => Widget’, but got one of type ‘(String) => SizedBox’. Despite my attempts to adjust the function types, the error persists.

I’m encountering an issue in my Flutter application when using a ListView builder within a custom widget. The error message I’m receiving is: "Expected a value of type ‘(Object) => Widget’, but got one of type ‘(String) => SizedBox’." I’ve provided the code below to illustrate the problem. I’ve tried adjusting the types of functions, but the error persists. Could someone please help me understand and resolve this issue?

  const ContentDesktopAdminView({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final colors = context.colors;

    return Scaffold(
      body: SingleChildScrollView(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Container(
              height: max(560, 560),
              width: 1000,
              child: SingleChildScrollView(
                child: Column(
                  children: [
                    AnyPage(
                      articles: [
                        Article(
                          lastModified: DateTime.now(),
                          name: 'Something',
                        ),
                      ],
                    ),
                  ],
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}




class ListViewColumn<T> extends StatelessWidget {
  const ListViewColumn({
    required this.itemList,
    Key? key,
  }) : super(key: key);

  final List<ListModel<T>> itemList;

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Row(
          children: [
            ...itemList.map(
              (e) => Column(
                children: [
                  if (e.columnHeaderCell != null)
                    e.columnHeaderCell!(e.columnName ?? '')
                  else
                    Text(e.columnName ?? ''),
                  SizedBox(
                    width: 100.pw,
                    height: 100.pw,
                    child: ListView.builder(
                      itemCount: e.list.length,
                      itemBuilder: (BuildContext context, int index) =>
                          e.cell(e.list[index]),
                    ),
                  ),
                ],
              ),
            ),
          ],
        ),
      ],
    );
  }
}

class ListModel<T> {
  ListModel({
    required this.list,
    required this.cell,
    this.columnName,
    this.columnHeaderCell,
  });

  final String? columnName;
  final List<T> list;
  final Widget Function(T value) cell;
  final Widget Function(String value)? columnHeaderCell;
}

class AnyPage extends StatelessWidget {
  const AnyPage({required this.articles, Key? key}) : super(key: key);

  final List<Article> articles;

  @override
  Widget build(BuildContext context) {
    return ListViewColumn(
      itemList: [
        ListModel(
          list: articles.map((e) => e.name).toList(),
          columnName: 'Title',
          cell: (value) => SizedBox(
            height: 20,
            width: 100,
            child: Text(value),
          ),
        ),
        ListModel(
          list: articles.map((e) => e.lastModified).toList(),
          columnName: 'Last modified',
          cell: (value) => SizedBox(
            height: 20,
            width: 100,
            child: Text(value.toIso8601String()),
          ),
        ),
      ],
    );
  }
}

class Article {
  Article({
    required this.lastModified,
    required this.name,
  });

  final String name;
  final DateTime lastModified;
}

2

Answers


  1. Seems in the first place article is a class and you are trying to achieve a list view by hand. If you are trying to create a listview, use ListView.builder widget instead. You can check all types of listviews available here

    Listview types

    Assuming you can define a list of articles you may want to use something like this.

    ListView.builder(
                itemCount: articles.length,
                itemBuilder: (context, index) {
                   return MyCustomArticleWidget(article: articles[index]);
                },
    );
    

    As you can see I’m accessing each of the items and passing the article down MyCustomArticleWidget which is a widget that takes an article as parameter. You can define the stateless widget like this

    class MyCustomArticleWidget extends StatelessWidget {
    final Article article;
    
    const MyCustomArticleWidget({
    super.key,
    required this.article,
    });
    
    @override
    Widget build(BuildContext context) {
      return Text(article.name); 
      }
    }
    
    Login or Signup to reply.
  2. Stacktrace:

    the generic type of the two ListModel widgets in the itemList are different (one being String and the other is DateTime), hence the generic type of ListViewColumn will be Object which in its turn will enforce it’s child itemList to be List<ListModel<Object>> and the cell function will be Widget Function(Object value) cell and that’s the problem, since you can’t bind a Widget Function(<String> or <DateTime>) to a Widget Function(Object)

    easy solution:

    just remove all generic types (aka <T>), and use Widget Function(dynamic value) cell

    hard solution (but recommended):

    refactor you code so that itemList wont take different generic type, since that is the root of the problem

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search