Les TextFields de ListView.builder disparaissent

Sep 02 2020

Pour faire un contrôle d'inventaire, je construis un ListView à partir de Firebase Data (une liste de "Alimentos") et un TextField pour éditer la quantité pour chaque "Alimento".

Cela fonctionne bien quand j'ai moins d'un écran de "Alimentos", mais quand j'ai quelques pages de "Alimentos", mes champs de texte disparaissent. Je comprends que cela se produit parce que ListView.builder ne construira que les éléments qui se trouvent dans ou près de la fenêtre (lorsque vous faites défiler), mais je ne sais pas comment le résoudre.

J'ai lu Textfield dans ListView.builder Post , où @Ashton Thomas suggère d'implémenter un widget personnalisé par ligne, mais je ne comprends pas comment l'obtenir.

Ceci est mon 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,));
            }
          },
      ),
    );
  }

Chaque ligne a un élément (_CrearItem) avec un TextField à sa fin (_cajaNum) comme suit:

  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) {
        },
      ),
    ); 
  }

Si mon ListView se reconstruit en continu au défilement, comment puis-je conserver les valeurs de TextFields?

MISE À JOUR

J'inclus des captures d'écran qui montrent des champs de texte "disparaissant" ...

Réponses

IqbalAbdurrazaq Dec 04 2020 at 16:54

ajouter la propriété TextFormField: initialValue. ça a marché pour moi, j'ai aussi vécu la même chose.

comme ça

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) {
    },
  ),

cause, votre champ de texte se reconstruit lorsque vous faites défiler et entrez le champ de texte suivant. mais vos données sont déjà stockées dans _controlList[i].cantControl.