Dynamically created widgets using json Data in listvew builder the TextFeild not working in flutter - flutter

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.

Related

Why doesn't my state change in my stateful widget even when I pass data through constructors flutter?

Hello guys i have two stateful widget InactiveCustomersListView and MessageCustomerHeader
InactiveCustomersListView has a List of tiles, and these tiles have checkboxes
class InactiveCustomersListView extends StatefulWidget {
final bool checkAll;
const InactiveCustomersListView({
Key key,
this.checkAll,
}) : super(key: key);
#override
State<InactiveCustomersListView> createState() =>
_InactiveCustomersListViewState();
}
class _InactiveCustomersListViewState extends State<InactiveCustomersListView> {
bool checkAll;
List<CheckBoxModel> listOfCustomers = [];
#override
void initState() {
listOfCustomers.addAll({
CheckBoxModel(selected: false),
});
super.initState();
}
#override
Widget build(BuildContext context) {
final controller = Get.put(CustomersController());
return ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: listOfCustomers.length,
itemBuilder: (context, index) {
return Obx(() {
return Container(
color: Color(0xffFFFFFF),
child: ListTile(
contentPadding: controller.isCheboxVisible.isTrue
? EdgeInsets.only(left: 0, right: 22, top: 10, bottom: 10)
: EdgeInsets.only(left: 22, right: 22, top: 10, bottom: 10),
horizontalTitleGap: 5,
leading: controller.isCheboxVisible.isTrue
? Visibility(
visible: controller.isCheboxVisible.value,
child: Transform.scale(
scale: 1.3,
child: Checkbox(
side: MaterialStateBorderSide.resolveWith(
(Set<MaterialState> states) {
if (states.contains(MaterialState.selected)) {
return const BorderSide(
width: 2, color: Color(0xff34495E));
}
return const BorderSide(
width: 1, color: Color(0xffB0BEC1));
},
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5)),
activeColor: Color(0xff34495E),
//materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
//visualDensity: VisualDensity(horizontal: -4, vertical: -4),
value: listOfCustomers[index].selected,
onChanged: (value) {
setState(() {
listOfCustomers[index].selected = value;
final check = listOfCustomers
.every((element) => element.selected);
checkAll = check;
});
},
),
),
)
: null,
title: Row(
children: [
SizedBox(
width: 60,
height: 60,
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(80)),
child: CachedNetworkImage(
height: 100,
width: double.infinity,
fit: BoxFit.cover,
imageUrl:
Get.find<AuthService>().user.value.avatar.thumb,
placeholder: (context, url) => Image.asset(
'assets/img/loading.gif',
fit: BoxFit.cover,
width: double.infinity,
height: 80,
),
errorWidget: (context, url, error) =>
Icon(Icons.error_outline),
),
),
),
SizedBox(
width: 10,
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'John Cletus',
style: GoogleFonts.poppins(
fontSize: 14,
fontWeight: FontWeight.w500,
color: Color(0xff151515)),
),
Container(
decoration: BoxDecoration(
color: Color(0xffECF0F1),
borderRadius: BorderRadius.circular(20),
),
child: Padding(
padding: const EdgeInsets.only(
left: 10.0,
right: 10.0,
top: 5.0,
bottom: 5.0),
child: Text(
'Inactive',
style: GoogleFonts.poppins(
fontSize: 10,
fontWeight: FontWeight.w400,
color: Color(0xff7F8D90)),
),
),
),
],
),
SizedBox(
height: 10,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
Text(
'2',
style: GoogleFonts.poppins(
fontSize: 14,
fontWeight: FontWeight.w500,
color: Color(0xff151515)),
),
SizedBox(
width: 5,
),
Text(
'jobs',
style: GoogleFonts.poppins(
fontSize: 12,
fontWeight: FontWeight.w400,
color: Color(0xff151515)),
),
],
),
Text(
'Last job 5 days ago',
style: GoogleFonts.poppins(
fontSize: 9,
fontStyle: FontStyle.italic,
fontWeight: FontWeight.w400,
color: Color(0xff151515)),
),
],
),
],
),
),
],
),
),
);
});
});
}
}
class CheckBoxModel {
bool selected;
CheckBoxModel({this.selected});
}
MessageCustomerHeader widget class has a checkbox that controls the Check boxes in the InactiveCustomersListView widget class:
class MessageCustomerHeader extends StatefulWidget {
final List<CheckBoxModel> listOfCustomers;
const MessageCustomerHeader({
Key key,
this.listOfCustomers,
}) : super(key: key);
#override
State<MessageCustomerHeader> createState() => _MessageCustomerHeaderState();
}
class _MessageCustomerHeaderState extends State<MessageCustomerHeader> {
bool checkAll = false;
#override
Widget build(BuildContext context) {
return Container(
color: Colors.white,
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Select customers you woult like to message',
style: GoogleFonts.poppins(
color: Color(0xff596780).withOpacity(0.8),
fontSize: 14,
fontWeight: FontWeight.w500),
),
SizedBox(
height: 10,
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Transform.scale(
scale: 1.3,
child: Checkbox(
side: MaterialStateBorderSide.resolveWith(
(Set<MaterialState> states) {
if (states.contains(MaterialState.selected)) {
return const BorderSide(
width: 2, color: Color(0xff34495E));
}
return const BorderSide(
width: 1, color: Color(0xffB0BEC1));
},
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5)),
activeColor: Color(0xff34495E),
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
visualDensity: VisualDensity(horizontal: -4, vertical: -4),
value: checkAll,
onChanged: (value) {
setState(() {
checkAll = value;
widget.listOfCustomers.forEach((element) {
element.selected = value;
});
});
},
),
),
SizedBox(
width: 10,
),
Text(
'Select all',
style: GoogleFonts.poppins(
color: Colors.black87,
fontSize: 12,
fontWeight: FontWeight.w400),
),
],
),
],
),
),
);
}
}
I tried using constructor to pass "listOfCustomers" from InactiveCustomersListView widget to MessageCustomerHeader widget
And also passing "checkAll" from MessageCustomerHeader to InactiveCustomersListView widget by also using constructors.
The problem is having is that when i click on the checkbox in MessageCustomerHeader widget to check all the check boxes in InactiveCustomersListView widget, the state don't seem to change and it doesn't even after setting all the logic. What am i doing wrong guys and how do i resolve this issue :(
This is the error i get when i tap the checkbox on the MessageCustomerHeader checkbox.
"The method 'forEach' was called on null.
Receiver: null
Tried calling: forEach(Closure: (CheckBoxModel) => Null)"
Thank you.
If you have the proper lints enabled you would have seen this warning: DON'T put any logic in createState().
From the associated description:
Implementations of createState() should return a new instance of a State object and do nothing more. Since state access is preferred via the widget field, passing data to State objects using custom constructor parameters should also be avoided and so further, the State constructor is required to be passed no arguments.
(emphasis added)
You are passing arguments to your State constructors. Instead, use widget.checkAll and widget.listOfCustomers to access widget properties from the state objects.
Also:
It would be better to specify a type for checkAll. In your code you just have final checkAll;.
It is difficult to read the screen shot of the error message. It would be better to include the error message as text in the question, along with an indication in your code of the line to which the error message is referring.

How do i correctly position these items horizontally in flutter to avoid overflow?

I have a list of items that are responsible for a tab bar design, i want to make all the sizedboxes display at a go and not overflow horizontally.
I will give my code for better clarification.
This is what i could come up with after over an hour of tussle:
And this is what i am expecting
I will give my code snippets of the view below.
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:google_fonts/google_fonts.dart';
class JobsHeaderWidget extends StatefulWidget {
const JobsHeaderWidget({
Key key,
}) : super(key: key);
#override
State<JobsHeaderWidget> createState() => _JobsHeaderWidgetState();
}
class _JobsHeaderWidgetState extends State<JobsHeaderWidget> {
List<String> items = [
"All",
"Critical",
"Open",
"Closed",
"Overdue",
];
int current = 0;
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(left: 10.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Jobs',
style: GoogleFonts.poppins(
color: Colors.black, fontSize: 18, fontWeight: FontWeight.w600),
),
Row(
children: [
Text(
'View Insights ',
style: GoogleFonts.poppins(
color: Color(0xff3498DB),
fontSize: 12,
fontWeight: FontWeight.w500),
),
Icon(
Icons.arrow_forward_ios,
color: Color(0xff3498DB),
size: 12,
),
],
),
filterJobs()
],
),
);
}
Widget filterJobs() {
return Container(
width: double.infinity,
child: Column(
children: [
/// CUSTOM TABBAR
SizedBox(
width: double.infinity,
height: 60,
child: ListView.builder(
physics: const BouncingScrollPhysics(),
itemCount: items.length,
scrollDirection: Axis.horizontal,
itemBuilder: (ctx, index) {
return Column(
children: [
GestureDetector(
onTap: () {
setState(() {
current = index;
});
},
child: AnimatedContainer(
duration: const Duration(milliseconds: 300),
margin: const EdgeInsets.all(5),
decoration: BoxDecoration(
color: current == index
? Color(0xff34495E)
: Color(0xffF5F5F5),
borderRadius: BorderRadius.circular(11),
),
child: Center(
child: Padding(
padding: const EdgeInsets.only(
left: 10.0, right: 10.0, top: 5, bottom: 5),
child: Text(
items[index],
style: GoogleFonts.poppins(
fontSize: 10,
fontWeight: FontWeight.w500,
color: current == index
? Colors.white
: Colors.grey),
),
),
),
),
),
],
);
}),
),
// Builder(
// builder: (context) {
// switch (current) {
// case 0:
// return AllNotificationItemsView();
// case 1:
// return JobsNotificationItemsView();
// case 2:
// return MessagesNotificationItemsView();
// case 3:
// return CustomersNotificationItemsView();
// default:
// return SizedBox.shrink();
// }
// },
// )
],
),
);
}
}
The reason for overflow is List View Builder. Remove it and add a Row widget instead. Iterate the list item in it and you will get your desired output.
Full Code : -
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Image',
theme: ThemeData(
primarySwatch: Colors.blue,
),
debugShowCheckedModeBanner: false,
home: const JobsHeaderWidget(),
);
}
}
class JobsHeaderWidget extends StatefulWidget {
const JobsHeaderWidget({super.key});
#override
State<JobsHeaderWidget> createState() => _JobsHeaderWidgetState();
}
class _JobsHeaderWidgetState extends State<JobsHeaderWidget> {
List<String> items = [
"All",
"Critical",
"Open",
"Closed",
"Overdue",
];
int current = 0;
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey,
body: Padding(
padding: const EdgeInsets.only(left: 10.0, right: 10, top: 5),
child: Align(
alignment: Alignment.topCenter,
child: Container(
constraints: const BoxConstraints(maxWidth: 610, maxHeight: 100),
alignment: Alignment.center,
width: double.infinity,
child: IntrinsicWidth(
child: FittedBox(
fit: BoxFit.fitWidth,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
for (int i = 0; i < items.length; i++) ...[
GestureDetector(
onTap: () {
setState(() {
current = i;
});
},
child: AnimatedContainer(
height: 40,
duration: const Duration(milliseconds: 300),
margin: const EdgeInsets.all(5),
padding: const EdgeInsets.only(
left: 15.0, right: 15.0, top: 5, bottom: 5),
decoration: BoxDecoration(
color: current == i
? const Color(0xff34495E)
: const Color(0xffF5F5F5),
borderRadius: BorderRadius.circular(11),
),
child: Center(
child: Text(
items[i],
style: GoogleFonts.poppins(
fontSize: 19,
fontWeight: FontWeight.w500,
color: current == i
? Colors.white
: Colors.grey),
),
),
),
),
]
],
),
),
),
),
),
),
);
}
}
Output : -
Hey there for making the appbar not overflowing, you must use expanded widget. try to wrap your gestureDetector or whatever widget that you create for making the design for each listview child like this
Expanded(
child: GestureDetector(
onTap: () {
setState(() {
current = i;
});
},
child: AnimatedContainer(
height: 40,
duration: const Duration(milliseconds: 300),
margin: const EdgeInsets.all(5),
padding: const EdgeInsets.only(
left: 15.0, right: 15.0, top: 5, bottom: 5),
decoration: BoxDecoration(
color: current == i
? const Color(0xff34495E)
: const Color(0xffF5F5F5),
borderRadius: BorderRadius.circular(11),
),
child: Center(
child: Text(
items[i],
style: GoogleFonts.poppins(
fontSize: 12,
fontWeight: FontWeight.w500,
color: current == i ? Colors.white : Colors.grey),
),
),
),
),
),
as you can see when you doing this the design will look like this
the text inside of the design would gone because of overflowing issue, you can change the text widget into this widget https://pub.dev/packages/auto_size_text
this is the snipet
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey,
body: SafeArea(
child: Padding(
padding: const EdgeInsets.only(left: 5.0, right: 5, top: 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
for (int i = 0; i < items.length; i++) ...[
Expanded(
child: GestureDetector(
onTap: () {
setState(() {
current = i;
});
},
child: AnimatedContainer(
height: 40,
duration: const Duration(milliseconds: 300),
margin: const EdgeInsets.all(5),
padding: const EdgeInsets.only(
left: 5.0, right: 5.0, top: 5, bottom: 5),
decoration: BoxDecoration(
color: current == i
? const Color(0xff34495E)
: const Color(0xffF5F5F5),
borderRadius: BorderRadius.circular(11),
),
child: Center(
child: AutoSizeText(
items[i],
maxLines: 1,
style: GoogleFonts.poppins(
fontSize: 12,
fontWeight: FontWeight.w500,
color:
current == i ? Colors.white : Colors.grey),
),
),
),
),
),
]
],
),
),
));
but surely the text would be some of big and some of small look like this, and this is the result

how to show multiple comment_tree: ^0.3.0 in flutter , I want to show multiple comment in comment page Pleas help me

'here is comment widget i want to show this multiple comment widget in comment page and i also trying to lot of trying to put this comment widget in listview when i put this widget in listview my screeen is not rendered. but when i put this in gridview it is showing all comment properly plese help me'
import 'package:comment_tree/comment_tree.dart';
import 'package:comment_tree/widgets/comment_tree_widget.dart';
import 'package:ecllipsenew/data/repository/post_repo.dart';
import 'package:ecllipsenew/provider/PostProvider.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:provider/provider.dart';
import '../../../../util/app_constants.dart';
class Comments extends StatefulWidget {
final List<Comment> commentList;
Comments({this.commentList});
#override
State<Comments> createState() => _CommentsState();
}
class _CommentsState extends State<Comments> {
bool reply = false;
final List<Comment> commentLi = [
Comment(
avatar: 'nukkll',
userName: 'njjull',
content: 'I mkk interested',
),
Comment(
avatar: 'null',
userName: 'null',
content: 'I mjjj interested',
),
];
#override
Widget build(BuildContext context) {
return Column(
children: [
Expanded(
child: Container(
child: CommentTreeWidget<Comment, Comment>(
commentLi[0],
[
commentLi[0],
commentLi[1],
],
treeThemeData:
TreeThemeData(lineColor: Colors.blue, lineWidth: 3),
avatarRoot: (context, data) => const PreferredSize(
child: CircleAvatar(
radius: 18,
backgroundColor: Colors.grey,
backgroundImage: NetworkImage(AppConstants.User_Url)),
preferredSize: Size.fromRadius(18),
),
avatarChild: (context, data) => const PreferredSize(
child: CircleAvatar(
radius: 12,
backgroundColor: Colors.grey,
backgroundImage: NetworkImage(AppConstants.User_Url)),
preferredSize: Size.fromRadius(12),
),
contentChild: (context, data) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: EdgeInsets.symmetric(vertical: 8, horizontal: 8),
decoration: BoxDecoration(
color: Colors.grey[100],
borderRadius: BorderRadius.circular(12)),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'${data.userName}',
style: Theme.of(context)
.textTheme
.caption
?.copyWith(
fontWeight: FontWeight.w600,
color: Colors.black),
),
SizedBox(
height: 4,
),
Text(
'${data.content}',
style: Theme.of(context)
.textTheme
.caption
?.copyWith(
fontWeight: FontWeight.w300,
color: Colors.black),
),
],
),
),
DefaultTextStyle(
style: Theme.of(context).textTheme.caption.copyWith(
color: Colors.grey[700], fontWeight: FontWeight.bold),
child: Padding(
padding: EdgeInsets.only(top: 4),
child: Row(
children: [
SizedBox(
width: 8,
),
Text('5d'),
SizedBox(
width: 8,
),
Text('Like'),
SizedBox(
width: 24,
),
Text('Reply'),
],
),
),
)
],
);
},
contentRoot: (context, data) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: EdgeInsets.symmetric(vertical: 8, horizontal: 8),
decoration: BoxDecoration(
color: Colors.grey[100],
borderRadius: BorderRadius.circular(12)),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Tina Chuhan',
style: Theme.of(context).textTheme.caption.copyWith(
fontWeight: FontWeight.w600,
color: Colors.black),
),
SizedBox(
height: 4,
),
Text(
'${data.content}',
style: Theme.of(context).textTheme.caption.copyWith(
fontWeight: FontWeight.w300,
color: Colors.black),
),
],
),
),
DefaultTextStyle(
style: Theme.of(context).textTheme.caption.copyWith(
color: Colors.grey[700], fontWeight: FontWeight.bold),
child: Padding(
padding: EdgeInsets.only(top: 4),
child: Row(
children: const [
SizedBox(
width: 8,
),
Text('5d'),
SizedBox(
width: 8,
),
Text('Like'),
SizedBox(
width: 24,
),
Text('Reply'),
],
),
),
)
],
);
},
),
padding: EdgeInsets.symmetric(vertical: 12, horizontal: 16),
),
),
],
);
// }
// );
// });
}
}
and here is my comment show page
import 'package:comment_tree/comment_tree.dart';
import 'package:ecllipsenew/screen/home/pages/comment/Comments.dart';
import 'package:ecllipsenew/screen/home/pages/comment/new_message.dart';
import 'package:ecllipsenew/util/app_constants.dart';
import 'package:flutter/material.dart';
class CommentPage extends StatefulWidget {
static const routeName = '/Comment_Page';
const CommentPage({Key key}) : super(key: key);
#override
State<CommentPage> createState() => _CommentPageState();
}
class _CommentPageState extends State<CommentPage> {
// final List<Comments> commentList = [
// Comments(
// commentId: "3",
// commentUserId: "11",
// commentUserName: "Himanshu",
// commentUserProfileImage: AppConstants.User_Url,
// commentType: "text",
// commentFile: "jjjj",
// commentDate: "12/12/12",
// commentTime: "12:30",
// commentReacts: "hhh",
// letestReplys: "jjjj")
// ];
final List<Comment> commentLi = [
Comment(
avatar: 'null',
userName: 'null',
content: 'I m interested',
),
Comment(
avatar: 'null',
userName: 'null',
content: 'I m interested',
),
];
#override
Widget build(BuildContext context) {
return
// Scaffold(
// appBar: AppBar(
// title: Text("Comment"),
// ),
// body:
SingleChildScrollView(
child: Container(
child: Column(
children: <Widget>[
//when I add this line my screen is not rendered
for (int i = 0; i < 3; i++) Comments(commentList: commentLi),
Expanded(
child: Comments(commentList: commentLi),
),
NewMessage()
],
),
),
);
// );
}
}
The main cause of render error is using Expanded widget inside Column, without having a fixed height for that Column.
If you want to use Expanded widget inside Column, you should wrap the column with a sizedbox and give it a fixed height as shown below:
SizedBox(
height: MediaQuery.of(context).size.height * 0.8,
child: Column(
children: [
Text('Header'),
Expanded(
child: Container(
child: Center(
child: Text('I take the remaining space'),
),
),
)
],
)
I could render the same code by removing the Expanded widgets wherever you have used them. They seem unnecessary too.
Screenshot of commentPage by removing Expanded widget everywhere
Please find full code as you have asked for in previous answer. Still, I recommend you to know the basic of flutter-layout to understand working with Expanded widget before using this code.
import 'package:flutter/material.dart';
import 'package:test/view.dart';
void main() {
runApp(const MyApp());
}
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: const CommentPage());
}
}
Comments page code
import 'package:comment_tree/comment_tree.dart';
import 'package:flutter/material.dart';
import 'package:test/test.dart';
class CommentPage extends StatefulWidget {
static const routeName = '/Comment_Page';
const CommentPage({Key? key}) : super(key: key);
#override
State<CommentPage> createState() => _CommentPageState();
}
class _CommentPageState extends State<CommentPage> {
// final List<Comments> commentList = [
// Comments(
// commentId: "3",
// commentUserId: "11",
// commentUserName: "Himanshu",
// commentUserProfileImage: AppConstants.User_Url,
// commentType: "text",
// commentFile: "jjjj",
// commentDate: "12/12/12",
// commentTime: "12:30",
// commentReacts: "hhh",
// letestReplys: "jjjj")
// ];
final List<Comment> commentLi = [
Comment(
avatar: 'null',
userName: 'null',
content: 'I m interested',
),
Comment(
avatar: 'null',
userName: 'null',
content: 'I m interested',
),
];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Comment"),
),
body: SingleChildScrollView(
child: Container(
child: Column(
children: <Widget>[
for (int i = 0; i < 3; i++) Comments(commentList: commentLi),
// Comments(commentList: commentLi),
// NewMessage()
],
),
),
),
);
// );
}
}
Comments tree page
import 'package:comment_tree/comment_tree.dart';
import 'package:flutter/material.dart';
class Comments extends StatefulWidget {
final List<Comment> commentList;
const Comments({Key? key, required this.commentList}) : super(key: key);
#override
State<Comments> createState() => _CommentsState();
}
class _CommentsState extends State<Comments> {
bool reply = false;
final List<Comment> commentLi = [
Comment(
avatar: 'nukkll',
userName: 'njjull',
content: 'I mkk interested',
),
Comment(
avatar: 'null',
userName: 'null',
content: 'I mjjj interested',
),
];
#override
Widget build(BuildContext context) {
return Column(
children: [
Container(
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16),
child: CommentTreeWidget<Comment, Comment>(
commentLi[0],
[
commentLi[0],
commentLi[1],
],
treeThemeData:
const TreeThemeData(lineColor: Colors.blue, lineWidth: 3),
avatarRoot: (context, data) => const PreferredSize(
preferredSize: Size.fromRadius(18),
child: CircleAvatar(
radius: 18,
backgroundColor: Colors.grey,
backgroundImage: NetworkImage(
"https://i.pinimg.com/736x/6f/de/85/6fde85b86c86526af5e99ce85f57432e.jpg")),
),
avatarChild: (context, data) => const PreferredSize(
preferredSize: Size.fromRadius(12),
child: CircleAvatar(
radius: 12,
backgroundColor: Colors.grey,
backgroundImage: NetworkImage(
"https://i.pinimg.com/736x/6f/de/85/6fde85b86c86526af5e99ce85f57432e.jpg")),
),
contentChild: (context, data) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding:
const EdgeInsets.symmetric(vertical: 8, horizontal: 8),
decoration: BoxDecoration(
color: Colors.grey[100],
borderRadius: BorderRadius.circular(12)),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'${data.userName}',
style: Theme.of(context).textTheme.caption?.copyWith(
fontWeight: FontWeight.w600, color: Colors.black),
),
const SizedBox(
height: 4,
),
Text(
'${data.content}',
style: Theme.of(context).textTheme.caption?.copyWith(
fontWeight: FontWeight.w300, color: Colors.black),
),
],
),
),
DefaultTextStyle(
style: Theme.of(context).textTheme.caption!.copyWith(
color: Colors.grey[700], fontWeight: FontWeight.bold),
child: Padding(
padding: const EdgeInsets.only(top: 4),
child: Row(
children: const [
SizedBox(
width: 8,
),
Text('5d'),
SizedBox(
width: 8,
),
Text('Like'),
SizedBox(
width: 24,
),
Text('Reply'),
],
),
),
)
],
);
},
contentRoot: (context, data) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding:
const EdgeInsets.symmetric(vertical: 8, horizontal: 8),
decoration: BoxDecoration(
color: Colors.grey[100],
borderRadius: BorderRadius.circular(12)),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Tina Chuhan',
style: Theme.of(context).textTheme.caption!.copyWith(
fontWeight: FontWeight.w600, color: Colors.black),
),
const SizedBox(
height: 4,
),
Text(
'${data.content}',
style: Theme.of(context).textTheme.caption!.copyWith(
fontWeight: FontWeight.w300, color: Colors.black),
),
],
),
),
DefaultTextStyle(
style: Theme.of(context).textTheme.caption!.copyWith(
color: Colors.grey[700], fontWeight: FontWeight.bold),
child: Padding(
padding: const EdgeInsets.only(top: 4),
child: Row(
children: const [
SizedBox(
width: 8,
),
Text('5d'),
SizedBox(
width: 8,
),
Text('Like'),
SizedBox(
width: 24,
),
Text('Reply'),
],
),
),
)
],
);
},
),
),
],
);
}
}

Flutter- click is responding to every item in listview.builder

I am trying to create a list of items in flutter with listView.builder, i am also using using elevatedButton in my itemBuilder.
i applied setState in button
i want to change value of single item only
but that is applying to every value in list
here is my code
import 'dart:developer';
import 'package:counter_button/counter_button.dart';
import 'package:flutter/material.dart';
import 'package:fooddeliveryapp/apis.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'models/restrauntmenu.dart';
class RestrauntPage extends StatefulWidget {
final String restrauntId;
final String restrauntName;
final String restrauntType;
final String restrauntApproxBill;
final String restrauntTagline;
const RestrauntPage(
{Key? key,
required this.restrauntId,
required this.restrauntType,
required this.restrauntApproxBill,
required this.restrauntTagline,
required this.restrauntName})
: super(key: key);
#override
State<RestrauntPage> createState() => _RestrauntPageState();
}
class _RestrauntPageState extends State<RestrauntPage> {
int _counterValue = 1;
bool itemAdded = false;
late Future<List<RestrauntMenu>> futureRestrauntMenu;
Future<List<RestrauntMenu>> fetchRestrauntMenu() async {
String restrauntId = widget.restrauntId;
final response = await http.get(Uri.parse(menuApi(restrauntId)));
if (response.statusCode == 200) {
final parsed = json.decode(response.body).cast<Map<String, dynamic>>();
return parsed
.map<RestrauntMenu>((json) => RestrauntMenu.fromMap(json))
.toList();
} else {
throw Exception('Failed to load album');
}
}
addToCartButton(
{required String? itemname,
required String? itemprice,
required int? itemCount,
required String? usermob,
required String? restrauntName}) {
return ElevatedButton(
clipBehavior: Clip.antiAliasWithSaveLayer,
style: ButtonStyle(
elevation: MaterialStateProperty.all(
6,
),
backgroundColor: MaterialStateProperty.all(Colors.white),
),
onPressed: () {
addToCart(
itemname: itemname,
itemprice: itemprice,
restrauntName: restrauntName,
usermob: usermob,
itemCount: itemCount);
},
child: const Padding(
padding: EdgeInsets.all(8.0),
child: Text(
'ADD TO CART',
style: TextStyle(
color: Colors.green,
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
),
);
}
counterButton() {
return Container(
decoration: const BoxDecoration(color: Colors.white),
child: CounterButton(
loading: false,
onChange: (int val) {
setState(() {
_counterValue = val;
});
},
count: _counterValue,
countColor: Colors.green,
buttonColor: Colors.black,
progressColor: Colors.black,
),
);
}
Future addToCart(
{required String? itemname,
required String? itemprice,
required int? itemCount,
required String? usermob,
required String? restrauntName}) async {
itemCount = _counterValue;
var url = addToCartApi(
itemname: itemname,
itemprice: itemprice,
itemCount: itemCount,
usermob: usermob,
restrauntName: restrauntName);
var response = await http.get(
Uri.parse(url),
);
if (response.statusCode == 200) {
setState(() {
itemAdded = true;
});
} else {
return false;
}
}
#override
void initState() {
futureRestrauntMenu = fetchRestrauntMenu();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
foregroundColor: Colors.black,
elevation: 0,
backgroundColor: Colors.white,
title: const Text('Restraunt Name'),
),
body: SingleChildScrollView(
child: SizedBox(
height: MediaQuery.of(context).size.height,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
SizedBox(
width: MediaQuery.of(context).size.width * 0.03,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
widget.restrauntName,
style: const TextStyle(
color: Colors.black,
fontSize: 24,
fontWeight: FontWeight.w900,
),
),
// const SizedBox(height: 4),
Text(
widget.restrauntType,
style: const TextStyle(
color: Colors.black,
fontSize: 16,
fontWeight: FontWeight.normal,
),
),
Text(
widget.restrauntTagline,
style: const TextStyle(
color: Colors.black87,
fontSize: 12,
fontWeight: FontWeight.normal,
),
),
const SizedBox(
height: 6,
),
Container(
decoration: BoxDecoration(
color: Colors.grey[200],
borderRadius: BorderRadius.circular(10),
),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: RichText(
text: TextSpan(
children: [
const WidgetSpan(
child: Icon(
Icons.currency_rupee,
size: 16,
color: Color.fromARGB(255, 45, 174, 49),
),
),
TextSpan(
text: widget.restrauntApproxBill,
style: const TextStyle(
color: Colors.black,
fontSize: 12,
fontWeight: FontWeight.bold,
),
),
],
),
),
),
),
],
),
const Spacer(),
Container(
decoration: BoxDecoration(
color: const Color.fromARGB(255, 49, 171, 53),
borderRadius: BorderRadius.circular(12),
),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: RichText(
text: const TextSpan(
children: [
TextSpan(
text: '3.6',
style: TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
WidgetSpan(
child: Icon(
Icons.star,
color: Colors.white,
size: 18,
),
),
],
),
),
),
),
SizedBox(
width: MediaQuery.of(context).size.width * 0.03,
),
],
),
const SizedBox(
height: 12,
),
Expanded(
child: FutureBuilder<List<RestrauntMenu>>(
future: futureRestrauntMenu,
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data!.length,
itemBuilder: (context, index) {
return ExpansionTile(
initiallyExpanded: true,
childrenPadding: const EdgeInsets.all(8),
title: Text(
snapshot.data![index].catname!,
style: const TextStyle(
fontSize: 20, fontWeight: FontWeight.bold),
),
children: [
Row(
children: [
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
snapshot.data![index].itemname!,
style: const TextStyle(
fontSize: 30,
fontWeight: FontWeight.bold,
),
),
const SizedBox(
height: 4,
),
Text(
snapshot.data![index].itemPrice!,
style: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.w600,
),
),
const SizedBox(
height: 4,
),
Text(
snapshot.data![index].itemDescription!,
style: const TextStyle(
fontSize: 12,
fontWeight: FontWeight.normal,
),
),
],
),
const Spacer(),
Stack(
alignment: Alignment.bottomCenter,
children: [
Padding(
padding:
const EdgeInsets.only(bottom: 16),
child: ClipRRect(
borderRadius:
BorderRadius.circular(10),
child: FittedBox(
child: Container(
height: MediaQuery.of(context)
.size
.height *
0.22,
width: MediaQuery.of(context)
.size
.width *
0.4,
decoration: BoxDecoration(
color: Colors.red,
image: DecorationImage(
fit: BoxFit.cover,
image: NetworkImage(
'http://www.jfamoslogistics.com/images/${snapshot.data![index].itemimage!}',
),
),
),
),
),
),
),
Align(
alignment: Alignment.topRight,
child: itemAdded
? counterButton()
: addToCartButton(
itemprice: snapshot
.data![index].itemPrice,
itemname: snapshot
.data![index].itemname,
itemCount: _counterValue,
restrauntName:
widget.restrauntName,
usermob: '9354954343',
))
],
)
],
),
],
);
},
);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
return const Center(
child: CircularProgressIndicator(),
);
},
),
),
],
),
),
),
);
}
}
please check and help me
please let me know if i am missing something or making some mistake in code
i have tried google everywhere but nothing works
thanks in advance
As Giseppe Colucci described, you are using a single counter variable for a list . You can follow the simple approach of using list. On State
int _counterValue = 1; will be replaced with List<int> _counterValue = []
After getting data initialize the list with default value.
if (snapshot.hasData) {
_counterValue =List.generate(snapshot.data!.length, (index) => 1); // you might prefer default value as 0 instead of 1
As for the counter button method we need to update specific index, therefore we will pass index here
counterButton(int index) {
return Container(
decoration: const BoxDecoration(color: Colors.white),
child: CounterButton(
loading: false,
onChange: (int val) {
setState(() {
_counterValue[index] = val;
});
},
count: _counterValue[index],
Now whenever we use this counterButton method we need to pass index and here we get index from listview.
child: itemAdded
? counterButton(index)
: addToCartButton(
That is because your itemAdded bool is only one, for every item in the list, you should make a map, like this:
{'id':true}
where id is the restaurant menu item, and true is whenever the item is selected or not.
If this is too hard for you, just use a simple list.

Accessing a function from one to another dart class

I am new to flutter. I have class name LoginCard.dart in this I have another class named _FormPageState which have _validateInputs function `
import 'package:firstapp/Future/app_futures.dart';
import 'package:firstapp/Models/Base/EventObject.dart';
import 'package:firstapp/Widgets/SignupCard.dart';
import 'package:firstapp/utils/constants.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:firstapp/Components/ProgressDialog.dart';
class LoginCard extends StatelessWidget {
#override
Widget build (BuildContext context){
return new Container(
child: new LoginFormContainer(),
);
}
}
class LoginFormContainer extends StatefulWidget{
// #override
// _FormPageState createState() => _FormPageState();
State<StatefulWidget> createState() {
return _FormPageState();
}
}
class _FormPageState extends State<LoginFormContainer>{
final GlobalKey<FormState> _formKey = new GlobalKey<FormState>();
bool _autoValidate = false;
// bool _obscureText = true;
String _email;
String _password;
ProgressDialog progressDialog = ProgressDialog
.getProgressDialog(ProgressDialogTitles.USER_LOG_IN);
#override
Widget build(BuildContext context) {
return new Container(
width: double.infinity,
height: ScreenUtil.getInstance().setHeight(500),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8.0),
boxShadow: [
BoxShadow(
color: Colors.black12,
offset: Offset(0.0, 15.0),
blurRadius: 15.0),
BoxShadow(
color: Colors.black12,
offset: Offset(0.0, -10.0),
blurRadius: 10.0),
]),
child: Padding(
padding: EdgeInsets.only(left: 16.0, right: 16.0, top: 16.0),
child: new Form(
key: _formKey,
autovalidate: _autoValidate,
child: new Stack(
children: <Widget>[loginFormUI(), progressDialog]
)
),
),
);
}
Widget loginFormUI(){
return new Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text("Login",
style: TextStyle(
fontSize: ScreenUtil.getInstance().setSp(45),
fontFamily: "Poppins-Bold",
letterSpacing: .6)),
SizedBox(
height: ScreenUtil.getInstance().setHeight(30),
),
Text("Username",
style: TextStyle(
fontFamily: "Poppins-Medium",
fontSize: ScreenUtil.getInstance().setSp(26))),
new TextFormField(
autofocus: true,
keyboardType: TextInputType.text,
validator: validateEmail,
onSaved: (val) =>
_email = val,
decoration: InputDecoration(
hintText: "username",
hintStyle: TextStyle(color: Colors.grey, fontSize: 12.0)),
),
SizedBox(
height: ScreenUtil.getInstance().setHeight(30),
),
Text("Password",
style: TextStyle(
fontFamily: "Poppins-Medium",
fontSize: ScreenUtil.getInstance().setSp(26))),
new TextFormField(
obscureText: true,
keyboardType: TextInputType.text,
validator: validatePassword,
onSaved: (val) =>
_password = val,
decoration: InputDecoration(
hintText: "Password",
hintStyle: TextStyle(color: Colors.grey, fontSize: 12.0)),
),
SizedBox(
height: ScreenUtil.getInstance().setHeight(35),
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Text(
"Forgot Password?",
style: TextStyle(
color: Colors.blue,
fontFamily: "Poppins-Medium",
fontSize: ScreenUtil.getInstance().setSp(28)),
)
],
)
],
);
}
String validateEmail(String value){
Pattern pattern = r'^(([^<>()[\]\\.,;:\s#\"]+(\.[^<>()[\]\\.,;:\s#\"]+)*)|(\".+\"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$';
RegExp regex = new RegExp(pattern);
if(value.isEmpty)
return "Email is required";
else if(!regex.hasMatch(value))
return 'Enter valid email';
else
return null;
}
String validatePassword(String value){
if (value.isEmpty)
return "Password is required";
else
return null;
}
void _validateInputs() {
if (_formKey.currentState.validate()){
print("hello");
// If all data are correct then save data to out variables
_formKey.currentState.save();
FocusScope.of(context).requestFocus(new FocusNode());
progressDialog.showProgress();
// _addNewUser();
_performLogin();
} else {
// If all data are not valid then start auto validation.
setState(() {
_autoValidate = true;
});
}
}
void _performLogin() async{
EventObject eventObject = await performLogin(_email, _password);
}
}
`
and Another class name is main.dart `
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'Widgets/LoginCard.dart';
import 'Widgets/SocialIcons.dart';
import 'CustomIcons.dart';
import 'signup.dart';
//
void main() => runApp(MaterialApp(
home: MyApp(),
debugShowCheckedModeBanner: false,
));
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State<MyApp> {
bool _isSelected = false;
// _FormPageState formPageState;
void _radio() {
setState(() {
_isSelected = !_isSelected;
});
}
Widget radioButton(bool isSelected) => Container(
width: 16.0,
height: 16.0,
padding: EdgeInsets.all(2.0),
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(width: 2.0, color: Colors.black)),
child: isSelected
? Container(
width: double.infinity,
height: double.infinity,
decoration:
BoxDecoration(shape: BoxShape.circle, color: Colors.black),
)
: Container(),
);
Widget horizontalLine() => Padding(
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: Container(
width: ScreenUtil.getInstance().setWidth(120),
height: 1.0,
color: Colors.black26.withOpacity(.2),
),
);
#override
Widget build(BuildContext context) {
ScreenUtil.instance = ScreenUtil.getInstance()..init(context);
ScreenUtil.instance =
ScreenUtil(width: 750, height: 1334, allowFontScaling: true);
return new Scaffold(
backgroundColor: Colors.white,
resizeToAvoidBottomPadding: true,
body: Stack(
fit: StackFit.expand,
children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: 100.0),
child: Image.asset("assets/carscartoon.png"),
),
Expanded(
child: Container(),
),
Image.asset("assets/image_02.png")
],
),
SingleChildScrollView(
child: Padding(
padding: EdgeInsets.only(left: 28.0, right: 28.0, top: 60.0),
child: Column(
children: <Widget>[
Row(
children: <Widget>[
Image.asset(
"assets/tlrlogo.png",
width: ScreenUtil.getInstance().setWidth(110),
height: ScreenUtil.getInstance().setHeight(110),
),
Text("Transport Levy Record",
style: TextStyle(
fontFamily: "Poppins-Bold",
fontSize: ScreenUtil.getInstance().setSp(30),
letterSpacing: .6,
fontWeight: FontWeight.bold))
],
),
SizedBox(
height: ScreenUtil.getInstance().setHeight(180),
),
LoginCard(),
SizedBox(height: ScreenUtil.getInstance().setHeight(40)),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Row(
children: <Widget>[
SizedBox(
width: 12.0,
),
GestureDetector(
onTap: _radio,
child: radioButton(_isSelected),
),
SizedBox(
width: 8.0,
),
Text("Remember me",
style: TextStyle(
fontSize: 12, fontFamily: "Poppins-Medium"))
],
),
InkWell(
child: Container(
width: ScreenUtil.getInstance().setWidth(330),
height: ScreenUtil.getInstance().setHeight(100),
decoration: BoxDecoration(
gradient: LinearGradient(colors: [
Color(0xFF17ead9),
Color(0xFF6078ea)
]),
borderRadius: BorderRadius.circular(6.0),
boxShadow: [
BoxShadow(
color: Color(0xFF6078ea).withOpacity(.3),
offset: Offset(0.0, 8.0),
blurRadius: 8.0)
]),
child: Material(
color: Colors.transparent,
child: InkWell(
onTap: () {
// LoginFormContainer()
},
child: Center(
child: Text("SIGNIN",
style: TextStyle(
color: Colors.white,
fontFamily: "Poppins-Bold",
fontSize: 18,
letterSpacing: 1.0)),
),
),
),
),
)
],
),
SizedBox(
height: ScreenUtil.getInstance().setHeight(40),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
horizontalLine(),
Text("Social Login",
style: TextStyle(
fontSize: 16.0, fontFamily: "Poppins-Medium")),
horizontalLine()
],
),
SizedBox(
height: ScreenUtil.getInstance().setHeight(40),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SocialIcons(
colors: [
Color(0xFF102397),
Color(0xFF187adf),
Color(0xFF00eaf8),
],
iconData: CustomIcons.facebook,
onPressed: () {},
),
SocialIcons(
colors: [
Color(0xFFff4f38),
Color(0xFFff355d),
],
iconData: CustomIcons.googlePlus,
onPressed: () {},
),
SocialIcons(
colors: [
Color(0xFF17ead9),
Color(0xFF6078ea),
],
iconData: CustomIcons.twitter,
onPressed: () {},
),
SocialIcons(
colors: [
Color(0xFF00c6fb),
Color(0xFF005bea),
],
iconData: CustomIcons.linkedin,
onPressed: () {},
)
],
),
SizedBox(
height: ScreenUtil.getInstance().setHeight(30),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
"New User? ",
style: TextStyle(fontFamily: "Poppins-Medium"),
),
InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder:
(context) => Signup()));
},
child: Text("SignUp",
style: TextStyle(
color: Color(0xFF5d74e3),
fontFamily: "Poppins-Bold")),
)
],
)
],
),
),
)
],
),
);
}
}
`
On line No. 143 there is onTap function of SignIn button in my main.dart class, I want access _validateInputs() function of _FormPageState.
I am new in dart. Please let me know, if any solution for this.
Put _validateInputs() function and all variables in main.dart file which is used in LoginCard.dart file and pass variables to Logincard constructor as argument from main.dart file.
In main.dart file
final GlobalKey<FormState> _formKey = new GlobalKey<FormState>();
pass _formkey to LoginCard() constructor
LoginCard(_formKey);
in LoginCard.dart file
class LoginCard extends StatelessWidget {
final GlobalKey<FormState> formKey;
LoginCard(this.formKey);
#override
Widget build (BuildContext context){
return new Container();
}