Leon_sooter
Leon_sooter

Reputation: 23

Return Type isn't a Widget: SetState Problem

I have a Problem updating my Page: I want to include a StatelessWidget with an itemBuilder in my Page. The Widget builds a ListView out of Cards. A LongPress should delete a card and update the Page, but it isn't updating. This can't happen because it's a stateless Widget.

I already tried making the StatlessWidget into a StatefullWidget, but in the itemBuilder i get an Error saying that the return type "ProductList(..)" isn't a Widget

List<String> artikelNamen = [];
List<int> barcodes = [];

class WiederaufnahmePage extends StatefulWidget {
  @override
  _WiederaufnahmePageState createState() => _WiederaufnahmePageState();
}

class ProductList extends StatelessWidget {
  final String artb;
  final int brcde;
  final int indx;

  ProductList(this.artb, this.brcde, this.indx);

  @override
  Widget build(BuildContext context) {
    return new Card(
        child: ListTile(
          title: Text(artb,
          style: TextStyle(fontWeight: FontWeight.w500, fontSize: 20)),
          subtitle: Text(brcde.toString()),
          leading: Icon(
            Icons.fastfood,
            color: Colors.blue[500],
          ),
          trailing: Icon(Icons.keyboard_arrow_right),
          onTap: () {
            Navigator.pushNamed(context, "/BarcodePage");
          },
          onLongPress: () {
            _showSnackBar(artb);
            artikelNamen.removeAt(indx);
            barcodes.removeAt(indx);
            //setState(() {}); //This isn't working bc StatelessWidget
         },
    ));
  }
}

class _WiederaufnahmePageState extends State<WiederaufnahmePage> {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
           child: Expanded(
              child: SizedBox(
                  height: 200.0,
                  child: new ListView.builder(
                    reverse: false,
                    itemBuilder: (_, int index) => ProductList(
                        artikelNamen[index], barcodes[index], index),
                    itemCount: artikelNamen.length,
                  )
              )),
          ))
  }   
}

I don't know how to solve this problem. The showed Code is the actual working code, i would like to implement that after each LongPress on a ListTile the whole Page is updated so the deleted Tile isn't visible anymore.

Upvotes: 2

Views: 7797

Answers (1)

fvillalba
fvillalba

Reputation: 1058

First of all is a good practice move the variable code to the state of the StatefulWidget, in this case artikelNamen and barcodes should not be accessed by ProductList.

After that, change the StatelessWidget to receive a callback function for onLongPress and and assign it to the card. Then you can move the onLongPress function to the StatefulWidget (calling setState) and pass it as parameter to stateless widget.

You can try something like this:

import 'package:flutter/material.dart';

class WiederaufnahmePage extends StatefulWidget {
  @override
  _WiederaufnahmePageState createState() => _WiederaufnahmePageState();
}

class _WiederaufnahmePageState extends State<WiederaufnahmePage> {
  List<String> artikelNamen = ['item 1', 'item 2', 'item 3'];
  List<int> barcodes = [0, 1, 2];
  @override
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.all(8.0),
      child: ListView.builder(
        reverse: false,
        itemBuilder: (BuildContext context, int index) => ProductList(
            artikelNamen[index], barcodes[index], () => onLongPress(index)),
        itemCount: artikelNamen.length,
      ),
    );
  }

  void onLongPress(int indx) {
    //_showSnackBar(artb);
    setState(() {
      artikelNamen.removeAt(indx);
      barcodes.removeAt(indx);
    });
  }
}

class ProductList extends StatelessWidget {
  final String artb;
  final int brcde;
  final onLongPress;

  ProductList(this.artb, this.brcde, this.onLongPress);

  @override
  Widget build(BuildContext context) {
    return new Card(
        child: ListTile(
      title: Text(artb,
          style: TextStyle(fontWeight: FontWeight.w500, fontSize: 20)),
      subtitle: Text(brcde.toString()),
      leading: Icon(
        Icons.fastfood,
        color: Colors.blue[500],
      ),
      trailing: Icon(Icons.keyboard_arrow_right),
      onTap: () {
        Navigator.pushNamed(context, "/BarcodePage");
      },
      onLongPress: onLongPress,
    ));
  }
}

Upvotes: 3

Related Questions