Os TextFields em ListView.builder estão desaparecendo

Sep 02 2020

Para fazer um Inventory Control, estou construindo um ListView a partir do Firebase Data (uma lista de "Alimentos") e um TextField para editar a quantidade de cada "Alimento".

Está funcionando bem quando tenho menos de uma tela de "Alimentos", mas quando tenho algumas páginas de "Alimentos", meus campos de texto desaparecem. Eu entendo que isso acontece porque ListView.builder só vai construir os itens que estão dentro ou perto da viewport (enquanto você rola), mas eu não sei como resolvê-lo.

Eu li Textfield em ListView.builder Post , onde @Ashton Thomas sugere implementar um widget personalizado por linha, mas não entendo como fazer isso.

Este é o meu ListView.Builder...

  Widget _crearListado(BuildContext context, AlimentoBloc alimentoBloc) {

    final _size = MediaQuery.of(context).size;

    return Container(
      height: _size.height * 0.5,
      child: StreamBuilder(
          stream: alimentoBloc.alimentoStream ,
          builder: (BuildContext context, AsyncSnapshot<List<AlimentoModel>> snapshot){
            if (snapshot.hasData) {
              List<AlimentoModel> alimentos = snapshot.data;
              alimentos.sort((a, b) => a.proteina.compareTo(b.proteina));
              return Stack(
                children: <Widget>[
                  ListView.builder(
                    itemCount: alimentos.length,
                    itemBuilder: (context, i) { //Esta variable es gráfica, sólo se crea para lo que se está viendo
                      _controlList.add(new ControlInventarioModel());
                      return _crearItem(context, alimentoBloc, alimentos[i], i);
                    },

                    padding: EdgeInsets.only(left: 10.0, right: 10.0, top: 0.0, bottom: 20.0),
                  ),
                ],
              );
            } else {
              return Center (child: Image(image: AssetImage('assets/Aplians-fish-Preloader.gif'), height: 200.0,));
            }
          },
      ),
    );
  }

Cada linha tem um Item (_CrearItem) com um TextField em seu final (_cajaNum) da seguinte forma:

  Widget _crearItem(BuildContext context, AlimentoBloc alimentoBloc, AlimentoModel alimento, int i) {

      return Card(
        color: Colors.grey[200], //color de la tarjeta
        elevation: 0.0, //sin sombra
        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15.0)),
        child: ListTile(
            title: Text('${alimento.nombre}', style: TextStyle(color: Theme.of(context).primaryColor, fontSize: 18.0)), subtitle: Text ('${alimento.fabricante}'), //refLoteActual
            onTap: () {},
            leading: Icon(FontAwesomeIcons.shoppingBag, color: Theme.of(context).accentColor),
            trailing: _cajaNum(context, i, alimento.idAlimento),// nuevoControlador),
        ),
      );
  }

  Widget _cajaNum(BuildContext context, int i, String idAlimento){    
    return Container(
      width: 100.0,
      height: 40.0,
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(10.0),
      ),
      child: TextField(
        style: TextStyle(fontSize: 20.0),
        textAlign: TextAlign.center,
        keyboardType: TextInputType.numberWithOptions(),//decimal:false, signed: false),
        inputFormatters: <TextInputFormatter>[
              FilteringTextInputFormatter.allow(RegExp(r'^(\d+)?\.?\d{0,2}')),
              FilteringTextInputFormatter.singleLineFormatter,
            ],
        maxLength: 5,
        onChanged: (value) {
                if(utils.isNumeric(value) && double.parse(value)>=0) {
                  _controlList[i].cantControl = double.parse(value);
                } 
                else {
                  _controlList[i].cantControl = null;
                }
                },
        onEditingComplete: () {
          FocusScope.of(context).unfocus();
        },
        onSubmitted: (value) {
        },
      ),
    ); 
  }

Se meu ListView for recriado continuamente na rolagem, como posso manter os valores de TextFields?

ATUALIZAR

Incluo capturas de tela que mostram campos de texto "desaparecendo" ...

Respostas

IqbalAbdurrazaq Dec 04 2020 at 16:54

adicione a propriedade TextFormField : initialValue. funcionou para mim, eu também experimentei a mesma coisa.

assim

TextField(
    style: TextStyle(fontSize: 20.0),
    initialValue: _controlList[i].cantControll ?? '0',
    onChanged: (value) {
            if(utils.isNumeric(value) && double.parse(value)>=0) {
              _controlList[i].cantControl = double.parse(value);
            } 
            else {
              _controlList[i].cantControl = null;
            }
            },
    onEditingComplete: () {
      FocusScope.of(context).unfocus();
    },
    onSubmitted: (value) {
    },
  ),

causa, seu campo de texto é reconstruído quando você rola e insere o próximo campo de texto. mas seus dados já estão armazenados em _controlList[i].cantControl.