Related
How would one make a centered content container like this in Flutter?:
.container {
margin-left: auto;
margin-right: auto;
width: 100%;
max-width: 600px;
background-color: red;
height: 100vh;
}
<div class="container">
Hello inside container
</div>
I have tried this, but it just overflows instead of fitting to the width of the screen once the application is smaller than the maxWidth.
import "package:flutter/material.dart";
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Theme.of(context).colorScheme.background,
body: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: double.infinity,
color: Colors.red,
constraints: const BoxConstraints(maxWidth: 800),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Text(
"Hello inside container",
style: TextStyle(fontSize: 40),
),
],
),
),
],
));
}
}
Try below code wrap your Column inside Expanded or Flexible
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
child: Container(
width: double.infinity,
color: Colors.red,
constraints: const BoxConstraints(maxWidth: 800),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Text(
"Hello inside container",
style: TextStyle(fontSize: 40),
),
],
),
),
),
],
),
You can use MediaQuery.of(context).size.width as width. It gives you the full width of screen. Also Limit max width of Container in Flutter have a look at this.
I am trying to filter out the results of the data from a REST api but do not seem to have an understanding of how to go about it. Basically, what I am trying to achieve is that I want to have a single class that gets all my events data from the api and using different classes, be able to retrieve specific data by filtering the data from the original events class.
Below is my code:
late Future<List<EntertainerEvent>> _fetchEvents;
#override
void initState() {
_fetchEvents = _authAPI.fetchEvents();
super.initState();
}
#override
Widget build(BuildContext context) {
return FutureBuilder<List<EntertainerEvent>>(
future: _fetchEvents,
builder: (BuildContext context, AsyncSnapshot snapshot) {
var childCount = 0;
if (snapshot.connectionState != ConnectionState.done) {
childCount = 1;
} else {
childCount = snapshot.data.length;
}
return SliverList(
delegate: SliverChildBuilderDelegate((context, index) {
if (snapshot.hasData) {
List<EntertainerEvent> someData = snapshot.data;
return InkWell(
child: Container(
height: 380.0,
color: const Color(0xFF00001A),
child: Container(
padding: const EdgeInsets.all(0.0),
margin: const EdgeInsets.all(30.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(4.0)),
boxShadow: [
BoxShadow(
color: Color(0xFF0492C2),
blurRadius: 10,
offset: Offset(0, 0),
),
],
color: Colors.white,
),
child: Stack(
children: <Widget>[
Align(
alignment: Alignment.topCenter,
child: Padding(
padding: const EdgeInsets.all(0.0),
child: Container(
width: MediaQuery.of(context).size.width,
height: 210,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(4.0),
topRight: Radius.circular(4.0),
bottomLeft: Radius.circular(0.0),
bottomRight: Radius.circular(0.0)),
image: DecorationImage(
fit: BoxFit.cover,
image: DecorationImage(
fit: BoxFit.cover,
image: new NetworkImage(
_authAPI.mediaPath +
someData[index].imagePoster)),
),
),
),
),
Align(
alignment: Alignment.bottomCenter,
child: Padding(
padding: const EdgeInsets.all(0.0),
child: Container(
width: MediaQuery.of(context).size.width,
height: 120,
child: Container(
padding: const EdgeInsets.all(10),
child: Row(
children: [
Expanded(
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Container(
padding: const EdgeInsets.only(
top: 10.0, bottom: 0.0),
child: Text(
someData[index]
.eventName
.toUpperCase(),
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15,
fontFamily: 'Nunito',
),
overflow:
TextOverflow.ellipsis,
softWrap: true,
maxLines: 1,
),
),
Container(
padding: const EdgeInsets.only(
top: 6.0, bottom: 0.0),
child: Text(
someData[index].eventTypeId ==
3
? 'Online Location'
: someData[index].suburb +
', ' +
someData[index].city +
', ' +
someData[index]
.province,
style: TextStyle(
color: Colors.black26,
),
overflow:
TextOverflow.ellipsis,
softWrap: true,
maxLines: 1,
),
),
Container(
padding:
EdgeInsets.only(top: 0.0),
child: Row(
mainAxisAlignment:
MainAxisAlignment
.spaceBetween,
children: [
Text(
_startDate(
someData[index])
.toString()
.toUpperCase(),
style: TextStyle(
color: Colors.red,
fontWeight:
FontWeight.bold,
fontSize: 10,
),
),
FavouriteWidget(
entEvent:
someData[index]),
IconButton(
icon: Icon(Icons.share),
onPressed: () {
Share.share(//Do Something);
},
),
],
),
),
],
),
),
],
),
),
),
),
),
],
),
),
),
onTap: () async {
Navigator.push(context,
MaterialPageRoute(builder: (BuildContext context) {
return EventDetails(
entEvent: someData[index],
isFavourited: _isFavourited);
}));
},
);
} else if (snapshot.hasError) {
return AlertDialog(
title: Text(
'An Error Occured!',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.redAccent,
),
),
content: Text(
"${snapshot.error}",
style: TextStyle(
color: Colors.blueAccent,
),
),
actions: <Widget>[
TextButton(
child: Text(
'Go Back',
style: TextStyle(
color: Colors.redAccent,
),
),
onPressed: () {
Navigator.of(context).pop();
},
)
],
);
} else {
return Center(
child: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height / 1.3,
child: Center(
child:
CircularProgressIndicator(color: Color(0xFFFFA500)),
),
),
);
}
}, childCount: childCount),
);
});
Bare in mind that in my HomePage(), I am calling this class using the code below:
return Container(
color: Color(0xFF00001A),
child: SafeArea(
top: false,
bottom: false,
child: Builder(
// This Builder is needed to provide a BuildContext that is
// "inside" the NestedScrollView, so that
// sliverOverlapAbsorberHandleFor() can find the
// NestedScrollView.
builder: (BuildContext context) {
return CustomScrollView(
// The "controller" and "primary" members should be left
// unset, so that the NestedScrollView can control this
// inner scroll view.
slivers: <Widget>[
SliverOverlapInjector(
// This is the flip side of the SliverOverlapAbsorber
// above.
handle:
NestedScrollView.sliverOverlapAbsorberHandleFor(context),
),
EventList(),
],
);
},
),
),
);
Thank you in advance.
if I'm understanding you right just do this for example:
if(someData[index].eventTypeId == '1'){
return SizedBox();
}
else{
return InkWell( ....
}
I have a search bar that queries a listview(JSON) to get likely close input text from the listview(JSON) for some reason my horizontal listview hide in the right side and won't show until I start typing on the search bar textfield and when it shows it won't show fully but partly and the rest list still hiding at the right side of my device screen. Below is my code and attached is my screenshot:
Container(
height: 120,
// width: 150,
child: ListView.builder(
scrollDirection: Axis.horizontal,
// padding: EdgeInsets.all(5.0),
itemCount: _notesForDisplay.length+1,
itemBuilder: (context, position) {
return position == 0 ? _searchBar() : _listItem(position-1);
}
)),
_listItem(position) {
return InkWell(
onTap: (){
_myFeatureSelection = position.toString();
debugPrint("myfeat:$_myFeatureSelection");
//_fetchFeaturePickedList();
_fetchComment();
},
child:Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Card(
semanticContainer: true,
clipBehavior: Clip.antiAliasWithSaveLayer,
child: Stack(
children: <Widget>[
Image.network(_notesForDisplay[position].img_link,
width: 120, height: 100, fit: BoxFit.cover),
/*Positioned(
// top: 16,
//left: 140,
child: Container(
height: 25,
width: 80,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5.0),
color: Colors.black, //Color(0xff0F0F0F),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.3),
)
]),
child: Center(
child: Text(
_notesForDisplay[position].title,
style: TextStyle(color: Colors.white),
),
),
))*/
],
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5.0)),
elevation: 5,
//margin: EdgeInsets.all(10),
),
// _FeatureText(featurePhoto.title,16),
//_FeatureText(featurePhoto.subtitle,12),
]));}
_searchBar() {
return
Container(
width: 240,
child: Align(
alignment: Alignment.center,
child: TextField(
//controller: searchController,
cursorColor: Colors.white,
style: TextStyle(color: Colors.white,fontSize: 12,
fontFamily: 'Montserrat'),
decoration: InputDecoration(
border: InputBorder.none,
prefixIcon: Icon(
Icons.search,
color: Colors.white,
size: 15,
),
hintStyle: TextStyle(
color: Colors.white,
fontSize: 12,
fontFamily: 'Montserrat'),
//alignLabelWithHint: true,
hintText: "Search...",//contentPadding: EdgeInsets.only(top: 2),
),
onChanged: (text) {
text = text.toLowerCase();
setState(() {
_notesForDisplay = feature.where((note) {
var noteTitle = note.title.toLowerCase();
return noteTitle.contains(text);
}).toList();
});
},
),
));
}
This is a problem associated with using column widget. to solve this, simply wrap the column with the SingleChildScrollView widget. it will solve the problem instantly
I have a signup page where i am making a http.post request to the server by passing the parameters email,username,password,firstname and lastname. I have tried everything but couldn't solve the problem. Whenever i tap on the signup button it says the following--
"I/flutter ( 2914): 400
I/flutter ( 2914): {"code":"rest_missing_callback_param","message":"Missing parameter(s): email, username, password","data":{"status":400,"params":["email","username","password"]}}"
I have gone through other posts but they didnt solve my problem so please help.
Thanks in advance.
import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:restaurant_app/globalVar.dart';
import 'package:restaurant_app/homescreen.dart';
class SignUp extends StatefulWidget {
#override
_SignUpState createState() => _SignUpState();
}
class _SignUpState extends State<SignUp> with SingleTickerProviderStateMixin
{
TabController controller;
TextEditingController _firstnameController;
TextEditingController _lastnameController;
TextEditingController _usernameController;
TextEditingController _emailController;
TextEditingController _passwordController;
TextEditingController _rePasswordController;
bool loading;
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>
();
#override
void initState() {
// TODO: implement initState
super.initState();
controller = new TabController(length: 2, vsync: this);
loading = false;
_firstnameController = new TextEditingController(text: "Vishal");
_lastnameController = new TextEditingController(text: "Das");
_usernameController = new TextEditingController(text: "vishaldas");
_emailController = new TextEditingController(text: "vissudas#gmail.com");
_passwordController = new TextEditingController(text: "Vishal#123");
_rePasswordController = new TextEditingController(text: "Vishal#123");
}
#override
void dispose() {
// TODO: implement dispose
super.dispose();
controller.dispose();
setState(() {
loading = false;
});
_emailController.dispose();
_usernameController.dispose();
_passwordController.dispose();
_firstnameController.dispose();
_lastnameController.dispose();
_rePasswordController.dispose();
}
// static final String fullnameKey = 'fullname';
// static final String emailKey = 'email';
// static final String passwordkey = 'password';
signUp(email, username, password, firstname, lastname) async {
setState(() {
loading = true;
});
var body = json.encode({
"email": email,
"username": username,
"password": password,
"firstname": firstname,
"lastname": lastname,
});
String basicAuth =
'Basic' + base64Encode(utf8.encode('$username:$password'));
Map<String, String> headers = {
HttpHeaders.AUTHORIZATION: basicAuth,
};
print(basicAuth);
await http
.post("${GlobalVar.url}wp-json/wc/v2/customers",
body: body, headers: headers)
.then((response) {
var body = json.decode(response.body);
print(response.statusCode);
print(response.body);
if (response.statusCode == 200) {
loading = false;
Navigator.pushReplacement(context,
MaterialPageRoute(builder: (BuildContext ctx) => HomePage()));
} else {
final snackBar = SnackBar(content: Text(body['message']));
_scaffoldKey.currentState.showSnackBar(snackBar);
}
setState(() {
loading = false;
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomPadding: false,
key: _scaffoldKey,
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('images/art.png'),
fit: BoxFit.fill,
colorFilter: ColorFilter.mode(
Colors.white12.withOpacity(0.2), BlendMode.dstATop),
),
),
child: ListView(
shrinkWrap: true,
physics: BouncingScrollPhysics(),
children: <Widget>[
SizedBox(
height: MediaQuery.of(context).size.height / 35,
),
Align(
alignment: Alignment.topCenter,
child: CircleAvatar(
backgroundColor: Colors.grey,
radius: 55.0,
backgroundImage: AssetImage('images/logo.png'),
),
),
SizedBox(
height: MediaQuery.of(context).size.height / 40,
),
Stack(
alignment: Alignment.center,
children: <Widget>[
SizedBox(
height: 2.0,
child: new Center(
child: new Container(
height: 10.0,
color: Colors.black12,
),
),
),
Row(
children: <Widget>[
SizedBox(
width: MediaQuery.of(context).size.width / 4,
),
Chip(
label: Text(
"SIGN IN",
style: TextStyle(color: Colors.white, fontSize: 18.0),
),
backgroundColor: Color(0xFFD1A155),
),
SizedBox(
width: MediaQuery.of(context).size.width / 35,
child: Container(
width: MediaQuery.of(context).size.height / 12,
height: 2.0,
color: Colors.white,
),
),
Chip(
label: Text(
"SIGN UP",
style: TextStyle(color: Colors.white, fontSize: 18.0),
),
backgroundColor: Colors.black87,
),
],
)
],
),
SizedBox(
height: MediaQuery.of(context).size.height / 30,
),
Align(
alignment: Alignment.center,
child: Text(
"Sign Up Maa ki Rasoi",
style: TextStyle(
fontSize: 20.0,
color: Color(0xFFD1A155),
),
)),
SizedBox(
height: MediaQuery.of(context).size.height / 30,
),
Column(
children: <Widget>[
Theme(
data: ThemeData(
hintColor: Colors.black26,
primaryColor: Color(0xFFD1A155),
),
child: Padding(
padding: const EdgeInsets.only(left: 15.0, right: 15.0),
child: TextField(
controller: _firstnameController,
decoration: InputDecoration(
border: OutlineInputBorder(borderSide: BorderSide()),
prefixIcon: Icon(
Icons.person,
color: Color(0xFFD1A155),
),
hintText: 'First name',
hintStyle: TextStyle(
color: Colors.black,
fontWeight: FontWeight.w400)),
keyboardType: TextInputType.text,
),
),
),
SizedBox(
height: MediaQuery.of(context).size.height / 50,
),
Theme(
data: ThemeData(
hintColor: Colors.black26,
primaryColor: Color(0xFFD1A155),
),
child: Padding(
padding: const EdgeInsets.only(left: 15.0, right: 15.0),
child: TextField(
controller: _lastnameController,
decoration: InputDecoration(
border: OutlineInputBorder(borderSide: BorderSide()),
prefixIcon: Icon(
Icons.person,
color: Color(0xFFD1A155),
),
hintText: 'Last name',
hintStyle: TextStyle(
color: Colors.black,
fontWeight: FontWeight.w400)),
keyboardType: TextInputType.text,
),
),
),
SizedBox(
height: MediaQuery.of(context).size.height / 50,
),
Theme(
data: ThemeData(
primaryColor: Color(0xFFD1A155),
hintColor: Colors.black26),
child: Padding(
padding: const EdgeInsets.only(left: 15.0, right: 15.0),
child: TextField(
controller: _emailController,
decoration: InputDecoration(
border: OutlineInputBorder(borderSide: BorderSide()),
prefixIcon: Icon(
Icons.email,
color: Color(0xFFD1A155),
),
hintText: 'Email Address',
hintStyle: TextStyle(
color: Colors.black,
fontWeight: FontWeight.w400)),
keyboardType: TextInputType.emailAddress,
),
),
),
SizedBox(
height: MediaQuery.of(context).size.height / 50,
),
Theme(
data: ThemeData(
hintColor: Colors.black26,
primaryColor: Color(0xFFD1A155),
),
child: Padding(
padding: const EdgeInsets.only(left: 15.0, right: 15.0),
child: TextField(
controller: _usernameController,
decoration: InputDecoration(
border: OutlineInputBorder(borderSide: BorderSide()),
prefixIcon: Icon(
Icons.supervised_user_circle,
color: Color(0xFFD1A155),
),
hintText: 'Username',
hintStyle: TextStyle(
color: Colors.black,
fontWeight: FontWeight.w400)),
keyboardType: TextInputType.text,
),
),
),
SizedBox(
height: MediaQuery.of(context).size.height / 50,
),
Theme(
data: ThemeData(
hintColor: Colors.black26,
primaryColor: Color(0xFFD1A155),
),
child: Padding(
padding: const EdgeInsets.only(left: 15.0, right: 15.0),
child: TextField(
controller: _passwordController,
decoration: InputDecoration(
border: OutlineInputBorder(borderSide: BorderSide()),
prefixIcon: Icon(
Icons.lock,
color: Color(0xFFD1A155),
),
hintText: 'Password',
hintStyle: TextStyle(
color: Colors.black,
fontWeight: FontWeight.w400)),
keyboardType: TextInputType.text,
obscureText: true,
),
),
),
SizedBox(
height: MediaQuery.of(context).size.height / 50,
),
Theme(
data: ThemeData(
primaryColor: Color(0xFFD1A155),
hintColor: Colors.black26),
child: Padding(
padding: const EdgeInsets.only(left: 15.0, right: 15.0),
child: TextField(
controller: _rePasswordController,
decoration: InputDecoration(
border: OutlineInputBorder(borderSide: BorderSide()),
prefixIcon: Icon(
Icons.lock,
color: Color(0xFFD1A155),
),
hintText: 'Re - Password',
hintStyle: TextStyle(
color: Colors.black,
fontWeight: FontWeight.w400)),
keyboardType: TextInputType.text,
obscureText: true,
),
),
),
SizedBox(
height: MediaQuery.of(context).size.height / 50,
),
Padding(
padding: const EdgeInsets.only(left: 15.0, right: 15.0),
child: InkWell(
onTap: () {
print(_emailController.text);
print(_passwordController.text);
print(_usernameController.text);
signUp(
_emailController.text,
_usernameController.text,
_passwordController.text,
_firstnameController.text,
_lastnameController.text,
);
},
child: loading
? CircularProgressIndicator()
: Container(
height: MediaQuery.of(context).size.height / 13,
//width: MediaQuery.of(context).size.height / 1.8,
decoration: BoxDecoration(
color: Color(0xFFD1A155),
borderRadius: BorderRadius.circular(5.0),
),
child: Center(
child: Text(
"SIGN UP",
style: TextStyle(
color: Colors.white, fontSize: 18.0),
),
),
),
),
)
],
),
SizedBox(
height: MediaQuery.of(context).size.height / 30,
),
Stack(
alignment: Alignment.center,
children: <Widget>[
SizedBox(
height: 2.0,
child: new Center(
child: new Container(
height: 10.0,
color: Colors.black12,
),
),
),
Container(
height: MediaQuery.of(context).size.height / 18,
width: MediaQuery.of(context).size.height / 11,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(23.0),
color: Colors.white,
border: Border.all(color: Colors.black12)),
child: Center(
child: Text(
"OR",
style: TextStyle(fontSize: 18.0),
)),
),
],
),
SizedBox(
height: MediaQuery.of(context).size.height / 40,
),
Padding(
padding: const EdgeInsets.only(left: 15.0, right: 15.0),
child: Row(
children: <Widget>[
Container(
height: MediaQuery.of(context).size.height / 13,
width: MediaQuery.of(context).size.width / 2.2,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5.0),
color: Colors.white,
border: Border.all(color: Colors.black12)),
child: Row(
children: <Widget>[
SizedBox(
width: 18.0,
),
Icon(Icons.tag_faces),
SizedBox(
width: 10.0,
),
Text(
"Facebook",
style: TextStyle(fontSize: 22.0, color: Colors.blue),
),
],
),
),
SizedBox(
width: MediaQuery.of(context).size.width / 40,
),
Container(
height: MediaQuery.of(context).size.height / 13,
width: MediaQuery.of(context).size.width / 2.3,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5.0),
color: Colors.white,
border: Border.all(color: Colors.black12)),
child: Row(
children: <Widget>[
SizedBox(
width: 18.0,
),
Icon(Icons.tag_faces),
SizedBox(
width: 10.0,
),
Text(
"Google+",
style: TextStyle(fontSize: 22.0, color: Colors.red),
),
],
),
),
],
),
),
SizedBox(
height: MediaQuery.of(context).size.height / 30,
),
Align(
alignment: Alignment.center,
child: InkWell(
onTap: () => Navigator.pop(context),
child: RichText(
text: TextSpan(
text: "Already have an account?",
style: TextStyle(fontSize: 20.0, color: Colors.black87),
children: <TextSpan>[
TextSpan(
text: ' Log in',
style: TextStyle(
color: Color(0xFFD1A155),
fontWeight: FontWeight.bold)),
])),
),
),
SizedBox(
height: MediaQuery.of(context).size.height / 40,
),
],
),
),
);
}
}
Error code 400 commonly occurs due to bad requests that the server is unable to process (i.e. unexpected parameters, malformed syntax). If what has been mentioned in the comments is correct, and woocommerce is being used here, there's no way that I can test your setup. But what I can suggest is testing your config in a client following this guide. Postman is a commonly used tool that I can suggest to test HTTP Requests. If the API works well with Postman but the request still has issues in Flutter, we can start from there.
I am trying to implement the cart functionality having add and remove quantity functions. I am using controller.text and updating to text field my issue is when i am adding and removing all the list items updated because of the same controller for text field how to separate update for each item?
ListView.builder(
scrollDirection: Axis.vertical,
itemCount: (data != null) ? (data["items"].length) * 20 : 0,
itemBuilder: (BuildContext context, int index) {
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
),
)
),
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,
),
)
),
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
),
),
),
],
),
),
]
Functions
void _addQuantity(){
setState(() {
quantity++;
_quantityController.text = '$quantity';
});
}
void _removeQuantity(){
setState(() {
if(quantity > 0){
quantity--;
}else{
quantity = 0;
}
_quantityController.text = '$quantity';
});
}
You need to provide a different controller for every text field.
Create a list of Controller
List<TextEditingController> _quantityController = new List();
and use it in your code like
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),
),
),
),
],
),
),
],
),
);
},
);
Now your function will change to
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';
});
}
Don't forget to dispose all the controller in the end.