Update current page from widget method outside the stateful class - android

I have a method outside the stateful class for showing a dialog I want to refresh the data on the page after I close the dialog how it can be one? If I push the Screen again it will act weird (it will open the home page then go to the current page any idea of that it may help me to fix my issue.
AlertWidget(BuildContext context, String Fname, String Lname, String key) {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final TextEditingController _firstName = TextEditingController(text: Fname);
final TextEditingController _lastName = TextEditingController(text: Lname);
showDialog(
context: context,
builder: (context) {
var _height = MediaQuery.of(context).size.height;
var _width = MediaQuery.of(context).size.width;
return Center(
child: Material(
type: MaterialType.transparency,
child: Padding(
padding: const EdgeInsets.only(left: 15, right: 15),
child: Container(
color: Colors.white,
padding: EdgeInsets.all(15),
height: _height - _height * 11.5 / 16,
child: Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Align(
alignment: (translator.currentLanguage == "en")
? Alignment.topLeft
: Alignment.topRight,
child: Text(
translator.translate('Name'),
style: TextStyle(
color: ProjectTheme.projectPrimaryColor,
fontSize: 25),
)),
SizedBox(
height: displayHeight(context) * 0.02,
),
Row(
children: [
Text("${translator.translate('FirstName')}:",
style: TextStyle(fontSize: 18)),
SizedBox(
height: _height * .8 / 16,
width: _width * 1.5 / 16,
),
Container(
height: _height * .5 / 16,
width: _width * 5.5 / 16,
child: Container(
child: Padding(
padding: const EdgeInsets.only(
left: 10, right: 10, top: 10),
child: TextFormField(
controller: _firstName,
validator: (value) {
if (value.trim().isEmpty)
return 'This field is required.';
return null;
},
decoration: InputDecoration(
border: InputBorder.none,
),
),
),
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.4),
spreadRadius: 2,
blurRadius: 5,
offset: Offset(0, 1),
),
],
color: Colors.white,
),
),
),
],
),
Row(
children: [
Text("${translator.translate('LastName')}:",
style: TextStyle(fontSize: 18)),
SizedBox(
height: _height * 1 / 16,
width: _width * 1.5 / 16,
),
Container(
height: _height * .5 / 16,
width: _width * 5.5 / 16,
child: Container(
child: Padding(
padding: const EdgeInsets.only(
left: 10, right: 10, top: 10),
child: TextFormField(
controller: _lastName,
validator: (value) {
if (value.trim().isEmpty)
return 'This field is required.';
return null;
},
decoration: InputDecoration(
border: InputBorder.none,
),
),
),
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.4),
spreadRadius: 2,
blurRadius: 5,
offset: Offset(0, 1),
),
],
color: Colors.white,
),
),
),
],
),
SizedBox(height: _height * .3 / 16),
Align(
alignment: Alignment.bottomRight,
child: Container(
height: 35,
width: 100,
decoration: BoxDecoration(
color: ProjectTheme.projectPrimaryColor,
borderRadius:
BorderRadius.all(Radius.circular(20.0)),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.5),
spreadRadius: 2,
blurRadius: 10,
offset: Offset(0, 3),
),
],
),
child: Center(
child: TextButton(
onPressed: () async {
bool isChanged = !(_firstName.text == Fname &&
_lastName == Lname);
if (_formKey.currentState.validate()) {
final FirebaseAuth _firebaseAuth =
FirebaseAuth.instance;
await FirebaseFirestore.instance
.collection('users')
.doc(_firebaseAuth.currentUser.uid)
.update((key == 'name')
? {
'firstName':
_firstName.text.trim(),
'lastName': _lastName.text.trim(),
'fullName':
_firstName.text.trim() +
' ' +
_lastName.text.trim(),
'userName':
_firstName.text.trim() +
' ' +
_lastName.text.trim(),
}
: {
key: _firstName.text.trim() +
' ' +
_lastName.text.trim()
});
FirebaseFirestore.instance
.collection('users')
.doc(_firebaseAuth.currentUser.uid)
.get()
.then((value) {
UserData newUser = UserData(
.......
);
Provider.of<AppData>(context, listen: false)
.updateUser(newUser);
// Navigator.of(context).pushReplacement(
// MaterialPageRoute(
// builder: (ctx) => profileScreen()));
});
}
},
child: Text(
translator.translate('Save'),
style: TextStyle(
fontSize: 16, color: Colors.white),
),
),
),
),
),
],
),
),
),
)),
);
},
);
}
Sorry for the long code, I'm trying to get much info as I can if you need more let me know.
Thanks.

The showDialog function, returns a future that can be used to see when the dialog is closed. Return this future to the page and await it or call then on it to know when it is done.
import 'package:flutter/material.dart';
Future<void> AlertWidget(
BuildContext context,
String Fname,
String Lname,
String key,
) {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final TextEditingController _firstName = TextEditingController(text: Fname);
final TextEditingController _lastName = TextEditingController(text: Lname);
return showDialog(
context: context,
builder: (context) {
/*...*/
});
}
class MyPage extends StatefulWidget {
#override
_MyPageState createState() => _MyPageState();
}
class _MyPageState extends State<MyPage> {
// this function opens the alert dialog & calls setState when the dialog is closed
void showDialogOnTap() {
// show dialog
AlertWidget(context, 'Fname', 'Lname', 'Pkey')
.then((_) { // then on closed
setState(() {}); // set page state
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Container(),
floatingActionButton: FloatingActionButton(
onPressed: showDialogOnTap,
),
);
}
}

Related

Updating text value with new discount amount in flutter

I'm making a food ordering app in which I want to provide a discount feature. I've implemented most of the part but I'm getting stuck at a point where I basically want to update the totalAmount with the discountRate.
class CartScreen extends StatefulWidget
{
final String? sellerUID;
const CartScreen({super.key, this.sellerUID});
#override
_CartScreenState createState() => _CartScreenState();
}
class _CartScreenState extends State<CartScreen>
{
List<int>? separateItemQuantityList;
num totalAmount = 0;
final _couponText = TextEditingController();
#override
void initState() {
super.initState();
totalAmount = 0;
Provider.of<TotalAmount>(context, listen: false).displayTotalAmount(0);
separateItemQuantityList = separateItemQuantities();
}
#override
Widget build(BuildContext context) {
var _coupon = Provider.of<CouponProvider>(context);
double discountRate = _coupon.discount/100;
return Scaffold(
appBar: AppBar(
title: const Text("Cart"),
flexibleSpace: Container(decoration: BoxDecoration(color: myColor),),
automaticallyImplyLeading: true,
),
body: CustomScrollView(
slivers: [
//display cart items with quantity number
StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance
.collection("items")
.where("itemID", whereIn: separateItemIDs())
.orderBy("publishedDate", descending: true)
.snapshots(),
builder: (context, snapshot)
{
return !snapshot.hasData
? SliverToBoxAdapter(child: Center(child: circularProgress(),),)
: snapshot.data!.docs.isEmpty
? const SliverToBoxAdapter(child: Center(child: Padding(
padding: EdgeInsets.only(top: 300),
child: Text("The cart is empty",style: TextStyle(
fontSize: 24, fontWeight: FontWeight.bold),),
)))
: SliverList(
delegate: SliverChildBuilderDelegate((context, index)
{
Items model = Items.fromJson(
snapshot.data!.docs[index].data()! as Map<String, dynamic>,
);
if(index == 0)
{
totalAmount = 0;
totalAmount = totalAmount + (model.price! * separateItemQuantityList![index]);
}
else
{
totalAmount = totalAmount + (model.price! * separateItemQuantityList![index]);
}
if(snapshot.data!.docs.length - 1 == index)
{
WidgetsBinding.instance.addPostFrameCallback((timeStamp)
{
Provider.of<TotalAmount>(context, listen: false).displayTotalAmount(totalAmount.toDouble());
});
}
return CartItemDesign(
model: model,
context: context,
quanNumber: separateItemQuantityList![index],
);
},
childCount: snapshot.hasData ? snapshot.data!.docs.length : 0,
),
);
},
),
SliverFillRemaining(
hasScrollBody: false,
child: Align(
alignment: Alignment.bottomCenter,
child: Container(
decoration: BoxDecoration(
color: const Color(0xfffb9e5a).withOpacity(0.6),
borderRadius: const BorderRadius.only(topLeft: Radius.circular(20), topRight: Radius.circular(20)),
),
width: double.infinity,
height: 160,
child: Padding(
padding: const EdgeInsets.fromLTRB(8, 12, 8, 6),
child: Column(
children: [
Consumer2<TotalAmount, CartItemCounter>(builder: (context, amountProvider, cartProvider, c){
return Center(
child: cartProvider.count == 0
? const Text("Please add something in the cart", style: TextStyle(fontSize: 18),)
: Column(
children: [
Text("The total amount is ₹${amountProvider.tAmount.toString()}", style: const TextStyle(fontSize: 18)),
const SizedBox(height: 10,),
Container(
height: 50,
width: MediaQuery.of(context).size.width * 8,
decoration: BoxDecoration(
border: Border.all(color: myColor, width: 1,),
borderRadius: const BorderRadius.all(Radius.circular(20)),
color: Colors.white54
//color: Colors.white54
),
child: Row(
children: [
Expanded(
child: Padding(
padding: const EdgeInsets.only(left: 10, right: 15),
child: TextField(
controller: _couponText,
maxLines: 1,
decoration: const InputDecoration.collapsed(
hintText: 'Apply coupon here ...'
),
),
),
),
Padding(
padding: const EdgeInsets.only(right: 10),
child: ElevatedButton(
onPressed: (){
_coupon.getcouponDetails(_couponText.text).then((value) {
if(value.data() == null){
setState(() {
_coupon.discount = 0;
});
showCodeDialog(_couponText.text, 'not valid');
return;
}
if(_coupon.expired==false){
// Code to be done here.
Fluttertoast.showToast(msg: 'Coupon is valid');
// I want to update the totalAmount value with the discountRate here...
}
if(_coupon.expired==true){
setState(() {
_coupon.discount = 0;
});
showCodeDialog(_couponText.text, 'expired');
return;
}
});
},
style: ElevatedButton.styleFrom(
textStyle: const TextStyle(
fontSize: 15,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
)
),
child: const Text('Apply'),
),
),
],
),
),
const SizedBox(height: 10,),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton.icon(
onPressed: (){
clearCartNow(context);
Navigator.pop(context);
Navigator.push(context, MaterialPageRoute(builder: (c) => const HomeScreen()));
Fluttertoast.showToast(msg: "Cart cleared");
},
style: ElevatedButton.styleFrom(
foregroundColor: Colors.black, backgroundColor: myColor
),
icon: const Icon(Icons.clear_all),
label: const Text("Clear")),
ElevatedButton.icon(
onPressed: (){
Navigator.pop(context);
Navigator.push(context, MaterialPageRoute(builder: (c)=> AddressScreen(
totalAmount: totalAmount.toDouble(),
sellerUID: widget.sellerUID,
),
),
);
},
style: ElevatedButton.styleFrom(
foregroundColor: Colors.black,
backgroundColor: myColor,
),
icon: const Icon(Icons.navigate_next),
label: const Text("Proceed")),
],
)
],
),
);
}),
],
),
)
),
),
)
],
),
);
}
showCodeDialog(code, validity){
showCupertinoDialog(
context: context,
builder: (BuildContext context){
return CupertinoAlertDialog(
title: const Text('Apply Coupon'),
content: Text('This discount coupon $code you have entered is $validity'),
actions: [
Padding(
padding: const EdgeInsets.all(8.0),
child: ElevatedButton(
onPressed: (){Navigator.pop(context);},
child: Text('Ok', style: TextStyle(color: Colors.white),),
),
)
],
);
});
}
}
I tried changing the totalAmount, amountProvider.tAmount and their types, but nothing is working for me.
In this image, the total amount is without discount. If I apply a coupon of 10%, the total amount should be subtracted by 10%.
I can add more information if required.

Red Screen Error type 'String' is not a subtype of type 'int' of 'index' Flutter

When I navigate my chat page, I see this error in red screen on emulator.
No idea why it does not work. Does anyone know how to solve it?
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import '../chat/chat.dart';
class ChatHome extends StatefulWidget {
#override
_ChatHomeState createState() => _ChatHomeState();
}
class _ChatHomeState extends State<ChatHome> {
var _db = FirebaseFirestore.instance;
TextEditingController userController;
final _scaffKey = GlobalKey<ScaffoldState>();
#override
void initState() {
super.initState();
userController = new TextEditingController();
setState(() {});
}
#override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffKey,
floatingActionButton: FloatingActionButton(
onPressed: () {
showDialog(
// barrierDismissible: false,
context: context,
builder: (context) => _buildPopUpMessage(context),
);
},
splashColor: Theme.of(context).colorScheme.onSecondary,
child: Icon(
Icons.add,
),
),
body: FutureBuilder(
future: getPosts(),
builder: (_, snapshot) {
if (snapshot.hasData) {
String myId = snapshot.data['id'];
return StreamBuilder(
stream: getChats(myId),
builder: (context, snapshot) {
if (snapshot.hasData) {
QuerySnapshot qSnap = snapshot.data;
List<DocumentSnapshot> docs = qSnap.docs;
if (docs.length == 0)
return Center(
child: Text('No Chats yet!'),
);
return ListView.builder(
itemCount: docs.length,
itemBuilder: (context, index) {
List<dynamic> members = docs[index].data()['members'];
String userId;
userId = members.elementAt(0) == myId
? members.elementAt(1)
: members.elementAt(0);
return FutureBuilder(
future: getUserByUsername(userId),
builder: (context, _snapshot) {
if (_snapshot.hasData) {
DocumentSnapshot docSnapUser = _snapshot.data;
Map<String, dynamic> _user = docSnapUser.data();
return Card(
margin: EdgeInsets.all(8.0),
elevation: 8.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5.0),
),
child: InkWell(
splashColor:
Theme.of(context).colorScheme.primary,
onTap: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Chat(
peerId: _user["id"],
peerAvatar: _user['photoUrl'],
))),
child: Container(
margin: EdgeInsets.all(10.0),
height:
MediaQuery.of(context).size.height * 0.08,
child: Center(
child: Row(
children: [
Hero(
tag: _user['photoUrl'],
child: Container(
width: MediaQuery.of(context)
.size
.width *
0.15,
height: MediaQuery.of(context)
.size
.width *
0.15,
decoration: new BoxDecoration(
shape: BoxShape.circle,
image: new DecorationImage(
fit: BoxFit.cover,
image: new NetworkImage(
_user['photoUrl']),
),
),
),
),
SizedBox(
width: MediaQuery.of(context)
.size
.width *
0.02,
),
SizedBox(
width: MediaQuery.of(context)
.size
.width *
0.43,
child: Text(
_user['nickname'],
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
),
),
),
],
),
),
),
),
);
}
return Card(
margin: EdgeInsets.all(8.0),
elevation: 8.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5.0),
),
child: Container(
margin: EdgeInsets.all(10.0),
height: MediaQuery.of(context).size.height * 0.08,
child: Center(
child: CircularProgressIndicator(
valueColor: new AlwaysStoppedAnimation(
Theme.of(context).colorScheme.primary,
),
),
),
),
);
},
);
},
);
}
return Center(
child: CircularProgressIndicator(
valueColor: new AlwaysStoppedAnimation(
Theme.of(context).colorScheme.primary,
),
),
);
},
);
}
return Center(
child: CircularProgressIndicator(
valueColor: new AlwaysStoppedAnimation(
Theme.of(context).colorScheme.primary,
),
),
);
},
),
);
}
Widget _timeDivider(Timestamp time) {
DateTime t = time.toDate();
String minute =
t.minute > 9 ? t.minute.toString() : '0' + t.minute.toString();
String ampm = t.hour >= 12 ? "PM" : "AM";
int hour = t.hour >= 12 ? t.hour % 12 : t.hour;
DateTime press = DateTime.now();
if (press.year == t.year && press.month == t.month && press.day == t.day)
return Text(hour.toString() + ':' + minute + ' ' + ampm);
return Text(t.day.toString() +
'/' +
(t.month + 1).toString() +
'/' +
t.year.toString());
}
Widget _buildPopUpMessage(context) {
return Align(
alignment: Alignment.topCenter,
child: Container(
padding: EdgeInsets.all(8.0),
height: MediaQuery.of(context).size.width * .5,
width: MediaQuery.of(context).size.width * .6,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(40),
),
margin: EdgeInsets.only(bottom: 50, left: 12, right: 12, top: 50),
child: SingleChildScrollView(
child: Column(
children: <Widget>[
SizedBox(
height: MediaQuery.of(context).size.width * .1,
child: Center(
child: new RichText(
text: new TextSpan(
style: new TextStyle(
fontSize: 14.0,
color: Colors.black,
),
children: <TextSpan>[
new TextSpan(
text: 'username',
style: new TextStyle(
color: Theme.of(context).colorScheme.primary,
fontWeight: FontWeight.bold),
),
new TextSpan(
text: '#gmail.com',
),
],
),
),
),
),
SizedBox(
height: MediaQuery.of(context).size.width * .2,
child: Center(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Material(
child: TextField(
autofocus: true,
controller: userController,
decoration: new InputDecoration(
border: new OutlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context).colorScheme.primary,
),
borderRadius: const BorderRadius.all(
const Radius.circular(10.0),
),
),
focusedBorder: new OutlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context).colorScheme.primary,
),
borderRadius: const BorderRadius.all(
const Radius.circular(10.0),
),
),
enabledBorder: new OutlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context).colorScheme.primary,
),
borderRadius: const BorderRadius.all(
const Radius.circular(10.0),
),
),
errorBorder: new OutlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context).colorScheme.error,
),
borderRadius: const BorderRadius.all(
const Radius.circular(10.0),
),
),
filled: true,
hintText: "Type in only Username",
hintStyle: TextStyle(fontSize: 16.0),
),
),
),
),
),
),
SizedBox(
height: MediaQuery.of(context).size.width * .1,
child: Center(
child: Align(
alignment: Alignment.center,
child: RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0),
),
color: Theme.of(context).colorScheme.secondary,
child: Text(
'Let\'s chat with your friend.',
style: TextStyle(
color: Theme.of(context).colorScheme.onSecondary),
),
onPressed: () async {
if (userController.text.isNotEmpty) {
String username = userController.text.toString();
userController.clear();
QuerySnapshot doc =
getUserByEmail(username + '#gmail.com');
if (doc.docs.length != 0) {
DocumentSnapshot user = doc.docs[0];
Map<String, dynamic> userData = user.data();
Navigator.pop(context);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Chat(
peerId: userData["id"],
peerAvatar: userData['photoUrl'],
)));
print(user.data()['nickname'].toString());
} else {
showSnackPlz(context, username);
Navigator.pop(context);
}
} else {
showSnackPlzWithMessage(context, 'Empty Username');
Navigator.pop(context);
}
},
),
),
),
),
],
),
),
),
);
}
showSnackPlz(BuildContext context, String username) {
final SnackBar snackMe = SnackBar(
content: new RichText(
text: new TextSpan(
style: new TextStyle(
fontSize: 14.0,
),
children: <TextSpan>[
new TextSpan(
text: 'User with email ',
),
new TextSpan(
text: username,
style: new TextStyle(fontWeight: FontWeight.bold),
),
new TextSpan(
text: '#gmail.com not in the database!',
),
],
),
),
);
_scaffKey.currentState.showSnackBar(snackMe);
}
showSnackPlzWithMessage(BuildContext context, String message) {
final SnackBar snackMe = SnackBar(
content: new Text(message),
);
_scaffKey.currentState.showSnackBar(snackMe);
}
getChats(String uid) {
return FirebaseFirestore.instance
.collection('messages')
.where('members', arrayContains: uid)
.snapshots();
}
getUserByUsername(String username) async {
return await _db.collection('users').doc(username).get();
}
getUserByEmail(String email) async {
return await _db.collection('users').where('email', isEqualTo: email).get();
}
Future getPosts() async {
var firestore = FirebaseFirestore.instance;
QuerySnapshot qn = await firestore.collection('users').get();
return qn.docs;
}
}
Can't find which code-row causes this.
Tried many changes but nothing helped.
Screenshot of the error
I've been facing this problem for whole day. Being rookie in flutterworld sometimes take bunch of time.
I can only assume what the problem could be please send the logs... So
List<dynamic> members = docs[index].data()['members'];
String userId;
userId = members.elementAt(0) == myId
? members.elementAt(1)
: members.elementAt(0);
You are using this to get the userId (String) from a dynamic list.
check whether you dynamic list only contains String values before handling a value as a string. Please do this for all other occurrences of dynamic...
This error means that you cast an int to a string. That is illegal. Just check all your String occurrences.

Is it possible to implement widgets using list in flutter?

I am creating a Journal mobile application which would work as a medium to view magazines and daily news updates. This is my first flutter project and I am totally new to flutter. So kindly excuse me if I had said something wrong about something or didnt provide enough information.
I used a code from github for the main page of my application and made few changes to accommodate my needs. Now in my code, the home page consists of a side menu bar and this bar consists of 4 buttons, namely Home, My Profile, Premium and FAQ. The GlobalKeys for the side menu bar is called using a list by the name _keys which is of the type GlobalKey. I tried changing the data type of the list _keys to Widget and then called the corresponding Widgets of the classes. But then two errors popped out.
The getter 'currentContext' isn't defined for the class 'Widget'.
The argument type 'Widget' can't be assigned to the parameter type 'GlobalKey<State>'.
Now I would like the list _keys to be of the type Widget in order for me to call upon it's corresponding widgets of Home, My Profile, Premium and FAQ from each of it's classes in order for me to view the corresponding pages. Or if it is not possible, I would love to know an alternative for it to start working.
Following is the code of my application.
import 'dart:math' as math;
import 'package:flutter/scheduler.dart';
import 'package:google_signin_example/google%20sign%20in/logged_in_widget.dart';
import 'package:google_signin_example/main app/lib/ui_3/TravelBean.dart';
import 'package:google_signin_example/main app/lib/ui_3/magazine/screens/home_screen.dart';
import 'package:google_signin_example/main%20app/lib/ui_3/FAQ/faq.dart';
import 'package:google_signin_example/main%20app/lib/ui_3/Newspaper%20and%20Kiddos/lib_kiddos/main.dart';
import 'package:google_signin_example/main%20app/lib/ui_3/Newspaper%20and%20Kiddos/lib_news/main.dart';
import 'package:google_signin_example/main%20app/lib/ui_3/premium/premium.dart';
import 'package:google_signin_example/widget/sign_up_widget.dart';
import 'detail_page.dart';
class HomePage1 extends StatefulWidget {
#override
_HomePage1State createState() => _HomePage1State();
}
class _HomePage1State extends State<HomePage1> {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Container(
child: Row(
children: <Widget>[
LeftWidget(),
Expanded(
child: RightWidget(),
)
],
),
),
);
}
}
class LeftWidget extends StatefulWidget {
#override
_LeftWidgetState createState() => _LeftWidgetState();
}
class _LeftWidgetState extends State<LeftWidget> with TickerProviderStateMixin {
List<String> _list = ["Home", "My profile", "Premium", "FAQ"];
List <Widget> _keys = [
HomePage1(), //These are the widgets from different classes.
LoggedInWidget(),
premium(),
faq(),
/*GlobalKey(), //This was available before I made the changes.
GlobalKey(),
GlobalKey(),
GlobalKey()*/
];
int checkIndex = 0;
Offset checkedPositionOffset = Offset(0, 0);
Offset lastCheckOffset = Offset(0, 0);
Offset animationOffset = Offset(0, 0);
Animation _animation;
AnimationController _animationController;
#override
void initState() {
checkIndex = _list.length - 1;
super.initState();
SchedulerBinding.instance.endOfFrame.then((value) {
calcuteCheckOffset();
addAnimation();
});
}
void calcuteCheckOffset() {
lastCheckOffset = checkedPositionOffset;
RenderBox renderBox = _keys[checkIndex].currentContext.findRenderObject(); //This is where the first error occurs.
Offset widgetOffset = renderBox.localToGlobal(Offset(0, 0));
Size widgetSise = renderBox.size;
checkedPositionOffset = Offset(widgetOffset.dx + widgetSise.width,
widgetOffset.dy + widgetSise.height);
}
#override
Widget build(BuildContext context) {
return Container(
child: Stack(
children: <Widget>[
Container(
width: 50,
decoration: BoxDecoration(
color: Color(0xff000000),
borderRadius: BorderRadius.circular(30),
),
child: Column(
children: _buildList(),
),
),
Positioned(
top: animationOffset.dy,
left: animationOffset.dx,
child: CustomPaint(
painter: CheckPointPainter(Offset(10, 0)),
),
)
],
),
);
}
List<Widget> _buildList() {
List<Widget> _widget_list = [];
_widget_list.add(Padding(
padding: EdgeInsets.only(
top: 50,
),
child: Icon(
Icons.settings,
color: Colors.white,
size: 30,
),
));
for (int i = 0; i < _list.length; i++) {
_widget_list.add(Expanded(
child: GestureDetector(
onTap: () {
indexChecked(i);
},
child: VerticalText(
_list[i],
_keys[i], //This is where the second error occurs.
checkIndex == i &&
(_animationController != null &&
_animationController.isCompleted))),
));
}
_widget_list.add(Padding(
padding: EdgeInsets.only(
top: 50,
bottom: 50,
),
child: Image(image: AssetImage('assets/images/Voix.png')),
));
return _widget_list;
}
void indexChecked(int i) {
if (checkIndex == i) return;
setState(() {
checkIndex = i;
calcuteCheckOffset();
addAnimation();
});
}
void addAnimation() {
_animationController =
AnimationController(duration: Duration(milliseconds: 300), vsync: this)
..addListener(() {
setState(() {
animationOffset =
Offset(checkedPositionOffset.dx, _animation.value);
});
});
_animation = Tween(begin: lastCheckOffset.dy, end: checkedPositionOffset.dy)
.animate(CurvedAnimation(
parent: _animationController, curve: Curves.easeInOutBack));
_animationController.forward();
}
}
class CheckPointPainter extends CustomPainter {
double pointRadius = 5;
double radius = 30;
Offset offset;
CheckPointPainter(this.offset);
#override
void paint(Canvas canvas, Size size) {
Paint paint = Paint()..style = PaintingStyle.fill;
double startAngle = -math.pi / 2;
double sweepAngle = math.pi;
paint.color = Color(0xff000000);
canvas.drawArc(
Rect.fromCircle(center: Offset(offset.dx, offset.dy), radius: radius),
startAngle,
sweepAngle,
false,
paint);
paint.color = Color(0xffffffff);
canvas.drawCircle(
Offset(offset.dx - pointRadius / 2, offset.dy - pointRadius / 2),
pointRadius,
paint);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
class VerticalText extends StatelessWidget {
String name;
bool checked;
GlobalKey globalKey;
VerticalText(this.name, this.globalKey, this.checked);
#override
Widget build(BuildContext context) {
return RotatedBox(
key: globalKey,
quarterTurns: 3,
child: Text(
name,
style: TextStyle(
color: checked ? Color(0xffffffff) : Colors.grey,
fontSize: 16,
),
),
);
}
}
class RightWidget extends StatefulWidget {
#override
_RightWidgetState createState() => _RightWidgetState();
}
class _RightWidgetState extends State<RightWidget>
with TickerProviderStateMixin {
TabController _tabController;
#override
void initState() {
super.initState();
_tabController = TabController(vsync: this, length: 5);
}
#override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.only(
left: 15,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: 50, left: 20),
child: Text(
"Voix Home",
style: TextStyle(
color: Colors.black,
fontSize: 25,
),
),
),
Padding(
padding: const EdgeInsets.only(top: 15, left: 10),
child: SizedBox(
height: 30,
child: TabBar(
isScrollable: true,
unselectedLabelColor: Colors.black,
labelColor: Color(0xffffffff),
controller: _tabController,
indicator: BoxDecoration(
color: Color(0xff9e9e9e),
borderRadius: BorderRadius.only(
topRight: Radius.circular(20),
bottomLeft: Radius.circular(20),
),
),
tabs: <Widget>[
Tab(
text: "Flash",
),
Tab(
text: "Magazine",
),
Tab(
text: "Newspaper",
),
Tab(
text: "Kiddos",
),
Tab(
text: "Editorial",
),
],
),
),
),
Expanded(
child: TabBarView(
controller: _tabController,
children: <Widget>[
TravelWidget(),
HomeScreen(),
News(),
Kiddos(),
RightBody(),
// RightBody(),
],
),
)
],
),
);
}
}
class RightBody extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.only(
left: 15,
),
color: Colors.white,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: EdgeInsets.only(
top: 20,
),
child: Text(
"Flash!",
style: TextStyle(
color: Colors.black,
fontSize: 20,
),
),
),
Expanded(
child: ListView(
scrollDirection: Axis.horizontal,
children: <Widget>[
Container(
width: 220,
margin: EdgeInsets.symmetric(
horizontal: 10,
vertical: 10,
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(40),
image: new DecorationImage(
image: new AssetImage('assets/images/bottom1.jpg'),
fit: BoxFit.cover,
),
boxShadow: [
BoxShadow(
spreadRadius: 5,
blurRadius: 5,
offset: Offset(1, 2),
color: Color(0x33757575),
),
],
),
),
Container(
width: 220,
margin: EdgeInsets.symmetric(
horizontal: 10,
vertical: 10,
),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(40),
boxShadow: [
BoxShadow(
spreadRadius: 5,
blurRadius: 5,
offset: Offset(1, 2),
color: Color(0x33757575),
),
],
),
),
],
),
),
],
),
);
}
}
class TravelWidget extends StatelessWidget {
List<TravelBean> _list = TravelBean.generateTravelBean();
#override
Widget build(BuildContext context) {
return PageView.builder(
controller: PageController(viewportFraction: 0.9),
itemBuilder: (context, index) {
var bean = _list[index];
return GestureDetector(
onTap: () {
Navigator.of(context).push(MaterialPageRoute(builder: (context) {
return DetailPage(bean);
}));
},
child: Hero(
tag: bean.url,
child: Stack(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(bottom: 30, right: 10),
child: ClipRRect(
borderRadius: BorderRadius.circular(5),
child: Image.asset(
bean.url,
width: MediaQuery.of(context).size.width,
fit: BoxFit.cover,
),
),
),
Positioned(
bottom: 80,
left: 15,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Material(
color: Colors.transparent,
child: Text(
bean.location,
style: TextStyle(
color: Colors.black54,
fontSize: 15,
),
),
),
Material(
color: Colors.transparent,
child: Text(
bean.name,
style: TextStyle(
color: Colors.black,
fontSize: 20,
),
),
),
],
),
),
Positioned(
bottom: 0,
right: 30,
child: Container(
width: 60,
height: 60,
decoration: BoxDecoration(
color: Colors.black,
borderRadius: BorderRadius.circular(30),
),
child: Icon(
Icons.arrow_forward,
color: Colors.white,
size: 30,
),
),
)
],
),
),
);
},
itemCount: _list.length,
);
}
}
At the beginning, when I leave the list _keys to be of the type GlobalKey and don't comment out the following 4 GlobalKeys I get the output but the side menu bar won't work.
This is my application with GlobalKeys in place of those Widgets
I want those corresponding pages to display when clicked on. But that render object just switches between the options and the same page is displayed.
So kindly help me out.
PS : As said earlier I'm new to flutter, so kindly don't mistake me if I had something wrong.
I suggest you check about flutter state management, especially Mobx with Provider, it will be kind easier for you.

Nested Gesture Does not change on Tap

I am currently working on the ui stuff for the appliction, so the thing is i have one gesture as a parent that swipes up and down and based on it the position of the widgets gets changed but the problem is the child gesture does not get any precedence when tapped on it it gives the precedence. So my tree structure is Pageview.builder which has single widget with topmost parent as Gesturedetector and the children accrodingly, Can any one tell me what i am doing wrong or any improvements to get the gesture for each.
Below is the sample code that i have been working on:
import 'dart:math';
import 'package:LocationAnimation/Model/device_model.dart';
import 'package:LocationAnimation/SplashPage/splash_page.dart';
import 'package:LocationAnimation/widgets/device_function_widget.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:google_fonts/google_fonts.dart';
import 'Model/device_model.dart' as devices;
import 'Model/locations_model.dart' as locations;
import 'extensions/capitalize.dart';
void main() {
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'HAL',
home: MyHomePage(),
);
}
}
class SampleList {
final String locationName;
SampleList({this.locationName});
}
class MyHomePage extends StatefulWidget {
#override
State createState() => new MyHomePageState();
}
class MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
final _controller = new PageController();
final _kArrowColor = Colors.black.withOpacity(0.8);
bool _isSwipe = false;
bool _isLoading = false;
var list = [
SampleList(locationName: 'Living Room'),
SampleList(locationName: 'Bed Room'),
SampleList(locationName: 'Back Porch Lights'),
SampleList(locationName: 'Basement Porch Lights'),
SampleList(locationName: 'Sample Room'),
];
#override
Widget build(BuildContext context) {
return new Scaffold(
body: new IconTheme(
data: new IconThemeData(color: _kArrowColor),
child: new Stack(
children: <Widget>[
new PageView.builder(
physics: _isSwipe
? NeverScrollableScrollPhysics()
: AlwaysScrollableScrollPhysics(),
controller: _controller,
itemCount: list.length,
itemBuilder: (BuildContext context, int index) {
return LocationDetails(
isLoading: _isLoading,
item: list[index],
onSwipeDown: () {
setState(() {
_isSwipe = false;
});
},
onSwipeUp: () {
setState(() {
_isSwipe = true;
});
},
);
},
),
],
),
),
);
}
}
class LocationDetails extends StatefulWidget {
final bool isLoading;
SampleList item;
final Function() onSwipeUp;
final Function() onSwipeDown;
LocationDetails(
{Key key, this.item, this.onSwipeUp, this.onSwipeDown, this.isLoading})
: super(key: key);
#override
_LocationDetailsState createState() => _LocationDetailsState();
}
class _LocationDetailsState extends State<LocationDetails> {
DragStartDetails startVerticalDragDetails;
DragUpdateDetails updateVerticalDragDetails;
bool moveWidget = false;
bool dismissSwipeText = true;
bool _isRotate = false;
int currentSelectedIndex = 0;
bool ignoreChildGestures = true;
bool _isSwpie = false;
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Container(
child: GestureDetector(
onTap: () {
print('Tap');
},
onVerticalDragStart: (dragDetails) {
startVerticalDragDetails = dragDetails;
},
onVerticalDragUpdate: (dragDetails) {
updateVerticalDragDetails = dragDetails;
},
onVerticalDragEnd: (endDetails) {
double dx = updateVerticalDragDetails.globalPosition.dx -
startVerticalDragDetails.globalPosition.dx;
double dy = updateVerticalDragDetails.globalPosition.dy -
startVerticalDragDetails.globalPosition.dy;
double velocity = endDetails.primaryVelocity;
//Convert values to be positive
if (dx < 0) dx = -dx;
if (dy < 0) dy = -dy;
if (velocity < 0) {
widget.onSwipeUp();
print('drag up');
setState(() {
moveWidget = true;
_isSwpie = true;
});
} else {
widget.onSwipeDown();
print(' drag down');
setState(() {
moveWidget = false;
_isSwpie = false;
});
}
},
child: Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
decoration: new BoxDecoration(
image: new DecorationImage(
colorFilter: ColorFilter.mode(
Colors.black.withOpacity(0.8), BlendMode.srcOver),
image: /* moveWidget
? */
AssetImage(
'Assets/backgroundImage.jpg',
),
/* : NetworkImage(widget.samplePage.networkImage), */
fit: BoxFit.fill,
),
),
child:
/* widget.isLoading
? Center(
child: CircularProgressIndicator(),
)
: */
Stack(
children: <Widget>[
AnimatedOpacity(
opacity: moveWidget ? 0 : 1,
duration: Duration(microseconds: 100),
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Column(
children: <Widget>[
Icon(
Icons.power_settings_new,
color: Colors.white,
size: 30,
),
Icon(
Icons.more_horiz,
color: Colors.white,
size: 25,
)
],
),
Row(
children: <Widget>[
Column(
children: <Widget>[
Text(
'Inside Temp',
style: TextStyle(
color: Colors.white, fontSize: 18),
),
SizedBox(
height: 5,
),
Row(
children: <Widget>[
Icon(
Icons.ac_unit,
color: Colors.white,
size: 20,
),
SizedBox(
width: 10,
),
Text(
'19 C',
style: TextStyle(color: Colors.white),
),
],
)
],
),
SizedBox(
width: 10,
),
Column(
children: <Widget>[
Text(
'Outside Temp',
style: TextStyle(
color: Colors.white, fontSize: 18),
),
SizedBox(
height: 5,
),
Row(
children: <Widget>[
Icon(
Icons.ac_unit,
color: Colors.white,
size: 20,
),
SizedBox(
width: 10,
),
Text(
'19 C',
style: TextStyle(color: Colors.white),
),
],
)
],
),
],
)
],
),
),
),
AnimatedPositioned(
onEnd: () {
setState(() {
dismissSwipeText = !dismissSwipeText;
//print(dismissSwipeText);
});
},
curve: Curves.ease,
duration: Duration(milliseconds: 700),
bottom: moveWidget
? 10
: MediaQuery.of(context).size.height * 0.18,
left: 10.0,
right: 0.0,
top: moveWidget
? 50
: MediaQuery.of(context).size.height * 0.75,
child: AnimatedOpacity(
opacity: dismissSwipeText ? 1 : 0,
duration: Duration(milliseconds: 500),
child: Text(
'Swipe up to customize',
style: TextStyle(color: Colors.white, fontSize: 20),
),
),
),
AnimatedPositioned(
curve: Curves.ease,
duration: Duration(milliseconds: 700),
onEnd: () {
setState(() {
_isSwpie = true;
});
},
left: 10,
top: moveWidget
? 80
: MediaQuery.of(context).size.height * 0.80,
child: Container(
width: MediaQuery.of(context).size.width * 0.97,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
GestureDetector(
onTap: () {
setState(() {
currentSelectedIndex = 0;
});
},
child: Container(
width: MediaQuery.of(context).size.width * 0.20,
height:
MediaQuery.of(context).size.height * 0.10,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: currentSelectedIndex == 0
? Colors.blue
: Colors.grey[900],
),
child: Center(
child: Text(
'Lights',
style: GoogleFonts.lato(
color: Colors.white,
fontWeight: FontWeight.w700),
)),
),
),
Row(
children: <Widget>[
SizedBox(
width: 10,
),
GestureDetector(
onTap: () {
setState(() {
currentSelectedIndex = 1;
});
},
child: Container(
width: MediaQuery.of(context).size.width *
0.20,
height: MediaQuery.of(context).size.height *
0.10,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: currentSelectedIndex == 1
? Colors.blue
: Colors.grey[900],
),
child: Center(
child: Text(
'Applicanes',
style: GoogleFonts.lato(
color: Colors.white,
fontWeight: FontWeight.w700),
)),
),
),
],
),
Row(
children: <Widget>[
SizedBox(
width: 10,
),
GestureDetector(
onTap: () {
setState(() {
currentSelectedIndex = 2;
});
},
child: Container(
width: MediaQuery.of(context).size.width *
0.20,
height: MediaQuery.of(context).size.height *
0.10,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: currentSelectedIndex == 2
? Colors.blue
: Colors.grey[900],
),
child: Center(
child: Text(
'Sensors',
style: GoogleFonts.lato(
color: Colors.white,
fontWeight: FontWeight.w700),
)),
),
),
],
),
Row(
children: <Widget>[
SizedBox(
width: 10,
),
Container(
width:
MediaQuery.of(context).size.width * 0.20,
height:
MediaQuery.of(context).size.height * 0.10,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.grey[900],
),
child: Center(
child: Text(
'Doors \n& Locks',
style: GoogleFonts.lato(
color: Colors.white,
fontWeight: FontWeight.w700),
)),
),
],
),
SizedBox(
width: 10,
),
],
),
),
),
AnimatedPositioned(
curve: Curves.ease,
duration: Duration(milliseconds: 400),
bottom: moveWidget
? 10
: MediaQuery.of(context).size.height * 0.20,
left: 10.0,
right: 0.0,
top: moveWidget
? 15
: MediaQuery.of(context).size.height * 0.70,
child: Text(
'${widget.item.locationName}',
style: TextStyle(fontSize: 30, color: Colors.white),
),
),
],
)),
),
),
),
);
}
}
You can add Color to the last AnimatedPositioned which use text widget.item.locationName in your code, like:
AnimatedPositioned(
curve: Curves.ease,
duration: Duration(milliseconds: 400),
bottom: moveWidget
? 10
: MediaQuery.of(context).size.height * 0.20,
left: 10.0,
right: 0.0,
top: moveWidget
? 15
: MediaQuery.of(context).size.height * 0.70,
child: Container(
color: Colors.white,
Text(
'${widget.item.locationName}',
style: TextStyle(fontSize: 30, color: Colors.white),
),
),
),
You will see a white screen (the widget which blocking you) when you scroll up. You can fix it by 2 ways
Change the bottom 10 to a larger number
Move this part of AnimatedPositioned to Top of the Stack widget
The Nested Gesture should work probably as you expected.
First of All you are using multiple Scaffold in a single page which is not recommended.
And remove the unwanted widgets from your tree which will help you to debug a way more better level. And Next you can try with passing a Callback function from parent to child which can eventually solve your problem

Flutter update data onClick at clicked index

I am building a food cart application and have a query on the menu item page.
My menu items page consists of a list view, which shows each item with description along with an option to specify the quantity of items( 1, 2, 3....)
Now I am able to increment or decrement item count for a single item, but not sure how to do that in a list view at a particular index where the user clicks.
Could some one please help me on this?
The code which I have done till now is as below :
FutureBuilder(
future: getItemList(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return CircularProgressIndicator();
}
var itemList = snapshot.data;
int itemlength = itemList.length;
return ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return Container(
height: 100,
margin: EdgeInsets.only(left: 10, right: 10, top: 10),
decoration: BoxDecoration(
color: Colors.white70,
border: Border.all(width: 2.0, color: Colors.blueGrey),
borderRadius: BorderRadius.circular(6.0),
boxShadow: [
BoxShadow(
color: Color(0xFF6078ea).withOpacity(.3),
offset: Offset(0.0, 8.0),
blurRadius: 8.0),
],
),
child: Row(
children: < Widget > [
Container(
width: 75,
child: ClipRRect(
borderRadius: new BorderRadius.circular(10.0),
child: Image(
image: AssetImage(
'assets/images/loginbg3.jpg'),
fit: BoxFit.cover,
),
),
margin: EdgeInsets.only(left: 10),
),
Expanded(
child: Container(
child: Column(
children: < Widget > [
Row(
children: < Widget > [
Expanded(child: Container(margin: EdgeInsets.only(left: 10, top: 15, bottom: 5), child: Text(itemList[index]['itemname'], style: kClickableTextStyle, ))),
Container(color: Colors.white, width: 25, margin: EdgeInsets.only(left: 10, top: 15, bottom: 5), child: Image.asset(_itemtype)),
],
),
Row(
children: < Widget > [
Container(margin: EdgeInsets.only(left: 10, top: 15, bottom: 5), child: Text('Price : ', style: kListTitleTextStyle, )),
Container(margin: EdgeInsets.only(left: 10, top: 15, bottom: 5), child: Text(numberofitems.toString() + ' \u20B9 ', style: kListTitleTextStyle, )),
],
),
],
),
),
),
Container(
margin: EdgeInsets.only(left: 10),
child: Row(
children: < Widget > [
InkWell(
onTap: onClickDelete,
child: Container(
width: 30, child: Icon(
Icons.remove_circle_outline,
color: Colors.green,
size: 30,
), ),
),
Container(
width: 30,
child: Center(child: Text(_count.toString(), style: TextStyle(fontSize: 25), )),
),
InkWell(
onTap: onClickAdd,
child: Container(
margin: EdgeInsets.only(right: 5),
width: 30, child: Icon(
Icons.add_circle_outline,
color: Colors.green,
size: 30,
), ),
),
],
),
),
],
),
);
},
itemCount: itemList == null ? 0 : itemList.length,
);
})
You can copy paste run full code below
Step 1: create Item class
Step 2: change future builder call
Step 3: deal with Inkwell onTap
working demo
code snippet
Future callback;
#override
void initState() {
callback = _getItemList();
super.initState();
}
#override
Widget build(BuildContext context) {
var futureBuilder = FutureBuilder(
future: callback,
...
InkWell(
onTap: () {
if (itemList[index].numberofitems > 0) {
setState(() {
itemList[index].numberofitems =
itemList[index].numberofitems - 1;
});
}
},
...
InkWell(
onTap: () {
setState(() {
itemList[index].numberofitems =
itemList[index].numberofitems + 1;
print(
' ${itemList[index].itemname.toString()} ${itemList[index].numberofitems.toString()}');
});
},
full code
import 'dart:async';
import 'dart:collection';
import 'package:flutter/material.dart';
void main() => runApp( MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class Item {
String itemname;
String itemtype;
int numberofitems;
Item({this.itemname, this.itemtype, this.numberofitems});
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Future callback;
#override
void initState() {
callback = _getItemList();
super.initState();
}
#override
Widget build(BuildContext context) {
var futureBuilder = FutureBuilder(
future: callback,
builder: (BuildContext context, AsyncSnapshot snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.waiting:
return Center(child: CircularProgressIndicator());
default:
if (snapshot.hasError)
return Text('Error: ${snapshot.error}');
else
return createListView(context, snapshot);
}
},
);
return Scaffold(
appBar: AppBar(
title: Text("Home Page"),
),
body: futureBuilder,
);
}
Future<List<Item>> _getItemList() async {
var values = List<Item>();
values.add(
Item(itemname: "A", itemtype: "assets/images/a.jpg", numberofitems: 0));
values.add(
Item(itemname: "B", itemtype: "assets/images/a.jpg", numberofitems: 1));
values.add(
Item(itemname: "C", itemtype: "assets/images/a.jpg", numberofitems: 2));
//throw Exception("Danger Will Robinson!!!");
await Future.delayed( Duration(seconds: 2));
return values;
}
Widget createListView(BuildContext context, AsyncSnapshot snapshot) {
List<Item> itemList = snapshot.data;
return ListView.builder(
itemCount: itemList.length,
itemBuilder: (BuildContext context, int index) {
{
return Container(
height: 100,
margin: EdgeInsets.only(left: 10, right: 10, top: 10),
decoration: BoxDecoration(
color: Colors.white70,
border: Border.all(width: 2.0, color: Colors.blueGrey),
borderRadius: BorderRadius.circular(6.0),
boxShadow: [
BoxShadow(
color: Color(0xFF6078ea).withOpacity(.3),
offset: Offset(0.0, 8.0),
blurRadius: 8.0),
],
),
child: Row(
children: <Widget>[
Container(
width: 75,
child: ClipRRect(
borderRadius: BorderRadius.circular(10.0),
child: Image(
image: AssetImage('assets/images/a.jpg'),
fit: BoxFit.cover,
),
),
margin: EdgeInsets.only(left: 10),
),
Expanded(
child: Container(
child: Column(
children: <Widget>[
Row(
children: <Widget>[
Expanded(
child: Container(
margin: EdgeInsets.only(
left: 10, top: 15, bottom: 5),
child: Text(
itemList[index].itemname,
))),
Container(
color: Colors.white,
width: 25,
margin: EdgeInsets.only(
left: 10, top: 15, bottom: 5),
child: Image.asset(itemList[index].itemtype)),
],
),
Row(
children: <Widget>[
Container(
margin: EdgeInsets.only(
left: 10, top: 15, bottom: 5),
child: Text(
'Price : ',
)),
Container(
margin: EdgeInsets.only(
left: 10, top: 15, bottom: 5),
child: Text(
itemList[index].numberofitems.toString() +
' \u20B9 ',
)),
],
),
],
),
),
),
Container(
margin: EdgeInsets.only(left: 10),
child: Row(
children: <Widget>[
InkWell(
onTap: () {
if (itemList[index].numberofitems > 0) {
setState(() {
itemList[index].numberofitems =
itemList[index].numberofitems - 1;
});
}
},
child: Container(
width: 30,
child: Icon(
Icons.remove_circle_outline,
color: Colors.green,
size: 30,
),
),
),
Container(
width: 30,
child: Center(
child: Text(
itemList[index].numberofitems.toString(),
style: TextStyle(fontSize: 25),
)),
),
InkWell(
onTap: () {
setState(() {
itemList[index].numberofitems =
itemList[index].numberofitems + 1;
print(
' ${itemList[index].itemname.toString()} ${itemList[index].numberofitems.toString()}');
});
},
child: Container(
margin: EdgeInsets.only(right: 5),
width: 30,
child: Icon(
Icons.add_circle_outline,
color: Colors.green,
size: 30,
),
),
),
],
),
),
],
),
);
}
;
});
}
}
you need to create list of objects for your Item like.
class Item{
String name;
String description;
int quantity;
double price;
}
and on tap of item, get index of clicked item with new incremented/decremented value and update your list of objects inside setState().
You need to wrap your itemBuilder item, i.e the Container with a GestureDetector and then call the onTap() method inside that detector.
Before that, you'll have to convert your item into a stateful widget with a variable to maintain the count of quantity.

Categories

Resources