To do an Inventory Control, I'm building a ListView from Firebase Data (a list of "Alimentos") and a TextField to edit the quantity for each "Alimento".
It's working fine when I have less than a screen of "Alimentos", but when I have some pages of "Alimentos", my textfields are disappearing. I understand it happens because ListView.builder is only going to build the items that are in or near the viewport (as you scroll), but I don't know how to solve it.
I read Textfield in ListView.builder Post, where @Ashton Thomas suggests to implemment a Custom Widget per Row, but I don't understand how to get that.
This is my 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,));
}
},
),
);
}
Each row has an Item (_CrearItem) with an a TextField on its trailing (_cajaNum) as following:
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) {
},
),
);
}
If my ListView continuously rebuilds on scroll, how can I keep the values of TextFields?
UPDATE
I include screenshots that show textfields "disappearing"...
add property TextFormField :
initialValue
. its worked for me, I also experienced the same thing.like this
cause, your textfield rebuild when you scroll and input next texfield. but your data is already stored in
_controlList[i].cantControl
.