Cart Quantity selection with TextField Flutter - android

I want to add text field in flutter and when user add value quatity value should be updated you can see in that below item image there is quantity I want to add a text field against it so user can edit quantity as much as he wanted to add you can ask anything you want to ask
here is the quantity selection
class QuantitySelection extends StatelessWidget {
final int limitSelectQuantity;
final int value;
final double width;
final double height;
final Function onChanged;
final Color color;
QuantitySelection(
{#required this.value,
this.width = 40.0,
this.height = 42.0,
this.limitSelectQuantity = 100,
#required this.color,
this.onChanged});
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
if (onChanged != null) {
showOptions(context);
}
},
child: Container(
decoration: BoxDecoration(
border: Border.all(width: 1.0, color: kGrey200),
borderRadius: BorderRadius.circular(3),
),
height: height,
width: width,
child: Padding(
padding: EdgeInsets.symmetric(
vertical: 2.0, horizontal: (onChanged != null) ? 5.0 : 10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(
child: Center(
child: Text(
value.toString(),
style: TextStyle(fontSize: 14, color: color),
),
),
),
if (onChanged != null)
const SizedBox(
width: 5.0,
),
if (onChanged != null)
Icon(Icons.keyboard_arrow_down,
size: 14, color: Theme.of(context).accentColor)
],
),
),
),
);
}
void showOptions(context) {
showModalBottomSheet(
context: context,
builder: (BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Expanded(
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
for (int option = 1;
option <= limitSelectQuantity;
option++)
ListTile(
onTap: () {
onChanged(option);
Navigator.pop(context);
},
title: Text(
option.toString(),
textAlign: TextAlign.center,
)),
],
),
),
),
Container(
height: 1,
decoration: BoxDecoration(color: kGrey200),
),
ListTile(
title: Text(
S.of(context).selectTheQuantity,
textAlign: TextAlign.center,
),
),
],
);
});
}
}
here is shopping cart
class ShoppingCartRow extends StatelessWidget {
ShoppingCartRow(
{#required this.product,
#required this.quantity,
this.onRemove,
this.onChangeQuantity,
this.variation});
final Product product;
final ProductVariation variation;
final int quantity;
final Function onChangeQuantity;
final VoidCallback onRemove;
#override
Widget build(BuildContext context) {
String currency = Provider.of<AppModel>(context).currency;
final currencyRate = Provider.of<AppModel>(context).currencyRate;
final price = Services()
.widget
.getPriceItemInCart(product, variation, currencyRate, currency);
final imageFeature = variation != null && variation.imageFeature != null
? variation.imageFeature
: product.imageFeature;
int maxQuantity = kCartDetail['maxAllowQuantity'] ?? 100;
int totalQuantity = variation != null
? (variation.stockQuantity ?? maxQuantity)
: (product.stockQuantity ?? maxQuantity);
int limitQuantity =
totalQuantity > maxQuantity ? maxQuantity : totalQuantity;
ThemeData theme = Theme.of(context);
return LayoutBuilder(
builder: (context, constraints) {
return Column(children: [
Row(
key: ValueKey(product.id),
crossAxisAlignment: CrossAxisAlignment.center,
children: [
if (onRemove != null)
IconButton(
icon: Icon(Icons.remove_circle_outline),
onPressed: onRemove,
),
Expanded(
child: Padding(
padding: const EdgeInsets.only(right: 16.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Stack(children: <Widget>[
Container(
width: constraints.maxWidth * 0.25,
height: constraints.maxWidth * 0.3,
child: Tools.image(url: imageFeature)),
Positioned(
bottom: 0,
right: 0,
child: Container(
decoration: BoxDecoration(
border: Border.all(width: 1.0, color: kGrey200),
color: Theme.of(context).backgroundColor,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(2.0)),
),
child: QuantitySelection(
width: 60,
height: 32,
color: Theme.of(context).accentColor,
limitSelectQuantity: limitQuantity,
value: quantity,
onChanged: onChangeQuantity,
),
),
)
]),
SizedBox(width: 16.0),
Expanded(
child: Container(
),
),
Expanded(
child: Container(
height: constraints.maxWidth * 0.3,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
product.name,
style: TextStyle(
color: theme.accentColor,
),
maxLines: 4,
overflow: TextOverflow.ellipsis,
),
SizedBox(height: 7),
Text(
price,
style: TextStyle(
color: theme.accentColor, fontSize: 14),
),
SizedBox(height: 10),
variation != null
? Services()
.widget
.renderVariantCartItem(variation)
: Container(),
],
),
),
),
],
),
),
),
],
),
SizedBox(height: 10.0),
Divider(color: kGrey200, height: 1),
SizedBox(height: 10.0),
]);
},
);
}
}

I think having an editable number field with plus and minus button would be a nice and user-friendly solution. There's a number of ways to do this with flutter - check out the solutions in this thread for ideas.

Related

How i can create dropdown like this in flutter

Hey guys I'm working on some project and need to create a custom dropdown,
like this
I am able to make that here is the code, the code is messy but I will refactor it once I make it work. Or if you have some other way how I can accomplish this I'm open to suggestions.
GlobalKey? actionKey = GlobalKey();
List<String> picked = [];
List<IconData> icons = [
Icons.blur_circular_outlined,
Icons.sports_basketball,
Icons.sports_baseball_sharp,
Icons.sports_tennis_rounded,
Icons.people,
];
List<String> sports = [
"Fudbal",
"Kosarka",
"Tenis",
"Stoni tenis",
"Kuglanje"
];
List<int> ints = [0, 1, 2, 3, 4];
List<bool> booles = [false, false, false, false, false];
OverlayEntry? overlayEntry;
var position;
double? y;
double? x;
void findDropdownData() {
RenderBox renderBox =
actionKey!.currentContext!.findRenderObject() as RenderBox;
position = renderBox.localToGlobal(Offset.zero);
y = position!.dy;
x = position!.dx;
}
OverlayEntry _overlayEntryBuilder() {
return OverlayEntry(
builder: (context) {
return Positioned(
// top: position,
left: 16.w,
right: 16.w,
child: Material(
child: dropdownExpanded(),
),
);
},
);
}
Widget buildRows(i) {
return Padding(
padding: EdgeInsets.symmetric(horizontal: 17.w, vertical: 15.h),
child: Row(
children: [
SizedBox(
height: 24.h,
width: 24.w,
child: Checkbox(
activeColor: style.purpleMain,
value: booles[i],
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(4)),
onChanged: (value) {
setState(() {
booles[i] = value!;
booles[i] == true
? picked.add(sports[i])
: picked.remove(sports[i]);
});
},
),
),
SizedBox(
width: 10.w,
),
Text(
sports[i],
style: TextStyle(
color: booles[i] == true ? style.purpleMain : Colors.grey,
),
),
const Spacer(),
Icon(
icons[i],
color: booles[i] == true ? style.purpleMain : Colors.grey,
size: 15,
),
],
),
);
}
Widget dropdown() {
return GestureDetector(
key: actionKey,
onTap: () {
setState(() {
isPressed = !isPressed;
});
if (isPressed == false) {
overlayEntry = _overlayEntryBuilder();
Overlay.of(context)!.insert(overlayEntry!);
}
},
child: Container(
width: double.infinity,
height: 50.h,
decoration: BoxDecoration(
border: Border.all(color: style.e8e8e8),
borderRadius: BorderRadius.circular(8),
),
padding: EdgeInsets.only(left: 16.w, right: 13.w),
child: Row(
children: [
picked.isEmpty ? pickedEmpty() : pickedNotEmpty(),
const Spacer(),
const Icon(
Icons.arrow_drop_down,
color: style.bdbdbd,
),
],
),
),
);
}
Widget pickedEmpty() {
return Text(
"Možete obeležiti više aktivnosti",
style: TextStyle(
fontSize: 16.sp,
color: style.bdbdbd,
fontWeight: FontWeight.w400,
),
);
}
Widget pickedNotEmpty() {
List<Widget> list = <Widget>[];
for (var i = 0; i < picked.length; i++) {
list.add(
Padding(
padding: EdgeInsets.only(right: 5.w),
child: Text(
picked[i],
style: TextStyle(
fontSize: 16.sp,
color: style.bdbdbd,
fontWeight: FontWeight.w400,
),
),
),
);
}
return Row(children: list);
}
Widget dropdownExpanded() {
return Container(
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(color: style.purpleMain),
borderRadius: BorderRadius.circular(8),
),
child: Column(
children: [
GestureDetector(
onTap: () {
setState(() {
isPressed = !isPressed;
});
overlayEntry?.remove();
},
child: Container(
width: double.infinity,
height: 50.h,
padding: EdgeInsets.only(left: 16.w, right: 13.w),
child: Row(
children: [
picked.isEmpty ? pickedEmpty() : pickedNotEmpty(),
const Spacer(),
const Icon(
Icons.arrow_drop_up,
color: style.bdbdbd,
),
],
),
),
),
const Divider(
height: 0,
thickness: 1,
color: style.e8e8e8,
indent: 17,
endIndent: 17,
),
Column(
children: [
for (int i in ints) buildRows(i),
],
),
],
),
);
}
Here are results
This is what I want to accomplish
So I just want to move down this expanded dropdown and how to update these booles in the overlay if I don't use overlay it's working as it should but I need to open that dropdown on the top of another content. Thanks for the help.
Use smart_select it is fully customizable and you can achieve the design you want easily using this library.
Updated Answer
Regarding the UI, it is like an Expansions Tile Widget in flutter. You can implement that dropdown with expansions tile and pass list of items in children,
for expand, collapse tile after select each item, you can create a global key and control that in UI.
final GlobalKey<AppExpansionTileState> expansionTile = new GlobalKey();
collapse → expansionTile.currentState.collapse();
ExpansionTile(
title: Text(
"Možete obeležiti više aktivnosti",
style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.w500),
),
children: <Widget>[
// put items here
],
),
smaple :
Widget customDropDown() => Container(
// color: Colors.white,
padding: const EdgeInsets.all(10),
child: ListTileTheme(
dense: true,
child: ExpansionTile(
title: const Text(
"Možete obeležiti više aktivnosti",
style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.w500),
),
children: <Widget>[
Container(
width: double.infinity,
decoration: const BoxDecoration(
color: Colors.white,
borderRadius:
BorderRadius.vertical(bottom: Radius.circular(20))),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: const [
ListTile(
leading: Icon(Icons.ac_unit),
title: Text("something"),
),
ListTile(
leading: Icon(Icons.ac_unit),
title: Text("something"),
),
ListTile(
leading: Icon(Icons.ac_unit),
title: Text("something"),
),
ListTile(
leading: Icon(Icons.ac_unit),
title: Text("something"),
)
],
),
),
)
],
),
),
);
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
body: SafeArea(
child: Stack(
children: [pageDesign(), customDropDown()],
),
),
),
);
}
fakeWidget(color) => Container(
height: 100,
width: double.infinity,
color: color,
child: const Center(
child: Text("widget1"),
),
);
Widget pageDesign() => Column(
children: [
/* you should control this size in diffrent orientation and for big size
device to handle responsive
*/
const SizedBox(
height: 80,
),
fakeWidget(
Colors.green,
),
fakeWidget(
Colors.yellow,
),
fakeWidget(
Colors.orange,
),
fakeWidget(
Colors.blue,
),
],
);

Using TabBarView with DraggableScrollableSheet in Flutter

I am developing a city travel guide application for my project. In this project, I have page like this:
Screenshot
In this page, I want to make the container with red border scrollable vertically until green line with DraggableScrollableSheet . And also I want to add TabBarView to the same container and scroll horizontally.
But I can not handle, encountered with many render errors.
How can i fix this?
Here is the full code:
import 'package:after_layout/after_layout.dart';
import 'package:flutter/material.dart';
class CategoryScreen extends StatefulWidget {
final double _expandedBottomSheetBottomPosition = 0;
final townimage;
const CategoryScreen({Key key, this.townimage}) : super(key: key);
#override
_CategoryScreen createState() => _CategoryScreen(
townimage: this.townimage,
);
}
class _CategoryScreen extends State<CategoryScreen>
with TickerProviderStateMixin, AfterLayoutMixin<CategoryScreen> {
var townimage;
_CategoryScreen({this.townimage});
double _bottomSheetBottomPosition = -330;
bool isCollapsed = false;
TabController _tabController;
#override
void initState() {
super.initState();
_tabController = TabController(length: 2, vsync: this);
}
#override
Widget build(BuildContext context) {
return Scaffold(
extendBodyBehindAppBar: true,
appBar: AppBar(elevation: 0, backgroundColor: Colors.transparent),
body: Container(
child: Stack(
fit: StackFit.expand,
children: <Widget>[
Hero(
tag: "image" + townimage,
child: Image.asset(
"images/photos/turkey.jpg",
fit: BoxFit.cover,
)),
AnimatedPositioned(
duration: const Duration(milliseconds: 500),
curve: Curves.decelerate,
bottom: _bottomSheetBottomPosition,
left: 0,
right: 0,
child: Column(
children: [
_tabBar(),
Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.red, width: 3.0),
color: Theme.of(context).canvasColor,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(40),
topRight: Radius.circular(40),
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
alignment: Alignment.centerLeft,
padding: const EdgeInsets.symmetric(horizontal: 32),
height: 90,
child: Row(
children: [
Text(
"Historical Places",
style: TextStyle(
fontSize: 28.0,
color: Colors.white,
fontWeight: FontWeight.bold),
),
],
),
),
SingleChildScrollView(
physics: ScrollPhysics(),
child: _clipsWidget(),
),
],
),
),
],
),
),
],
),
),
);
}
Widget _clipsWidget() {
return Container(
color: Theme.of(context).canvasColor,
height: 250,
margin: const EdgeInsets.symmetric(horizontal: 16),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.account_balance_rounded),
Text("I want to add TabBarView to this area"),
Text(
"Some Future Builder elements will be implemented.",
)
],
),
));
}
#override
void afterFirstLayout(BuildContext context) {
Future.delayed(const Duration(milliseconds: 500), () {
setState(() {
isCollapsed = true;
_bottomSheetBottomPosition = widget._expandedBottomSheetBottomPosition;
});
});
}
Widget _tabBar() {
return TabBar(
controller: _tabController,
indicatorColor: Colors.transparent,
isScrollable: true,
labelColor: Colors.white,
unselectedLabelColor: Colors.grey,
labelPadding: EdgeInsets.symmetric(horizontal: 10),
tabs: [
Container(
height: 70,
child: Tab(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
margin: EdgeInsets.all(5),
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(100),
color: Theme.of(context).canvasColor.withOpacity(0.8),
),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Icon(
Icons.account_balance_rounded,
),
),
),
],
)),
),
Container(
height: 70,
child: Tab(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
margin: EdgeInsets.all(5),
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(100),
color: Theme.of(context).canvasColor.withOpacity(0.8),
),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Icon(
Icons.park,
),
),
),
],
)),
),
]);
}
}

Flutter chat bubble text not aligned

I'm using Flutter to build a Chat Application.
In my message bubbles, I display the message text, the date, and an icon to show if the message was read or not. The text of the message is poorly displayed. It goes to the next line after just one or two words instead of filling the full width of the bubble.
Container(
padding: EdgeInsets.symmetric(
horizontal: 15.0, vertical: 10.0),
width: MediaQuery.of(context).size.width * 0.65,
margin: EdgeInsets.only(top: 8.0, bottom: 8.0, left: 80.0, right: 10),
decoration: BoxDecoration(
color: primaryColor.withOpacity(.1),
borderRadius: BorderRadius.circular(20)),
child: Column(
children: <Widget>[
Row(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded(
child: Container(
child: Text(
documentSnapshot.data['text'],
style: TextStyle(
color: Colors.black87,
fontSize: 16.0,
fontWeight: FontWeight.w600,
),
),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Text(
documentSnapshot.data["time"] != null
? DateFormat.MMMd().add_jm()
.format(documentSnapshot.data["time"].toDate())
.toString()
: "",
style: TextStyle(
color: secondryColor,
fontSize: 13.0,
fontWeight: FontWeight.w600,
),
),
SizedBox(width: 5),
documentSnapshot.data['isRead'] == false
? Icon(
Icons.done,
color: secondryColor,
size: 15,
)
: Icon(
Icons.done_all,
color: primaryColor,
size: 15,
)
],
),
Short answer
Currently, you are using a Row Widget to display the message text as the first child and then the date and read icon as the second child:
Instead, you should use a Column Widget.
Full solution
After going back and forth with Julien
1. Domain Layer
class ChatEntry {
final String text;
final DateTime date;
final bool read;
final bool sent;
ChatEntry({
this.text,
this.date,
this.read,
this.sent,
});
}
2. Chat Bubble
class Bubble extends StatelessWidget {
final ChatEntry entry;
const Bubble({Key key, this.entry}) : super(key: key);
#override
Widget build(BuildContext context) {
return Align(
alignment: entry.sent ? Alignment.centerRight : Alignment.centerLeft,
child: Container(
padding: kBubblePadding,
decoration: BoxDecoration(
color: (entry.sent ? kSentColor : kReceivedColor)
.withOpacity(entry.read ? kReadOpacity : 1),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(kBorderRadius),
topRight: Radius.circular(kBorderRadius),
bottomRight: Radius.circular(entry.sent ? 0.0 : kBorderRadius),
bottomLeft: Radius.circular(entry.sent ? kBorderRadius : 0.0),
),
),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment:
entry.sent ? CrossAxisAlignment.end : CrossAxisAlignment.start,
children: <Widget>[
Text(entry.text, style: kBubbleTextStyle),
Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(
DateFormat('MMMd – kk:mm').format(entry.date),
style: TextStyle(fontSize: kBubbleMetaFontSize),
),
if (entry.read) ...[
const SizedBox(width: 5),
Icon(Icons.done, size: kBubbleMetaFontSize)
]
],
),
],
),
),
);
}
}
3. Chat Conversation
class Conversation extends StatelessWidget {
final List<ChatEntry> entries;
const Conversation({Key key, this.entries}) : super(key: key);
#override
Widget build(BuildContext context) {
return Column(
children: entries
.map(
(entry) => Padding(
padding: const EdgeInsets.all(8.0),
child: Bubble(entry: entry),
),
)
.toList(),
);
}
}
4. Application
void main() {
runApp(
MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Chat Demo',
home: Scaffold(
body: SingleChildScrollView(
child: Conversation(entries: getChatEntries()),
),
),
),
);
}
Full Source Code for easy copy-paste
Together with random data generation.
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:faker/faker.dart';
void main() {
runApp(
MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Chat Demo',
home: Scaffold(
body: SingleChildScrollView(
child: Conversation(entries: getChatEntries()),
),
),
),
);
}
class Conversation extends StatelessWidget {
final List<ChatEntry> entries;
const Conversation({Key key, this.entries}) : super(key: key);
#override
Widget build(BuildContext context) {
return Column(
children: entries
.map(
(entry) => Padding(
padding: const EdgeInsets.all(8.0),
child: Bubble(entry: entry),
),
)
.toList(),
);
}
}
class Bubble extends StatelessWidget {
final ChatEntry entry;
const Bubble({Key key, this.entry}) : super(key: key);
#override
Widget build(BuildContext context) {
return Align(
alignment: entry.sent ? Alignment.centerRight : Alignment.centerLeft,
child: Container(
padding: kBubblePadding,
decoration: BoxDecoration(
color: (entry.sent ? kSentColor : kReceivedColor)
.withOpacity(entry.read ? kReadOpacity : 1),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(kBorderRadius),
topRight: Radius.circular(kBorderRadius),
bottomRight: Radius.circular(entry.sent ? 0.0 : kBorderRadius),
bottomLeft: Radius.circular(entry.sent ? kBorderRadius : 0.0),
),
),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment:
entry.sent ? CrossAxisAlignment.end : CrossAxisAlignment.start,
children: <Widget>[
Text(entry.text, style: kBubbleTextStyle),
Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(
DateFormat('MMMd – kk:mm').format(entry.date),
style: TextStyle(fontSize: kBubbleMetaFontSize),
),
if (entry.read) ...[
const SizedBox(width: 5),
Icon(Icons.done, size: kBubbleMetaFontSize)
]
],
),
],
),
),
);
}
}
// DOMAIN
class ChatEntry {
final String text;
final DateTime date;
final bool read;
final bool sent;
ChatEntry({
this.text,
this.date,
this.read,
this.sent,
});
}
// CONFIG
const kSentColor = Color(0xff03bd85);
const kReceivedColor = Color(0xff0251d6);
const kReadOpacity = .3;
const kBorderRadius = 15.0;
const kBubblePadding = const EdgeInsets.symmetric(
horizontal: 15.0,
vertical: 10.0,
);
const kBubbleTextStyle = const TextStyle(
color: Colors.black87,
fontSize: 16.0,
fontWeight: FontWeight.w600,
);
const kBubbleMetaFontSize = 11.0;
// RANDOM DATA
final Random random = Random.secure();
final faker = new Faker();
List<ChatEntry> getChatEntries() {
final nbMessages = random.nextInt(17) + 3;
final lastRead = random.nextInt(nbMessages);
DateTime date = DateTime.now();
return List.generate(
nbMessages,
(index) {
date = date.subtract(Duration(minutes: random.nextInt(30)));
return ChatEntry(
text: faker.lorem
.words(2 + random.nextInt(random.nextBool() ? 3 : 15))
.join(' '),
date: date,
read: index >= lastRead,
sent: random.nextBool(),
);
},
).reversed.toList();
}

why unnecessary values overriding when calculating total in flutter

when i try to increase the quantity the total amount showing big numbers and when i exit the page and reenter it showing correct out put why this happenning...?this happens when i increase or decrease the quantity
this happens when i exit the page and reenter
import 'package:flutter/material.dart';
import 'package:hive/hive.dart';
import 'package:appnew/src/hivedatabase/cart_model.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:appnew/src/widgets/totalprice.dart';
List<String> compnme = List();
List<String> compqnt = List();
class CartPage extends StatefulWidget {
#override
_CartPageState createState() => _CartPageState();
}
class _CartPageState extends State<CartPage> {
double sum = 0;
final cartBox = Hive.box('carts');
final totBox = Hive.box('tot');
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 1,
backgroundColor: Colors.lightGreen,
title: Text(
'Cart',
),
),
body: _buildListView(),
bottomNavigationBar: Container(
color: Colors.white,
child: Row(
children: <Widget>[
Expanded(
child: _buildtotal(),
),
Expanded(
child: new MaterialButton(
onPressed: () {
final cartBox = Hive.box('carts');
cartBox.clear();
compnme.clear();
compqnt.clear();
totBox.clear();
},
child: new Text(
"Check Out",
style: TextStyle(color: Colors.white),
),
color: Colors.red,
)),
],
),
),
);
}
Widget _buildListView() {
// ignore: deprecated_member_use
return WatchBoxBuilder(
box: Hive.box('carts'),
builder: (context, cartBox) {
return ListView.builder(
itemCount: cartBox.length,
itemBuilder: (BuildContext context, int index) {
final cartModel = cartBox.getAt(index) as CartModel;
double iprice = double.parse(cartModel.price);
double nprice = 0;
int iquant = int.parse(cartModel.quantitys);
return Card(
elevation: 5,
child: Container(
height: 130,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
height: 129,
width: 125,
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(cartModel.img),
fit: BoxFit.fill,
),
),
),
Container(
height: 130,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: const EdgeInsets.fromLTRB(0, 10, 0, 5),
child: Text(
cartModel.pname,
style: TextStyle(fontSize: 20),
),
),
Padding(
padding: EdgeInsets.fromLTRB(0, 4, 0, 3),
child: Container(
width: 160,
child: Text(cartModel.curquant,
style: TextStyle(fontSize: 17)),
),
),
Padding(
padding: EdgeInsets.fromLTRB(1, 25, 0, 0),
child: Text("Rs." + cartModel.price,
style: TextStyle(
fontSize: 19, color: Colors.black54)),
)
],
),
),
Padding(
padding: const EdgeInsets.fromLTRB(0, 77, 19, 2),
child: Container(
height: 90,
child: IconButton(
icon: Icon(Icons.add_circle,
size: 35, color: Colors.green[300]),
onPressed: () {
iquant++;
nprice = iprice + (iprice / (iquant - 1));
cartBox.putAt(
index,
CartModel(
cartModel.pname,
cartModel.curquant,
cartModel.img,
nprice.toString(),
iquant.toString()));
}),
),
),
Padding(
padding: const EdgeInsets.fromLTRB(0, 77, 0, 2),
child: Container(
height: 90,
child: CircleAvatar(
backgroundColor: Colors.grey[300],
maxRadius: 16,
child: Text(cartModel.quantitys),
),
),
),
Padding(
padding: const EdgeInsets.fromLTRB(19, 77, 0, 2),
child: Container(
height: 90,
child: IconButton(
icon: Icon(Icons.remove_circle,
size: 35, color: Colors.redAccent),
onPressed: () {
if (iquant == 1) {
cartBox.deleteAt(index);
print(compnme[index]);
compnme.removeAt(index);
compqnt.removeAt(index);
} else {
iquant--;
nprice = iprice - (iprice / (iquant + 1));
cartBox.putAt(
index,
CartModel(
cartModel.pname,
cartModel.curquant,
cartModel.img,
nprice.toString(),
iquant.toString()));
}
}),
),
)
],
),
),
);
},
);
},
);
}
Widget _buildtotal() {
// ignore: deprecated_member_use
return WatchBoxBuilder(
box: Hive.box('carts'),
builder: (context, cartBox) {
for (int i = 0; i < cartBox.length; i++) {
final cartModel = cartBox.getAt(i) as CartModel;
double iprice = double.parse(cartModel.price);
sum += iprice;
print(sum);
}
return ListTile(
title: new Text("total:", style: TextStyle(color: Colors.black)),
subtitle: new Text(sum.toString(),
style: TextStyle(
color: Colors.black,
fontSize: 16,
)),
);
});
}
}
i tried adding setState() in buttons and functions but it didnt worked
Just assign zero each time in _buildtotal() method
Widget _buildtotal() {
sum=0;//This will reset sum value zero before re-calculating total
// ignore: deprecated_member_use
return WatchBoxBuilder(
box: Hive.box('carts'),
builder: (context, cartBox) {
for (int i = 0; i < cartBox.length; i++) {
final cartModel = cartBox.getAt(i) as CartModel;
double iprice = double.parse(cartModel.price);
sum += iprice;
print(sum);
}
return ListTile(
title: new Text("total:", style: TextStyle(color: Colors.black)),
subtitle: new Text(sum.toString(),
style: TextStyle(
color: Colors.black,
fontSize: 16,
)),
);
});
}

Flutter: i get invalid argument(s) Error in flutter if i want to navigate to detail page

I want to navigate to detail page. But i get invalid argument error. In detail page, i try to get detail information from my online server. If i click on Hot reload button in android studio, the error disappear. Please, How can i do to fix this error ? Screenshoot of error
the error log :
════════ (2) Exception caught by widgets library ═══════════════════════════════════════════════════
Invalid argument(s): The source must not be null
The relevant error-causing widget was:
DetailArticlePage file:///C:/Users/abiboo/FlutterProject/projectname/lib/miledoo_widget/home.dart:515:39
//home.dart
return new Container(
margin: EdgeInsets.symmetric(vertical: 8.0),
height: 240.0,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: articledata.length,
itemBuilder: (BuildContext context,int index) {
return Padding(
padding: EdgeInsets.all(4),
child: InkWell(
onTap: (){
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) =>
DetailArticlePage(int.parse(articledata[index].idArt), articledata[index].designation)));
},
child: Container(
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
This is a piece of code for detail page who contain a method to get detail informaation from server
//detailpage.dart
import 'package:cached_network_image/cached_network_image.dart';
import 'package:f_miledoo/miledoo_widget/detail_boutique_page.dart';
import 'package:f_miledoo/miledoo_widget/panier_page.dart';
import 'package:f_miledoo/models/detail_article_models.dart';
import 'package:f_miledoo/models/panier_models.dart';
import 'package:f_miledoo/shared/constants.dart';
import 'package:f_miledoo/utils/database_helper.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import '../localisation_internationnalisation/localisation.dart';
import 'dart:async';
import 'package:http/http.dart' as http;
import 'dart:convert';
class DetailArticlePage extends StatefulWidget{
final int id_art;
final String art_desgnation;
DetailArticlePage(this.id_art, this.art_desgnation);
DetailArticlePages createState() => DetailArticlePages();
}
class DetailArticlePages extends State<DetailArticlePage> {
DatabaseHelper helper = DatabaseHelper();
PanierModel _panier = new PanierModel.withempty();
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
int qtecompter = 1;
double prixTotal = 0.0;
String aAfficher = "";
int taillePanier = 0;
String idArt;
String designation;
String descrip;
String prixUnit;
String prixUnit2;
String qteStock;
String idBou;
String lienPhoto;
String nomBou;
#override
void initState() {
// TODO: implement initState
super.initState();
getpanierTaille();
this.getRecapArticleData(widget.id_art, widget.art_desgnation);
}
getpanierTaille() async => taillePanier = await helper.getCount();
getRecapArticleData(int id_article, String nom_article) async {
final response = await http.get(BASE + "xxxxxxx?id_art="+ id_article.toString() +"&nom_art="+ nom_article);
if (response.statusCode == 200) {
final jsonResponse = json.decode(response.body);
TheDetailData myData = new TheDetailData.fromJson(jsonResponse);
for (var i = 0; i < myData.articledetail.list_recap_article.length; i++) {
idArt = myData.articledetail.list_recap_article[i].idArt;
designation = myData.articledetail.list_recap_article[i].designation;
descrip = myData.articledetail.list_recap_article[i].descrip;
prixUnit = myData.articledetail.list_recap_article[i].prixUnit;
prixUnit2 = myData.articledetail.list_recap_article[i].prixUnit2;
qteStock = myData.articledetail.list_recap_article[i].qteStock;
lienPhoto = myData.articledetail.list_recap_article[i].lienPhoto;
idBou = myData.articledetail.list_recap_article[i].idBou;
print("id_art = " + idArt + " designation = " + designation +
" prixUnit2 = " + prixUnit2 + " Qté = " + qteStock);
}
} else {
throw Exception("Failed to load Data");
}
}
Future<List<ListArtMemeCate>> _getSameArticleData(int id_article, String nom_article) async {
final response = await http.get(BASE + "xxxxxxx?id_art="+ id_article.toString() +"&nom_art="+ nom_article);
if (response.statusCode == 200) {
final jsonResponse = json.decode(response.body);
TheDetailData myData = new TheDetailData.fromJson(jsonResponse);
List<ListArtMemeCate> datas = [];
for (var i = 0; i < myData.articledetail.list_art_meme_cate .length; i++) {
datas.add(myData.articledetail.list_art_meme_cate[i]);
}
return datas;
} else {
throw Exception("Failed to load Data");
}
}
#override
Widget build(BuildContext context) {
int localStockQte = int.parse(qteStock);
double localPrixUnit2 = double.parse(prixUnit2.toString());
Widget article_afficher333 = FutureBuilder(
future: _getSameArticleData(widget.id_art, widget.art_desgnation),
builder: (context, snapshot) {
//if(snapshot.data != null){
if (snapshot.hasData) {
List<ListArtMemeCate> articledata = snapshot.data;
return new Container(
child: GridView.count(
shrinkWrap: true,
crossAxisCount: 2,
childAspectRatio: 0.7,
padding: EdgeInsets.only(top: 8, left: 6, right: 6, bottom: 12),
children: List.generate(articledata.length, (index){
return Container(
child: Card(
clipBehavior: Clip.antiAlias,
child: InkWell(
onTap: () {
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) =>
DetailArticlePage(int.parse(articledata[index].idArt) , articledata[index].designation)));
},
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
SizedBox(
height: (MediaQuery.of(context).size.width / 2 - 40),
width: double.infinity,
child: CachedNetworkImage(
fit: BoxFit.cover,
imageUrl: BASEIMAGES+articledata[index].lienPhoto,
placeholder: (context, url) => Center(
child: CircularProgressIndicator()
),
errorWidget: (context, url, error) => new Icon(Icons.image),
),
),
Padding(
padding: const EdgeInsets.only(top: 2.0),
child: ListTile(
title: Text((() {
if(articledata[index].designation.length >12){
return "${articledata[index].designation.substring(0, 12)}...";}
return "${articledata[index].designation}";
})(), style: TextStyle(fontWeight: FontWeight.bold, fontSize: 15.0, fontFamily: "Questrial")),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 2.0, bottom: 1),
child: Text(articledata[index].prixUnit2+" F CFA", style: TextStyle(
color: Theme.of(context).accentColor,
fontWeight: FontWeight.w700,
fontFamily: 'Questrial'
)),
),
],
),
],
),
),
)
],
),
),
),
);
}),
),
);
} else if (snapshot.hasError) {
return Container(
child: Center(
child: Text(
"Erreur de chargement. Verifier votre connexion internet"),
),
);
}
return new Center(
child: CircularProgressIndicator(),
);
},
);
setState(() {
_panier.nom_article = designation;
_panier.prixUnit2 = double.parse(prixUnit2);
_panier.image_article = lienPhoto;
_panier.prixTot = qtecompter*double.parse(prixUnit2);
_panier.quantite = qtecompter ;
_panier.id_article = int.parse(idArt);
});
void _incrementeQte(){
setState((){
if(qtecompter >= localStockQte){
qtecompter = localStockQte;
}
qtecompter++;
});
}
void _decrementeQte(){
setState((){
if(qtecompter <=1){
qtecompter = 1;
}else{
qtecompter--;
}
});
}
String _getPrixTotal(){
setState((){
prixTotal = qtecompter*localPrixUnit2;
aAfficher = prixTotal.toString();
});
return aAfficher;
}
void _ajouterPanier() async {
//s.addToCart(widget.article);
var result = await helper.addCart(_panier);
var result3 = await helper.getCount();
/*int result;
result = await helper.addCart(_panier);
if(result != 0)
print('STATUS Panier Save Successfully');*/
}
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(
title: Text("designation", style: TextStyle(color: Colors.white),),
iconTheme: new IconThemeData(color: Colors.white),
actions: <Widget>[
Stack(
children: <Widget>[
IconButton(
icon: Icon(Icons.shopping_cart, color: Colors.white, ),
onPressed: () {
//showAlertDialog(context);
Navigator.push(context, new MaterialPageRoute(builder: (context) => PanierPage()));
},
),
Container(
width: 25,
height: 25,
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(30),
),
alignment: Alignment.center,
child: Text(taillePanier.toString(),
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 12
),)
),
],
),
],
),
body: new ListView(
children: <Widget>[
new Container(
height: 240,
child: new Hero(tag: lienPhoto, child: new Material(
child: InkWell(
child: new Image.network(
BASEIMAGES + lienPhoto,
fit: BoxFit.cover),
),
)),
),
new Container(
child: new Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 10,left: 5),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
new Text(designation.toString(), style: new TextStyle(fontSize: 20.0, color: Colors.black, fontFamily: 'Questrial'),),
],
),
),
SizedBox(height: 10.0),
Padding(
padding: const EdgeInsets.only(left: 280),
child: new Text(prixUnit2.toString()+" F CFA", style: new TextStyle(fontSize: 15.0, color: Colors.black54, fontFamily: 'Questrial', fontWeight: FontWeight.bold),),
),
SizedBox(height: 10.0),
Padding(
padding: const EdgeInsets.only(left: 20, right: 20, bottom: 10),
child: new Text(descrip.toString(), style: new TextStyle(fontSize: 15.0, color: Colors.grey, fontFamily: 'Questrial'),),
),
SizedBox(height: 10.0),
new Container(
height: 100,
child: Column(
children: <Widget>[
Container(
height: 1.0,
color: Colors.grey,
),
Padding(
padding: const EdgeInsets.only(left: 25, right: 25, top: 20),
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(AppLocalizations.of(context)
.translate('_QUANTITY'), style: TextStyle(fontWeight: FontWeight.bold, fontSize: 15, fontFamily: 'Questrial'),),
Text(AppLocalizations.of(context)
.translate('_TOTAL_PRICE'), style: TextStyle(fontWeight: FontWeight.bold, fontSize: 15, fontFamily: 'Questrial'), ),
],
),
),
Padding(
padding: const EdgeInsets.only(left: 10, right: 25),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
new Row(
children: <Widget>[
new IconButton(
icon: Icon(Icons.remove_circle_outline, color: Colors.amber, ),
onPressed: _decrementeQte,
),
new Text("$qtecompter"),
new IconButton(
icon: Icon(Icons.add_circle_outline, color: Colors.amber, ),
onPressed: _incrementeQte,
),
],
),
new Text(_getPrixTotal()+" F CFA", style: new TextStyle(fontSize: 20.0, color: Colors.grey),),
],
),
),
Container(
height: 1.0,
color: Colors.grey,
),
],
),
),
//articleMemeCategorie()
],
),
),
Padding(
padding: const EdgeInsets.only(top: 10, left: 25, ),
child: Text(AppLocalizations.of(context)
.translate('_ITEMS_OF_SAME_QUATEGORY'), style: TextStyle(fontFamily: 'Questrial', fontSize: 15, fontWeight: FontWeight.bold),),
),
article_afficher333,
],
),
bottomNavigationBar: new Container(
color: Colors.white,
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded(child: new MaterialButton(
onPressed: (){showAlertDialog(context);},
child: new Row(
//crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
IconButton(
//widget.article
icon: Icon(Icons.store, color: Colors.white,),
onPressed: () {
//showAlertDialog(context);
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) =>
DetailBoutiquePage(int.parse(idBou)))); },
),
],
),
color: Color(0xFFFFC23A),
),),
Expanded(
flex: 2,
child: new MaterialButton(
onPressed: (){
_ajouterPanier();
},
child: new Container(
child: new Row(
children: <Widget>[
IconButton(
icon: Icon(Icons.add_shopping_cart, color: Colors.white,),
),
Text(AppLocalizations.of(context)
.translate('_ADD_TO_CART'), style: TextStyle(color: Color(0xFFFFFFFF)))
],
),
),
color: Color(0xFFFFC23A),
),),
Expanded(child: new MaterialButton(
onPressed: (){showAlertDialog(context);},
child: new Text(AppLocalizations.of(context)
.translate('_BUY_NOW'), style: TextStyle(color: Color(0xFFFFFFFF)),),
color: Color(0xFFFFC23A),
),),
],
),
)
);
}
}
Without seeing your full detail page and error log it is difficult to tell exactly what your error is.
From the information you have given it sounds like you are trying to retrieve data from an Http request, and then use that information for the display of your page. Have you tried using a FutureBuilder in the detail page? This will allow you to display a page while waiting for the data from the server, and will then display the data from the server once it has been retrieved.

Categories

Resources