Для каждого текстового поля необходимо указать отдельный контроллер.
Создать список контроллеров
List<TextEditingController> _quantityController = new List();
и используйте его в своем коде как
ListView.builder(
scrollDirection: Axis.vertical,
itemCount: (data != null) ? (data["items"].length) * 20 : 0,
itemBuilder: (BuildContext context, int index) {
_quantityController.add(new TextEditingController());
return Container(
child: Column(
children: <Widget>[
Container(
alignment: Alignment.topLeft,
width: double.infinity,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Container(
margin: const EdgeInsets.only(top: 8.0),
color: Colors.white,
child: ButtonTheme(
height: 16.0,
minWidth: 10.0,
child: RaisedButton(
padding: const EdgeInsets.all(4.0),
color: Colors.white,
child: Icon(Icons.remove, color: Colors.black,
size: 20.0,),
onPressed: ()=>_removeQuantity(index)
),
)
),
Container(
width: 60.0,
padding: const EdgeInsets.only(left: 1.0, right: 1.0),
child: Center(
child: TextField(
textAlign: TextAlign.center,
decoration: new InputDecoration(
hintText: "1",
),
keyboardType: TextInputType.number,
controller: _quantityController[index],
),
)
),
Container(
margin: const EdgeInsets.only(top: 8.0),
color: Colors.white,
child: ButtonTheme(
height: 16.0,
minWidth: 10.0,
child: RaisedButton(
padding: const EdgeInsets.all(4.0),
color: Colors.white,
child: Icon(
Icons.add, color: Colors.black, size: 20.0),
onPressed: ()=>_addQuantity(index),
),
),
),
],
),
),
],
),
);
},
);
Теперь ваша функция изменится на
void _addQuantity(int index){
setState(() {
quantity++;
_quantityController[index].text = '$quantity';
});
}
void _removeQuantity(int index){
setState(() {
if(quantity > 0){
quantity--;
}else{
quantity = 0;
}
_quantityController[index].text = '$quantity';
});
}
Не забудьте утилизировать весь контроллер в конце.