Os TextFields em ListView.builder estão desaparecendo
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
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.