Related
am new to flutter, and stuck logically on this problem :
i have a dropdown menu where the user will choose a gate from,
then show the chosen gate in the google map.
i've tried having the longitude and latitudes as global vairiables, but it didn't work . as if google map widget doesn't see it after it changes,
i also tried passing the longitude and latitudes using the navigator, with this the attributes does change in the google map but the dropdown menu stops showing the chosen item in the front.
i just want to change the google map depending on the choice of the dropdown menu.
heres my full code
import 'package:flutter/src/widgets/container.dart';
import 'package:flutter/src/widgets/framework.dart';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import '../widgets/My_wedgits.dart';
// shmalyh 3 LatLng(21.489191114466923, 39.24285294444855)
//shmalyh 1 LatLng( 21.490190928284374, 39.24029335794148)
//west 2 LatLng(21.489312801215913, 39.239637004938416)
//double lat = 21.48880614639443;
//double leng = 39.24159501940586;
String dropdownvalue = "";
const List<String> gatelist = <String>[
'NorthGate 1',
'NorthGate 3',
'WestGate 2'
];
class homepage extends StatefulWidget {
//const homepage({super.key});
double lat;
double lan;
homepage({Key? mykey, required this.lan, required this.lat})
: super(key: mykey);
#override
State<homepage> createState() => _homepageState();
}
class _homepageState extends State<homepage> {
DropdownButtonExample mydropdown = DropdownButtonExample();
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
toolbarHeight: 60,
centerTitle: true,
title: const Text(
'Wajeeh',
style: TextStyle(
fontSize: 28,
),
),
elevation: 10,
backgroundColor: const Color.fromARGB(255, 4, 105, 55),
leading: Padding(
padding: const EdgeInsets.all(6.0),
child: Image.asset(
'images/logo2.png',
height: 30,
),
),
),
backgroundColor: Colors.white,
body: Column(
children: [
const SizedBox(
height: 70,
),
Row(
// ignore: prefer_const_literals_to_create_immutables
children: [
Expanded(
child: Align(
alignment: Alignment.topCenter,
child: SizedBox(
width: 250,
child: mydropdown,
),
)),
],
),
const SizedBox(
height: 45,
),
Row(
children: [
Expanded(
child: Column(
children: [
Image.asset('images/full.jpg'),
const Text(
'Total Parking',
style: TextStyle(
fontSize: 22.0,
fontWeight: FontWeight.bold,
color: Color.fromARGB(255, 0, 0, 0)),
),
const Text(
'33',
style: TextStyle(
fontSize: 22.0,
fontWeight: FontWeight.bold,
color: Color.fromARGB(255, 4, 105, 55)),
),
],
)),
Expanded(
child: Column(
children: [
Image.asset('images/remain.jpg'),
const Text(
'Available Parking',
style: TextStyle(
fontSize: 22.0,
fontWeight: FontWeight.bold,
color: Color.fromARGB(255, 0, 0, 0)),
),
const Text(
"100",
style: TextStyle(
fontSize: 22.0,
fontWeight: FontWeight.bold,
color: Color.fromARGB(255, 4, 105, 55)),
),
],
))
],
),
//here where the map should be
const SizedBox(
height: 70,
),
Row(
// ignore: prefer_const_literals_to_create_immutables
children: [
Expanded(
child: Align(
alignment: Alignment.topCenter,
child: SizedBox(
width: 355,
height: 315,
child: Stack(
children: [
GoogleMap(
initialCameraPosition: CameraPosition(
target: LatLng(widget.lan, widget.lat),
zoom: 16,
),
),
Container(
alignment: Alignment.topLeft,
child: const Icon(
Icons.star,
color: Color.fromARGB(255, 231, 210, 23),
size: 40,
),
),
],
),
),
)),
],
),
],
));
}
// ignore: unused_element
}
class DropdownButtonExample extends StatefulWidget {
const DropdownButtonExample({super.key});
#override
State<DropdownButtonExample> createState() => _DropdownButtonExampleState();
/*Widget goodglemap() {
return GoogleMap(
initialCameraPosition: CameraPosition(
target: LatLng(lat, leng),
zoom: 16,
),
);
}*/
}
class _DropdownButtonExampleState extends State<DropdownButtonExample> {
double lat = 21.48880614639443;
double leng = 39.24159501940586;
String dropdownValue = gatelist.first;
// ignore: avoid_print
#override
Widget build(BuildContext context) {
return DropdownButton<String>(
hint: const Text("Choose a Gate"),
isExpanded: true,
value: dropdownValue,
icon: const Icon(Icons.arrow_drop_down_sharp),
style: const TextStyle(color: const Color.fromARGB(255, 4, 105, 55)),
underline: Container(
height: 2,
color: const Color.fromARGB(255, 4, 105, 55),
),
onChanged: (String? value) {
// This is called when the user selects an item.
setState(() {
dropdownValue = value!;
//see if i can reach the other classs from here
if (identical(dropdownValue, "NorthGate 1")) {
lat = 21.490190928284374;
leng = 39.24029335794148;
}
//see if i can reach the other classs from here
if (identical(dropdownValue, "NorthGate 3")) {
lat = 21.489191114466923;
leng = 39.24285294444855;
}
if (identical(dropdownValue, "WestGate 2")) {
lat = 21.489312801215913;
leng = 39.239637004938416;
}
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => homepage(lat: lat, lan: leng)));
});
},
items: gatelist.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(
value,
),
);
}).toList(),
);
}
Widget goodglemap() {
return GoogleMap(
initialCameraPosition: CameraPosition(
target: LatLng(lat, leng),
zoom: 16,
),
);
}
}
I have created a list of the widgets using JSON data, I have five types of widgets, and each widget is added to the list depending on the JSON data, but the issue is with the widget includes a text field, All widget displays ok but once I click on the text field the keyboard appears and disappears immediately and gives this error "Exception caught by widgets library" => "Incorrect use of ParentDataWidget."
I try removing everything and adding just this text field widget in the list, but it still not working right. Please guide me on where am doing wrong.
import 'dart:io';
import 'package:flutter/material.dart';
import 'dart:convert';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:my_car/AppUI/CustomWidgets/DateQuestionBox.dart';
import 'package:my_car/AppUI/CustomWidgets/MultiSelectQuestionBox.dart';
import 'package:my_car/AppUI/CustomWidgets/RadioQuestionBox.dart';
import 'package:my_car/AppUI/CustomWidgets/SelectQuestionBox.dart';
import 'package:my_car/AppUI/CustomWidgets/TextQuestionBox.dart';
import 'package:my_car/LocalData/AppColors.dart';
import 'package:flutter/services.dart';
import 'package:my_car/Models/MyClaimQuestionsResponse.dart';
import 'package:my_car/Models/VehiclesResponse.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../../Models/VehiclesResponse.dart';
class SubmitClaimQuestionsPage extends StatefulWidget {
String vehicle;
String coverage;
SubmitClaimQuestionsPage(this.vehicle, this.coverage, {Key? key})
: super(key: key);
#override
SubmitClaimQuestionsState createState() =>
SubmitClaimQuestionsState(this.coverage, this.vehicle);
}
class SubmitClaimQuestionsState extends State {
String vehicle;
String coverage;
SubmitClaimQuestionsState(this.coverage, this.vehicle);
Future getMyVehicles() async {
final prefs = await SharedPreferences.getInstance();
final String? action = prefs.getString('vehiclesList');
VehiclesResponse myVehiclesResponse =
VehiclesResponse.fromJson(jsonDecode(action!));
return myVehiclesResponse.vehicles;
}
static List<MyCarClaimType> myCarClaims = <MyCarClaimType>[];
// Fetch content from the json file
Future generateQuestionsFromJson() async {
final String response = await rootBundle
.loadString('lib/Assets/JsonDataFiles/MyCarDataClaimQuestions.json');
MyClaimQuestionsResponse myClaimQuestionsResponse =
MyClaimQuestionsResponse.fromJson(jsonDecode(response));
if (myClaimQuestionsResponse.myCarClaimTypes.isNotEmpty) {
myCarClaims.clear();
myCarClaims = myClaimQuestionsResponse.myCarClaimTypes
.where((element) =>
element.claimType.toLowerCase() == coverage.toLowerCase())
.toList();
}
if (myCarClaims.isNotEmpty) {
setState(() {
for (var i = 0; i < myCarClaims.length; i++) {
if (myCarClaims[i].questionType == "TEXT") {
allQuestions.add(TextQuestionBox(myCarClaims[i]));
} else if (myCarClaims[i].questionType == "SELECT") {
allQuestions.add(SelectQuestionBox(myCarClaims[i]));
} else if (myCarClaims[i].questionType == "RADIO") {
allQuestions.add(RadioQuestionBox(myCarClaims[i]));
} else if (myCarClaims[i].questionType == "MULTI_SELECT") {
allQuestions.add(MultiSelectQuestionBox(myCarClaims[i]));
} else if (myCarClaims[i].questionType == "DATE") {
allQuestions.add(DateQuestionBox(myCarClaims[i]));
}
}
});
}
return allQuestions;
}
#override
void initState() {
super.initState();
generateQuestionsFromJson();
}
bool isVehicleSelected = false;
// ignore: unused_field
List<Widget> allQuestions = <Widget>[];
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
fontFamily: 'Lato',
),
home: Scaffold(
backgroundColor: Color(AppColors.bgColor),
body: SafeArea(
child: SingleChildScrollView(
physics: const ClampingScrollPhysics(),
child: Container(
margin: const EdgeInsets.only(top: 30, bottom: 20),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
margin: const EdgeInsets.only(
bottom: 15,
left: 20,
right: 20,
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
GestureDetector(
onTap: () {
Navigator.of(context).pop();
},
child: Align(
alignment: Alignment.centerLeft,
child: SvgPicture.asset(
'lib/Assets/Images/backarrow.svg',
height: 20,
)),
),
Expanded(
child: Column(
children: [
Align(
alignment: Alignment.center,
child: Padding(
padding: const EdgeInsets.only(right: 20),
child: Text(
vehicle,
textAlign: TextAlign.start,
style: const TextStyle(
fontSize: 18,
letterSpacing: -0.5,
fontWeight: FontWeight.w700,
),
),
),
),
Align(
alignment: Alignment.center,
child: Padding(
padding: const EdgeInsets.only(right: 20),
child: Text(
coverage,
textAlign: TextAlign.start,
style: TextStyle(
fontSize: 13,
fontWeight: FontWeight.w500,
color: Color(AppColors.primaryBlueColor)),
),
),
),
],
)),
],
),
),
Flexible(
fit: FlexFit.loose,
child: ListView.builder(
physics: const ClampingScrollPhysics(),
shrinkWrap: true,
key: UniqueKey(),
itemCount: allQuestions.length,
itemBuilder: (BuildContext context, int index) {
return allQuestions[index];
},
),
),
const SizedBox(
width: 20,
),
],
),
),
Container(
width: double.infinity,
margin: const EdgeInsets.only(
left: 20,
right: 20,
top: 15,
),
child: TextButton(
style: ButtonStyle(
padding: MaterialStateProperty.all(
const EdgeInsets.symmetric(vertical: 16)),
backgroundColor: MaterialStateProperty.all(
Color(AppColors.primaryBlueColor)),
shape:
MaterialStateProperty.all<RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
)),
),
child: Text(
'Submit Claim',
style: TextStyle(
fontWeight: FontWeight.w500,
fontSize: 15,
color:
Color(AppColors.primaryWhiteButtomTextColor)),
),
onPressed: () {},
),
),
],
),
),
),
),
),
);
}
}
My TextFeild widget is this:
import 'package:flutter/material.dart';
import 'package:my_car/LocalData/AppColors.dart';
import 'package:my_car/Models/MyClaimQuestionsResponse.dart';
class TextQuestionBox extends StatefulWidget {
MyCarClaimType claimObj;
TextQuestionBox(this.claimObj, {Key? key}) : super(key: key);
#override
State<StatefulWidget> createState() {
return TextQuestionBoxState(claimObj);
}
}
class TextQuestionBoxState extends State<TextQuestionBox> {
MyCarClaimType claimObj;
TextQuestionBoxState(this.claimObj);
TextEditingController txtControler = TextEditingController();
Widget get questionTxtBox {
return Container(
//width: double.infinity,
//height: 200,
margin: const EdgeInsets.symmetric(horizontal: 10),
padding: const EdgeInsets.all(10),
child: Column(
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"${claimObj.order + 1}. ",
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.w700,
),
),
Expanded(
child: Text.rich(
//softWrap: false,
//overflow: TextOverflow.fade,
TextSpan(
text: claimObj.question,
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.w700,
),
children: <InlineSpan>[
TextSpan(
text: claimObj.isMandatory == "YES" ? "*" : "",
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w700,
color: Color(AppColors.primaryBlueColor)),
),
])),
),
],
),
const SizedBox(
height: 10,
),
Container(
height: 110,
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(15))),
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Expanded(
child: TextField(
controller: txtControler,
keyboardType: TextInputType.multiline,
//maxLines: null,
style: const TextStyle(
fontSize: 14, fontWeight: FontWeight.w500),
decoration: const InputDecoration(
border: InputBorder.none,
filled: true,
fillColor: Colors.transparent,
hintText: 'Description',
),
),
),
Container(
margin: const EdgeInsets.only(bottom: 10, right: 15),
child: Text(
'Min. 40 Letters',
style: TextStyle(
fontSize: 10,
fontWeight: FontWeight.w500,
color: Color(AppColors.greyText)),
))
],
)),
],
),
);
}
#override
Widget build(BuildContext context) {
return questionTxtBox;
}
}
TextFields usually try to expand to the available width. This can be problematic in a Column where usually only height is fixed and the Textfield tries to expand into infinity. You should try wrapping the TextField in a Widget that gives it a fixed width like a SizedBox.
Need to display icon with checkmark based on a String value that comes dynamically.
Like
this image is its pending show first widget with tick and rest are blank.
if delivered show with tick and the rest are blank.
Facing problems in creating logic using enums.
Currently, it displays the icons on button clicks
based on four constants which is fine with the widget CheckStatus.
Need to make in a way based on a boolean check if it's true and pending that pending tick widget displayed
and similar with other values.
Here is the complete code for it currently.
import 'package:dotted_border/dotted_border.dart';
import 'package:dotted_line/dotted_line.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:matab/models/order.dart';
import 'package:matab/ui/general_widgets/check_status.dart';
import 'package:matab/ui/pages/styles.dart';
import '../../general_widgets/custom_gradient_button.dart';
class TrackOrder extends StatefulWidget {
const TrackOrder({Key? key, required this.order}) : super(key: key);
final Order order;
#override
State<TrackOrder> createState() => _TrackOrderState();
}
enum Status { Pending, Confirmed, Shipped, Received }
class _TrackOrderState extends State<TrackOrder> {
static const darkGreyColor = Colors.grey;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Center(child: Text('Track Order')),
leading: IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () => Get.back(),
),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
const SizedBox(height: 50),
Text(
"Order ID:" + widget.order.orderID,
style: const TextStyle(
color: darkGreyColor,
fontSize: 18,
fontWeight: FontWeight.bold),
),
const SizedBox(height: 50),
const Text('Sat, 12 Mar 2022',
style: TextStyle(
color: darkGreyColor,
fontSize: 18,
fontWeight: FontWeight.bold)),
const SizedBox(
height: 15,
),
Container(
margin: const EdgeInsets.fromLTRB(15, 0, 0, 0),
child: const Text('Estimated Time: 07 Days',
style: TextStyle(fontSize: 23, fontWeight: FontWeight.bold)),
),
const SizedBox(height: 30),
SizedBox(
width: 200,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
OrderStatusBar(title: widget.order.orderStatus, status: true),
dottedLine(),
OrderStatusBar(
title: widget.order.orderStatus, status: false),
dottedLine(),
OrderStatusBar(
title: widget.order.orderStatus, status: false),
dottedLine(),
OrderStatusBar(
title: widget.order.orderStatus, status: false),
],
),
),
const SizedBox(
height: 40,
),
Container(
margin: const EdgeInsets.fromLTRB(15, 0, 0, 0),
child: const Text('Shipping Address',
style: TextStyle(fontSize: 23, fontWeight: FontWeight.bold)),
),
Center(
child: Text(widget.order.deliveryAddress.address,
style: const TextStyle(
color: Colors.grey,
fontSize: 18,
fontWeight: FontWeight.bold)),
),
Center(
child: Padding(
padding: const EdgeInsets.all(
50.0,
),
child: CustomGradientButton(
buttonText: "Track Order".tr, buttonFunction: () => {}),
),
),
Center(
child: Padding(
padding: const EdgeInsets.only(top: 18.0),
child: GestureDetector(
child: Text(
'Back to Home'.tr,
style: TextStyle(
color: mainColor,
fontSize: 23,
fontWeight: FontWeight.bold),
),
onTap: () => {
Get.off(CheckStatus(
order: widget.order,
))
},
),
),
)
],
),
),
);
}
}
class OrderStatusBar extends StatefulWidget {
const OrderStatusBar({Key? key, required this.title, required this.status})
: super(key: key);
final String title;
final bool status;
#override
State<OrderStatusBar> createState() => _OrderStatusBarState();
}
class _OrderStatusBarState extends State<OrderStatusBar> {
#override
Widget build(BuildContext context) {
return Directionality(
textDirection: TextDirection.rtl,
child: Row(
children: [
widget.status ? dottedCircleWithCheckMark() : dottedCircle(),
const SizedBox(width: 30),
Text(
widget.title.tr,
style: TextStyle(
fontSize: 20,
fontWeight: widget.status ? FontWeight.bold : null,
),
),
],
),
);
}
}
const size = 25.0;
const strokeWidth = 1.0;
const checkedColor = Color.fromRGBO(232, 113, 65, 1);
Widget dottedLine() {
return Directionality(
textDirection: TextDirection.rtl,
child: Align(
alignment: Alignment.topRight,
child: Container(
margin: const EdgeInsets.fromLTRB(0, 0, size / 2, 0),
child: const Padding(
padding: EdgeInsets.only(left: 27 / 2),
child: SizedBox(
height: size,
child: DottedLine(
dashColor: Colors.black,
direction: Axis.vertical,
lineLength: size,
lineThickness: strokeWidth,
dashLength: 5,
dashGapLength: 5,
),
),
),
),
),
);
}
dottedCircle() {
return DottedBorder(
borderType: BorderType.Circle,
dashPattern: const [5, 5],
child: Container(
height: size,
width: size,
decoration: const BoxDecoration(shape: BoxShape.circle),
));
}
dottedCircleWithCheckMark() {
return Container(
height: size + strokeWidth * 2,
width: size + strokeWidth * 2,
decoration: const BoxDecoration(
shape: BoxShape.circle,
color: checkedColor,
),
child: const Icon(
Icons.check,
color: Colors.white,
size: size / 4 * 3,
),
);
}
// ignore_for_file: constant_identifier_names
class CheckStatus extends StatefulWidget {
const CheckStatus({Key? key, required this.order}) : super(key: key);
final Order order;
#override
State<CheckStatus> createState() => _CheckStatusState();
}
class _CheckStatusState extends State<CheckStatus> {
int selectedItemIndex = 0;
var pending = Status.Pending;
List<bool> orderStatus = [true,true,true,false];
#override
void initState() {
// TODO: implement initState
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
for (int i = 0; i < Status.values.length; i++)
ElevatedButton(
onPressed: () {
selectedItemIndex = i;
setState(() {});
},
child: Text("Order Status ${Status.values[i]}"),
),
Row(
children: [
for (int i = 0; i <= selectedItemIndex; i++)
Container(
height: size + strokeWidth * 2,
width: size + strokeWidth * 2,
decoration: const BoxDecoration(
shape: BoxShape.circle,
color: checkedColor,
),
child: const Icon(
Icons.check,
color: Colors.white,
size: size / 4 * 3,
),
),
ElevatedButton(onPressed: () {}, child: Text("Back"))
],
)
],
),
);
}
}
function description: when an item is clicked, change the background color of this item 。
I defined the variable color in the List.generate function and used the setState function in onTapDown to modify this value, but it has no effect. what should I do?
my code is as follows
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
class Homepage extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Homepage> {
final titles = ["AAA", "BBB", "CCC", "DDD"];
final subtitles = [
"我去,额度这么高?",
"XX,你上次给我兑换的烤箱还不错哦",
"抱歉,我觉得我们不是很合适",
"邻居你好,你家的租户最近有点吵"
];
final date = ["昨天 18:08", "星期二", "7月21日", "7月19日"];
final avatar = [
"WechatIMG325.jpeg",
"WechatIMG326.jpeg",
"WechatIMG327.jpeg",
"WechatIMG328.jpeg"
];
// final icons = [Icons.ac_unit, Icons.access_alarm, Icons.access_time];
#override
Widget build(BuildContext context) {
return Column(
children: [
...List.generate(titles.length, (index) {
var color = Colors.white;
return GestureDetector(
behavior: HitTestBehavior.opaque,
onTapDown: (TapDownDetails details) {
setState(() {
color = Colors.grey;
});
debugPrint("presed GestureDetector");
},
onTapUp: (TapUpDetails details) {
setState(() {
color = Colors.white;
});
debugPrint("presed GestureDetector");
},
child: Container(
color: color,
margin: const EdgeInsets.fromLTRB(10, 0, 10, 0),
child: Row(children: [
SizedBox(
width: 50,
child: Container(
margin: const EdgeInsets.fromLTRB(0, 10, 0, 10),
child: ClipRRect(
borderRadius: BorderRadius.circular(5.0),
child: Image.asset("assets/images/${avatar[index]}",
height: 50, width: 50),
),
),
),
//const SizedBox(width: 10),
IntrinsicWidth(
child: Container(
margin: const EdgeInsets.fromLTRB(10, 0, 0, 0),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
titles[index],
style: const TextStyle(
fontSize: 18,
color: Colors.black,
fontWeight: FontWeight.w300,
),
),
const SizedBox(height: 5),
Text(
subtitles[index],
style: const TextStyle(
fontSize: 15,
color: Colors.black54,
fontWeight: FontWeight.w300,
),
),
],
),
),
),
]),
),
);
}),
],
);
}
}
try this code will help you to start in OOP and make model to data in your app and you can add any thing to class like Icon ....
class FakeData {
final String title, subTitle, avatar, data;
bool onTapDown;
FakeData(
{required this.title,
this.onTapDown = false,
required this.subTitle,
required this.avatar,
required this.data});
}
this class collect data app and state for all item
class HomeState extends State<Homepage> {
final fakeData = [
FakeData(
title: 'AAA',
subTitle: '我去,额度这么高?',
avatar: "WechatIMG325.jpeg",
data: "昨天 18:08",
),
FakeData(
title: 'BBB',
subTitle: "XX,你上次给我兑换的烤箱还不错哦",
avatar: "WechatIMG326.jpeg",
data: "星期二",
),
FakeData(
title: 'CCC',
subTitle: "抱歉,我觉得我们不是很合适",
avatar: "WechatIMG327.jpeg",
data: "7月21日",
),
FakeData(
title: 'DDD',
subTitle: "邻居你好,你家的租户最近有点吵",
avatar: "WechatIMG328.jpeg",
data: "7月19日",
),
];
// final icons = [Icons.ac_unit, Icons.access_alarm, Icons.access_time];
#override
Widget build(BuildContext context) {
return Column(
children: [
...List.generate(fakeData.length, (index) {
return GestureDetector(
behavior: HitTestBehavior.opaque,
onTapDown: (TapDownDetails details) {
setState(() {
fakeData[index].onTapDown = !fakeData[index].onTapDown;
});
debugPrint("presed GestureDetector");
},
onTapUp: (TapUpDetails details) {
setState(() {
fakeData[index].onTapDown = !fakeData[index].onTapDown;
});
debugPrint("presed GestureDetector");
},
child: Container(
color: fakeData[index].onTapDown ? Colors.grey : Colors.white,
margin: const EdgeInsets.fromLTRB(10, 0, 10, 0),
child: Row(children: [
SizedBox(
width: 50,
child: Container(
margin: const EdgeInsets.fromLTRB(0, 10, 0, 10),
child: ClipRRect(
borderRadius: BorderRadius.circular(5.0),
child: Image.asset(
"assets/images/${fakeData[index].avatar}",
height: 50,
width: 50),
),
),
),
//const SizedBox(width: 10),
IntrinsicWidth(
child: Container(
margin: const EdgeInsets.fromLTRB(10, 0, 0, 0),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
fakeData[index].title,
style: const TextStyle(
fontSize: 18,
color: Colors.black,
fontWeight: FontWeight.w300,
),
),
const SizedBox(height: 5),
Text(
fakeData[index].subTitle,
style: const TextStyle(
fontSize: 15,
color: Colors.black54,
fontWeight: FontWeight.w300,
),
),
],
),
),
),
]),
),
);
}),
],
);
}
}
The variable color needs to be outside the build method of the State, this code will reset the color to Colors.white on each build.
import 'package:flutter/material.dart';
class Homepage extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Homepage> {
final titles = ["AAA", "BBB", "CCC", "DDD"];
final subtitles = [
"我去,额度这么高?",
"XX,你上次给我兑换的烤箱还不错哦",
"抱歉,我觉得我们不是很合适",
"邻居你好,你家的租户最近有点吵"
];
final date = ["昨天 18:08", "星期二", "7月21日", "7月19日"];
final avatar = [
"WechatIMG325.jpeg",
"WechatIMG326.jpeg",
"WechatIMG327.jpeg",
"WechatIMG328.jpeg"
];
var color = Colors.white;
// final icons = [Icons.ac_unit, Icons.access_alarm, Icons.access_time];
#override
Widget build(BuildContext context) {
return Column(
children: [
...List.generate(titles.length, (index) {
return GestureDetector(
behavior: HitTestBehavior.opaque,
onTapDown: (TapDownDetails details) {
setState(() {
color = Colors.grey;
});
debugPrint("presed GestureDetector");
},
onTapUp: (TapUpDetails details) {
setState(() {
color = Colors.white;
});
debugPrint("presed GestureDetector");
},
child: Container(
color: color,
margin: const EdgeInsets.fromLTRB(10, 0, 10, 0),
child: Row(children: [
SizedBox(
width: 50,
child: Container(
margin: const EdgeInsets.fromLTRB(0, 10, 0, 10),
child: ClipRRect(
borderRadius: BorderRadius.circular(5.0),
child: Image.asset("assets/images/${avatar[index]}",
height: 50, width: 50),
),
),
),
//const SizedBox(width: 10),
IntrinsicWidth(
child: Container(
margin: const EdgeInsets.fromLTRB(10, 0, 0, 0),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
titles[index],
style: const TextStyle(
fontSize: 18,
color: Colors.black,
fontWeight: FontWeight.w300,
),
),
const SizedBox(height: 5),
Text(
subtitles[index],
style: const TextStyle(
fontSize: 15,
color: Colors.black54,
fontWeight: FontWeight.w300,
),
),
],
),
),
),
]),
),
);
}),
],
);
}
}
The code above should work as our state is extracted outside of the build method and it would update correctly with each setState.
when I am increasing my quantity of one product then all product's quantity is increasing, so how to solve it.
This is my product page:
import 'dart:convert';
import 'package:carousel_pro/carousel_pro.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:hospital/Authentication/LoginLogoutScreenPage/login.dart';
import 'package:hospital/CartPage/Cart_Api/cart_api.dart';
import 'package:hospital/CartPage/pages/cartPage.dart';
import 'package:hospital/Drawer/dropdown_menu.dart';
import 'package:hospital/ProductDetailsPage/product_detailPage.dart';
import 'package:hospital/ProductDetailsPage/related_product_page.dart';
import 'package:hospital/SecondSection/Medicine/medicine_page.dart';
import 'package:hospital/constant.dart';
import 'package:hospital/customApiVariable.dart';
import 'package:http/http.dart' as http;
import 'package:line_icons/line_icons.dart';
import 'package:provider/provider.dart';
class DetailPage extends StatefulWidget {
final plistId;
const DetailPage({Key key, this.plistId}) : super(key: key);
#override
_DetailPageState createState() => _DetailPageState();
}
class _DetailPageState extends State<DetailPage> {
final GlobalKey<FormState> _formKey = GlobalKey();
int quantity = 1;
var response;
var detailPageApi;
#override
void initState() {
super.initState();
fetchData(widget.plistId);
}
fetchData(var consultWithDoctor) async {
var api = Uri.parse(
'$ecommerceBaseUrl/productListApi.php?a2rTokenKey=$a2rTokenKey&plistId=${widget.plistId}');
response = await http.get(
api,
);
print("detailPageApi " + api.toString());
print("detailPageBody " + response.body);
detailPageApi = jsonDecode(response.body);
print("detailPagelist " + detailPageApi.toString());
setState(() {});
}
Future _submit() async {
var errorMessage = 'Authentication Failed';
if (successfully_add_cart_status.toString() == 'false') {
errorMessage = 'Please try again later';
print(errorMessage);
_showerrorDialog(errorMessage);
} else {
errorMessage = 'Product Succesfully Added to Cart';
print(errorMessage);
_showerrorDialog(errorMessage);
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: kGreen,
title: Text(
"Details",
style: TextStyle(fontStyle: FontStyle.italic),
),
actions: [
IconButton(
icon: Icon(Icons.shopping_cart),
// onPressed: () => print("open cart"),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Cartpage()),
);
},
),
DropDownMenu(),
],
),
body: Container(
child: response != null
? ListView.builder(
itemCount: detailPageApi.length.clamp(0, 1),
scrollDirection: Axis.vertical,
physics: ScrollPhysics(),
shrinkWrap: true,
itemBuilder: (context, index) {
var details = detailPageApi[index];
if (details['num'] == 0) {
return Center(
child: CircularProgressIndicator(
backgroundColor: Colors.white,
),
);
}
return Column(
children: <Widget>[
Hero(
tag: "1",
child: SizedBox(
height: 300.0,
width: 300.0,
child: Carousel(
boxFit: BoxFit.cover,
autoplay: false,
animationCurve: Curves.fastOutSlowIn,
animationDuration: Duration(milliseconds: 800),
dotSize: 6.0,
dotIncreasedColor: Colors.black,
dotBgColor: Colors.transparent,
// dotPosition: DotPosition.topRight,
dotVerticalPadding: 10.0,
showIndicator: true,
indicatorBgPadding: 7.0,
images: [
NetworkImage(details['pImgImg']),
],
),
),
),
SizedBox(
height: 50,
),
Padding(
padding: const EdgeInsets.only(left: 20, right: 20),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
"Name :",
style: TextStyle(
fontSize: 18,
height: 1.5,
fontWeight: FontWeight.w500),
),
SizedBox(
width: 20,
),
Flexible(
child: Text(
// widget.details,
details['productName'],
style: TextStyle(
fontSize: 17,
height: 1.5,
fontWeight: FontWeight.w500),
),
),
],
),
),
SizedBox(
height: 20,
),
Padding(
padding: const EdgeInsets.only(left: 20, right: 20),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
"Details :",
style: TextStyle(
fontSize: 18,
height: 1.5,
fontWeight: FontWeight.w500),
),
SizedBox(
width: 20,
),
Flexible(
child: Text(
// widget.details,
details['productDescription'],
style: TextStyle(
fontSize: 17,
height: 1.5,
fontWeight: FontWeight.w500),
),
),
],
),
),
SizedBox(
height: 20,
),
Padding(
padding: const EdgeInsets.only(left: 20, right: 20),
child: Row(
children: <Widget>[
Text(
"Price :",
style: TextStyle(
fontSize: 18, fontWeight: FontWeight.w500),
),
SizedBox(
width: 20,
),
Row(
children: <Widget>[
Text(
// "Rs " + widget.pPromotionPrice,
"Rs 55.0",
style: TextStyle(
fontSize: 17,
fontWeight: FontWeight.w500),
),
SizedBox(
width: 20,
),
Text(
// "Rs " + widget.pPrice,
"Rs 100",
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w500,
// color: warning,
decoration: TextDecoration.lineThrough),
)
],
)
],
),
),
SizedBox(
height: 25,
),
Padding(
padding: const EdgeInsets.only(right: 20, left: 20),
child: Row(
children: <Widget>[
Text(
"Qty :",
style: TextStyle(
fontSize: 17, fontWeight: FontWeight.w500),
),
SizedBox(
width: 20,
),
Row(
children: <Widget>[
InkWell(
onTap: () {
if (quantity > 1) {
setState(() {
quantity = --quantity;
});
}
// minus here
},
child: Container(
width: 25,
height: 25,
decoration: BoxDecoration(
// border: Border.all(color: primary),
shape: BoxShape.circle),
child: Icon(
LineIcons.minus,
size: 15,
),
),
),
SizedBox(
width: 15,
),
Text(
quantity.toString(),
style: TextStyle(fontSize: 16),
),
SizedBox(
width: 15,
),
InkWell(
onTap: () {
setState(() {
quantity = ++quantity;
});
// minus here
},
child: Container(
width: 25,
height: 25,
decoration: BoxDecoration(
// border: Border.all(color: primary),
shape: BoxShape.circle),
child: Icon(
LineIcons.plus,
size: 15,
),
),
),
],
)
],
),
),
SizedBox(
height: 50,
),
InkWell(
onTap: () async {
if (var_uid.toString() != null.toString()) {
_submit();
var qty = quantity.toString();
var plistId = widget.plistId;
print('pplistid' + plistId);
var uid = var_uid.toString();
var sid = var_sid.toString();
print('uuid' + uid);
print('ssid' + sid);
var response =
await add_to_cart_fn(qty, plistId, uid, sid);
print("rsp: " + response['msg']);
} else {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => LoginPage()));
}
},
// },
child: Padding(
padding: EdgeInsets.only(left: 20, right: 20),
child: Container(
height: 45,
width: double.infinity,
decoration: BoxDecoration(
color: kGreen,
borderRadius: BorderRadius.circular(30)),
child: Center(
child: Text(
"ADD TO CART",
style: TextStyle(
color: kWhite,
fontSize: 20,
),
),
),
),
),
),
SizedBox(height: 20.0),
RelatedProductPage(plistId: widget.plistId)
],
);
})
: Center(
child: CircularProgressIndicator(
backgroundColor: Colors.white,
),
),
),
);
}
void _showerrorDialog(String message) {
Fluttertoast.showToast(
msg: message,
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
timeInSecForIosWeb: 1,
backgroundColor: Colors.grey[350],
textColor: Colors.black,
fontSize: 16.0);
}
}
You are using the same quantity variable against each item. Changing the value on one of those will cause all items to update. What you need to do is to keep a Map of quantity selected against product id. That way whenever you increase or decrease the quantity, you update the quantity against that specific product id and the rest will remain unchanged.
EDIT: Here is how this will work
//Create a new map to save the product id and product selected quantity
var productQuantity = new Map<int, int>()
//When setting the values of the product, set the quantity from the map
Padding(
padding: const EdgeInsets.only(right: 20, left: 20),
child: Row(
children: <Widget>[
Text(
"Qty :",
style: TextStyle(
fontSize: 17, fontWeight: FontWeight.w500),
),
SizedBox(width: 20,),
Row(
children: <Widget>[
InkWell(
onTap: () {
if (quantity > 1) {
setState(() {
//Changed here
productQuantity['$productId'] -= 1;
});
}
},
child: Container(
width: 25,
height: 25,
decoration: BoxDecoration(shape: BoxShape.circle),
child: Icon(
LineIcons.minus,
size: 15,
),
),
),
SizedBox(width: 15,),
Text(
//Changed here
productQuantity['$productId'].toString(),
style: TextStyle(fontSize: 16),
),
SizedBox(width: 15,),
InkWell(
onTap: () {
setState(() {
//Changed here
productQuantity['$productId'] += 1;
});
},
child: Container(
width: 25,
height: 25,
decoration: BoxDecoration(
shape: BoxShape.circle),
),
child: Icon(
LineIcons.plus,
size: 15,
),
),
),
],
)
],
),
)
you set the common quantity in all products so change it and set it inside the class.
Please Check the example
import 'package:flutter/material.dart';
class QuantityUpdatePage extends StatefulWidget {
#override
_QuantityUpdatePageState createState() => _QuantityUpdatePageState();
}
class _QuantityUpdatePageState extends State<QuantityUpdatePage> {
List<Product> productArray = [];
#override
void initState() {
super.initState();
WidgetsBinding.instance!.addPostFrameCallback((timeStamp) {
productArray.clear();
productArray.add(Product(1, "Product 1", 1));
productArray.add(Product(2, "Product 2", 1));
productArray.add(Product(3, "Product 3", 1));
productArray.add(Product(4, "Product 4", 1));
productArray.add(Product(5, "Product 5", 1));
setState(() {});
});
}
#override
void dispose() {
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("QUANTITY UPDATE")),
body: ListView.builder(
shrinkWrap: true,
itemCount: productArray.length,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.only(right: 20, left: 20),
child: ListView(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
children: [
SizedBox(
height: 20,
),
Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(productArray[index].productName),
SizedBox(
width: 40,
),
Row(
children: <Widget>[
Text(
"Qty :",
style: TextStyle(fontSize: 17, fontWeight: FontWeight.w500),
),
SizedBox(
width: 20,
),
Row(
children: <Widget>[
InkWell(
onTap: () {
if (productArray[index].quantity > 1) {
setState(() {
productArray[index].quantity = --productArray[index].quantity;
});
}
// minus here
},
child: Container(
width: 25,
height: 25,
decoration: BoxDecoration(
// border: Border.all(color: primary),
shape: BoxShape.circle),
child: Icon(
Icons.minimize,
size: 15,
),
),
),
SizedBox(
width: 15,
),
Text(
productArray[index].quantity.toString(),
style: TextStyle(fontSize: 16),
),
SizedBox(
width: 15,
),
InkWell(
onTap: () {
setState(() {
productArray[index].quantity = ++productArray[index].quantity;
});
// minus here
},
child: Container(
width: 25,
height: 25,
decoration: BoxDecoration(
// border: Border.all(color: primary),
shape: BoxShape.circle),
child: Icon(
Icons.add,
size: 15,
),
),
),
],
)
],
),
],
),
SizedBox(
height: 20,
),
],
),
);
}));
}
}
class Product {
String productName;
int quantity;
int id;
Product(this.id, this.productName, this.quantity);
}
#Deepak if you don't understand Maps use list instead, with a value being updated for each index. Initialize a list of int types with some large values like 1000000, and update the value for each index. use ListView builder to fetch the data from the API for each index.
List<int> quantity = List.empty(growable: true);
OR
List<int> quantity = List.filled(10000, []);
For updating quantity:-
quantity[index] += 1;
For Grid view thing, refer this example from CodeGrepper:-
GridView.count(
// Create a grid with 2 columns. If you change the scrollDirection to
// horizontal, this produces 2 rows.
crossAxisCount: 2,
// Generate 100 widgets that display their index in the List.
children: List.generate(100, (index) {
return Center(
child: Text(
'Item $index',
style: Theme.of(context).textTheme.headline5,
),
);
}),
);