Related
type 'List<Object?>' is not a subtype of type 'List<Animal?>' of 'function result'
giving me errors on saving selected values value is shown in debug but cant print value properly and only print "instance of class".
how to get out this error
MultiSelectDialogField(
items: _items,
title: const Text("Animals"),
selectedColor: Colors.blue,
decoration: BoxDecoration(
color: Colors.blue.withOpacity(0.1),
borderRadius: const BorderRadius.all(Radius.circular(40)),
border: Border.all(
color: Colors.blue,
width: 2,
),
),
buttonIcon: const Icon(
Icons.pets,
color: Colors.blue,
),
buttonText: Text(
"Favorite Animals",
style: TextStyle(
color: Colors.blue[800],
fontSize: 16,
),
),
onConfirm: (results) {
//_selectedAnimals = results;
},
),
const SizedBox(height: 50),
//################################################################################################
// This MultiSelectBottomSheetField has no decoration, but is instead wrapped in a Container that has
// decoration applied. This allows the ChipDisplay to render inside the same Container.
//################################################################################################
Container(
decoration: BoxDecoration(
color: Theme.of(context).primaryColor.withOpacity(.4),
border: Border.all(
color: Theme.of(context).primaryColor,
width: 2,
),
),
child: Column(
children: <Widget>[
MultiSelectBottomSheetField(
initialChildSize: 0.4,
listType: MultiSelectListType.CHIP,
searchable: true,
buttonText: const Text("Favorite Animals"),
title: const Text("Animals"),
items: _items,
onConfirm: (values) {
_selectedAnimals2 = values;
},
chipDisplay: MultiSelectChipDisplay(
onTap: (value) {
setState(() {
_selectedAnimals2.remove(value);
});
},
),
),
_selectedAnimals2 == null || _selectedAnimals2.isEmpty
? Container(
padding: const EdgeInsets.all(10),
alignment: Alignment.centerLeft,
// ignore: prefer_const_constructors
child: Text(
"None selected",
style: const TextStyle(color: Colors.black54),
))
: Container(),
],
),
),
const SizedBox(height: 40),
//################################################################################################
// MultiSelectBottomSheetField with validators
//################################################################################################
MultiSelectBottomSheetField<Animal>(
key: _multiSelectKey,
initialChildSize: 0.7,
maxChildSize: 0.95,
title: const Text("Animals"),
buttonText: const Text("Favorite Animals"),
items: _items,
searchable: true,
validator: (values) {
if (values == null || values.isEmpty) {
return "Required";
}
List<String> names = values.map((e) => e.name).toList();
if (names.contains("Frog")) {
return "Frogs are weird!";
}
return null;
},
onConfirm: (values) {
setState(() {
_selectedAnimals3 = values;
});
_multiSelectKey.currentState!.validate();
},
chipDisplay: MultiSelectChipDisplay(
onTap: (item) {
setState(() {
_selectedAnimals3.remove(item);
});
_multiSelectKey.currentState!.validate();
},
),
),
const SizedBox(height: 40),
//################################################################################################
// MultiSelectChipField
//################################################################################################
MultiSelectChipField(
items: _items,
initialValue: [_animals[4], _animals[7], _animals[9]],
title: const Text("Animals"),
headerColor: Colors.blue.withOpacity(0.5),
decoration: BoxDecoration(
border: Border.all(color: Colors.blue.shade100, width: 1.8),
),
selectedChipColor: Colors.blue.withOpacity(0.5),
selectedTextStyle: TextStyle(color: Colors.blue[800]),
onTap: (values) {
_selectedAnimals4 = values;
},
),
const SizedBox(height: 40),
//################################################################################################
// MultiSelectDialogField with initial values
//################################################################################################
MultiSelectDialogField(
onConfirm: (values) {
_selectedAnimals5 = values;
},
dialogWidth: MediaQuery.of(context).size.width * 0.7,
items: _items,
initialValue:
_selectedAnimals5, // setting the value of this in initState() to pre-select values.
),
Heading
how to solve this error with this flutter dart dependency you have any solution????
It's just a null-safety issue. You should search for a good tutorial on that to better understand the meaning of the ? added at the end of a type.
From what I can see from the screenshot, you're passing a List<Animal> object where the code expects a List<Animal?> object: the difference is that the items in the first type CANNOT be null, while in the second type they MIGHT be null.
I'm guessing the problem is in the validatorof MultiSelectBottomSheetField<Animal> object. It's nice and fancy to just write things like (item) => something() but it's very easy to lose control on types.
I am design a screen in which I need to opening a drop down list when user click on textfield till now I am using CupertinoActionSheetAction sheet which is correctly working now I need to replace it with DropdownButton but when I am doing it is not displaying on screen I don't know why.
Here is my code focus on line number 136 (function for CupertinoActionSheetAction is working code) and line 138 where (function for drop not working code) according to me may be it due to build context but I m not sure how to use 'build context' in this context can any one help me out to fix that.
Thanks in advance, And any suggestion for making my code more reusable will be helpful as well :)
import 'dart:ffi';
import 'package:fleet_management/AppContants/Contants.dart';
import 'package:fleet_management/Controllers/NewFuelExpenseController.dart';
import 'package:fleet_management/Models/NewFuelExpenseModel.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class AddFuelView extends StatefulWidget {
const AddFuelView({Key? key}) : super(key: key);
#override
_AddFuelView createState() {
return _AddFuelView();
}
}
// MyTripHistoryView
class _AddFuelView extends State<AddFuelView> {
NewFuelExpenseModel fuelExpense =
NewFuelExpenseController().getNewFuelExpense();
DateTime _selectedDate = DateTime.now();
String dropdownvalue = 'Item 1';
// List of items in our dropdown menu
var items = [
'Item 1',
'Item 2',
'Item 3',
'Item 4',
'Item 5',
];
TextStyle _titleTextStyle = const TextStyle();
TextStyle _valueTextStyle = const TextStyle();
final GlobalKey newFuelExpenseFormField = GlobalKey<FormState>();
final TextEditingController _dateEditingController = TextEditingController();
final TextEditingController _priceTextEditingController =
TextEditingController();
final TextEditingController _gallonsTextEditingController =
TextEditingController();
final TextEditingController _totalTextEditingController =
TextEditingController();
final TextEditingController _odometerTextEditingController =
TextEditingController();
final TextEditingController _fuelTypeTextEditingController =
TextEditingController();
final TextEditingController _vendorTextEditingController =
TextEditingController();
#override
void initState() {
super.initState();
_titleTextStyle =
const TextStyle(fontSize: 16, fontWeight: FontWeight.w600);
_valueTextStyle = const TextStyle(
fontSize: 16, fontWeight: FontWeight.w600, color: Colors.black38);
_dateEditingController.text =
"${_selectedDate.day}-${_selectedDate.month}-${_selectedDate.year}";
}
#override
Widget build(BuildContext context) {
var scaffold = Scaffold(
appBar: AppBar(
title: Text(StringsConstants.newFuelExpense),
backgroundColor: AppColorsConstants.primaryColor,
actions: <Widget>[
FlatButton(
textColor: Colors.white,
onPressed: () {
print("SAVE Button Clicked");
},
child: Text("Save", style: _titleTextStyle),
),
],
),
body: SafeArea(
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(16),
child: Form(
key: newFuelExpenseFormField,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
showDateRow(context),
addTextFieldInput(
StringsConstants.priceGallon,
"\u{20B9}0.00",
false,
_priceTextEditingController,
TextInputType.datetime,
null,
null),
addTextFieldInput(
StringsConstants.gallons,
"",
false,
_gallonsTextEditingController,
TextInputType.number,
null,
null),
addTextFieldInput(
StringsConstants.total,
"\u{20B9}0.00",
false,
_totalTextEditingController,
TextInputType.number,
null,
null),
addTextFieldInput(
StringsConstants.odometer,
"",
false,
_odometerTextEditingController,
TextInputType.number,
null,
null),
// show action sheet
addTextFieldInput(
StringsConstants.fuelType,
"",
true,
_fuelTypeTextEditingController,
TextInputType.none,
null, () {
// Working. - >>>> HERE <<<<<
showActionSheet(context);
// Not Working >>>> HERE <<<<< Uncomment following function before
// showDropDown();
}),
addTextFieldInput(
StringsConstants.vendor,
"",
false,
_vendorTextEditingController,
TextInputType.text,
null,
null),
const SizedBox(
height: 50,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton(
onPressed: () {
print("Submit button pressed!");
},
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(horizontal: 24),
primary: AppColorsConstants.primaryColor,
textStyle:
const TextStyle(fontWeight: FontWeight.bold),
),
child: Text(StringsConstants.submit)),
ElevatedButton(
onPressed: () {
print("Cancel button pressed!");
},
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(horizontal: 24),
primary: AppColorsConstants.primaryColor,
textStyle:
const TextStyle(fontWeight: FontWeight.bold),
),
child: Text(StringsConstants.cancel))
],
)
],
),
),
),
),
),
);
return scaffold;
}
void showDropDown() {
DropdownButton<String>(
items: <String>['A', 'B', 'C', 'D'].map((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
onChanged: (_) {},
);
}
Future<dynamic> showActionSheet(BuildContext context) {
return showCupertinoModalPopup(
context: context,
builder: (BuildContext context) => CupertinoActionSheet(
title: const Text('Choose Options'),
actions: <Widget>[
CupertinoActionSheetAction(
child: const Text('Oil'),
onPressed: () {
_fuelTypeTextEditingController.text = "Oil";
Navigator.pop(context, 'Oil');
},
),
CupertinoActionSheetAction(
child: const Text('Petrol'),
onPressed: () {
_fuelTypeTextEditingController.text = "Petrol";
Navigator.pop(context, 'Petrol');
},
),
CupertinoActionSheetAction(
child: const Text('diesel'),
onPressed: () {
_fuelTypeTextEditingController.text = "diesel";
Navigator.pop(context, 'diesel');
},
)
],
cancelButton: CupertinoActionSheetAction(
child: const Text('Cancel'),
isDefaultAction: true,
onPressed: () {
Navigator.pop(context, 'Cancel');
},
)),
);
}
Container addTextFieldInput(
String title,
String initialValue,
bool isEditable,
TextEditingController textfieldController,
TextInputType keyboardType,
FormFieldValidator<String>? validator,
GestureTapCallback? tabCallback,
) {
return Container(
padding: const EdgeInsets.fromLTRB(0, 16, 0, 8),
child: SizedBox(
child: TextFormField(
onTap: tabCallback,
keyboardType: keyboardType,
cursorHeight: 16,
cursorWidth: 1.4,
readOnly: isEditable,
controller: textfieldController,
validator: validator,
decoration: InputDecoration(
isDense: true,
floatingLabelStyle:
TextStyle(color: AppColorsConstants.primaryColor),
labelText: title,
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: AppColorsConstants.primaryColor, width: 1.5),
),
enabledBorder: const OutlineInputBorder(
borderSide: BorderSide(color: Colors.black38, width: 1.5),
),
border: const OutlineInputBorder()),
style: const TextStyle(fontSize: 18),
cursorColor: Colors.black38,
showCursor: true,
autofocus: true,
),
),
);
}
Container showDateRow(BuildContext context) {
return Container(
child: TextFormField(
onTap: () => {_selectDate(context)},
cursorHeight: 16,
cursorWidth: 1.4,
readOnly: true,
enableInteractiveSelection: false,
controller: _dateEditingController,
decoration: InputDecoration(
isDense: true,
labelStyle: const TextStyle(color: Colors.orangeAccent),
labelText: StringsConstants.date,
focusedBorder: const OutlineInputBorder(
borderSide: BorderSide(color: Colors.orangeAccent, width: 1.5),
),
enabledBorder: const OutlineInputBorder(
borderSide: BorderSide(color: Colors.black38, width: 1.5),
),
border: const OutlineInputBorder()),
style: const TextStyle(fontSize: 18),
cursorColor: Colors.black38,
showCursor: true,
autofocus: true,
),
);
}
Future<void> _selectDate(BuildContext context) async {
final DateTime? picked = await showDatePicker(
context: context,
initialDate: _selectedDate,
firstDate: DateTime(1990),
lastDate: DateTime.now());
if (picked != null && picked != _selectedDate) {
setState(() {
_selectedDate = picked;
this._dateEditingController.text =
"${_selectedDate.day}-${_selectedDate.month}-${_selectedDate.year}";
});
}
}
}
For DropDown in flutter you need
an initail value,
a list to be shown just
String selectedvalue='myvalue';
/// be sure you add the variable value in the 0 index of you list other wise it will thrown error or exception..
List<String> myList=[
'myvalue',/// the value is same as variable value
'othe value', ....
];
DropDownButton(
onChanged: (resultValue){
/// you can get selected value from here
},
items: myList.map((e){
retrun DropdownMenuItem(
value: e,
child: Text(e));
}).toList(),
value: selectedvalue,
),
You can use DropdownButtonFormField in place of TextFormField and can make some style related changes per your requirement.
class MyWidget extends StatelessWidget {
String selectedValue = "USA";
List<DropdownMenuItem<String>> get dropdownItems{
List<DropdownMenuItem<String>> menuItems = [
DropdownMenuItem(child: Text("USA"),value: "USA"),
DropdownMenuItem(child: Text("Canada"),value: "Canada"),
DropdownMenuItem(child: Text("Brazil"),value: "Brazil"),
DropdownMenuItem(child: Text("England"),value: "England"),
];
return menuItems;
}
#override
Widget build(BuildContext context) {
return DropdownButtonFormField(
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.blue, width: 2),
borderRadius: BorderRadius.circular(20),
),
border: OutlineInputBorder(
borderSide: BorderSide(color: Colors.blue, width: 2),
borderRadius: BorderRadius.circular(20),
),
filled: true,
fillColor: Colors.blueAccent,
),
dropdownColor: Colors.blueAccent,
value: selectedValue,
onChanged: (String? newValue) {
selectedValue = newValue!;
},
items: dropdownItems);
}
}
I'm opening up a form to enter the details and close it upon filling everything and submitting it, but only the trailing icon is getting changed, also I'm trying to set the changes in the onExpansionChanged but not reflecting in the UI.
Updated Code
Scaffold(
backgroundColor: Colors.grey.shade200,
appBar: AppBar(
title: TextButton(
child: Text(count.toString()),
onPressed: () {
Navigator.push(context,
MaterialPageRoute(builder: (_) => RegisterLetterBookedListScreen()));
},
),
backgroundColor: ColorConstants.kPrimaryColor,
elevation: 0,
),
floatingActionButton: FloatingActionButton(
onPressed: () {
MotionToast.success(
title: 'Amount to be Collected',
titleStyle: TextStyle(fontWeight: FontWeight.bold),
description: '\u{20B9} $amountToBeCollected',
descriptionStyle: TextStyle(fontSize: 20, fontWeight: FontWeight.w500),
layoutOrientation: ORIENTATION.LTR,
animationType: ANIMATION.FROM_LEFT,
width: 300,
).show(context);
},
child: Text(
'\u{20B9} $amountToBeCollected',
style: TextStyle(fontSize: 20),
),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
),
body: Padding(
padding: const EdgeInsets.all(20.0),
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
//Article Details
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
//Sender Details
ExpansionTile(
key: GlobalKey(),
trailing: (senderExpansion == false)
? Icon(
MdiIcons.toggleSwitchOffOutline,
size: 40,
color: Colors.black54,
)
: Icon(MdiIcons.toggleSwitchOutline, size: 40, color: Colors.red),
onExpansionChanged: (value) {
senderExpansion = value;
},
maintainState: true,
initiallyExpanded: senderExpansion,
title: Text(
'Sender Details',
style: TextStyle(
fontWeight: FontWeight.bold,
color: senderHeadingColor,
fontSize: 20,
letterSpacing: 1),
),
children: [
Column(
children: [
CInputForm(
readOnly: false,
iconData: Icons.person,
labelText: 'Name *',
controller: senderNameController,
textType: TextInputType.text,
typeValue: 'Name',
focusNode: senderNameFocusNode,
),
CInputForm(
readOnly: false,
iconData: MdiIcons.home,
labelText: 'Address *',
controller: senderAddressController,
textType: TextInputType.multiline,
typeValue: 'Address',
focusNode: senderAddressFocusNode,
),
Card(
elevation: 0,
child: TypeAheadFormField(
textFieldConfiguration: TextFieldConfiguration(
style: TextStyle(color: Colors.blueGrey),
controller: senderPinCodeCityController,
autofocus: false,
decoration: InputDecoration(
prefixIcon: Icon(
Icons.location_on_outlined,
color: Colors.blueGrey,
),
fillColor: Colors.white,
filled: true,
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.white),
),
labelText: 'Pincode/Office Name *',
labelStyle: TextStyle(
color: ColorConstants.kAmberAccentColor),
border: OutlineInputBorder(
borderSide: BorderSide(color: Colors.white)))),
onSuggestionSelected:
(Map<String, String> suggestion) async {
senderPinCodeCityController.text = suggestion['pinCode']!;
senderCityController.text = suggestion['city']!;
senderStateController.text = suggestion['state']!;
},
itemBuilder: (context, Map<String, String> suggestion) {
return ListTile(
title: Text(suggestion['officeName']! +
", " +
suggestion['pinCode']!),
);
},
suggestionsCallback: (pattern) async {
return await FetchPin.getSuggestions(pattern);
},
validator: (value) {
if (value!.isEmpty) {
issPin = false;
isLoading = false;
}
},
),
),
Visibility(
visible: issPin == false ? senderPinCodeCityController.text.isEmpty ? true : false : false,
child: Align(
alignment: Alignment.topLeft,
child: Padding(
padding: const EdgeInsets.only(left: 17.0),
child: Text('Select a Pincode/Office name', style: TextStyle(fontSize: 10, color: ColorConstants.kPrimaryColor),),
)),
),
Visibility(
visible:
senderPinCodeCityController.text.isEmpty ? false : true,
child: CInputForm(
readOnly: true,
iconData: Icons.location_city,
labelText: 'City',
controller: senderCityController,
textType: TextInputType.text,
typeValue: 'City',
focusNode: senderPinCodeFocusNode,
),
),
Visibility(
visible:
senderPinCodeCityController.text.isEmpty ? false : true,
child: CInputForm(
readOnly: true,
iconData: Icons.location_city,
labelText: 'State',
controller: senderStateController,
textType: TextInputType.text,
typeValue: 'City',
focusNode: senderPinCodeFocusNode,
),
),
CInputForm(
readOnly: false,
iconData: MdiIcons.cellphone,
labelText: 'Mobile Number',
controller: senderMobileNumberController,
textType: TextInputType.number,
typeValue: 'MobileNumber',
focusNode: senderMobileFocusNode,
),
CInputForm(
readOnly: false,
iconData: MdiIcons.email,
labelText: 'Email',
controller: senderEmailController,
textType: TextInputType.emailAddress,
typeValue: 'Email',
focusNode: senderEmailFocusNode,
),
],
)
],
),
//Addressee Details
ExpansionTile(
trailing: (addresseeExpansion == false)
? Icon(
MdiIcons.toggleSwitchOffOutline,
size: 40,
color: Colors.black54,
)
: Icon(MdiIcons.toggleSwitchOutline, size: 40, color: Colors.red),
onExpansionChanged: (value) {
addresseeExpansion = value;
},
maintainState: true,
title: Text('Addressee Details',
style: TextStyle(
fontWeight: FontWeight.bold,
color: addresseeHeadingColor,
fontSize: 20,
letterSpacing: 1)),
children: [
Column(
children: [
CInputForm(
readOnly: false,
iconData: Icons.person,
labelText: 'Name *',
controller: addresseeNameController,
textType: TextInputType.text,
typeValue: 'Name',
focusNode: addresseeNameFocusNode,
),
CInputForm(
readOnly: false,
iconData: MdiIcons.home,
labelText: 'Address *',
controller: addresseeAddressController,
textType: TextInputType.multiline,
typeValue: 'Address',
focusNode: addresseeAddressFocusNode,
),
Card(
elevation: 0,
child: TypeAheadFormField(
textFieldConfiguration: TextFieldConfiguration(
style: TextStyle(color: Colors.blueGrey),
controller: addresseePinCodeCityController,
autofocus: false,
decoration: InputDecoration(
prefixIcon: Icon(
Icons.location_on_outlined,
color: Colors.blueGrey,
),
fillColor: Colors.white,
filled: true,
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.white),
),
labelText: 'Pincode/Office Name *',
labelStyle: TextStyle(
color: ColorConstants.kAmberAccentColor),
border: OutlineInputBorder(
borderSide: BorderSide(color: Colors.white)))),
onSuggestionSelected:
(Map<String, String> suggestion) async {
addresseePinCodeCityController.text =
suggestion['pinCode']!;
addresseeCityController.text = suggestion['city']!;
addresseeStateController.text = suggestion['state']!;
},
itemBuilder: (context, Map<String, String> suggestion) {
return ListTile(
title: Text(suggestion['officeName']! +
", " +
suggestion['pinCode']!),
);
},
suggestionsCallback: (pattern) async {
return await FetchPin.getSuggestions(pattern);
},
validator: (value) {
if (value!.isEmpty) {
isLoading = false;
isaPin = false;
}
},
),
),
Visibility(
visible: isaPin == false ? addresseePinCodeCityController.text.isEmpty ? true : false : false,
child: Align(
alignment: Alignment.topLeft,
child: Padding(
padding: const EdgeInsets.only(left: 17.0),
child: Text('Select a Pincode/Office name', style: TextStyle(fontSize: 10, color: ColorConstants.kPrimaryColor),),
)),
),
Visibility(
visible: addresseePinCodeCityController.text.isEmpty
? false
: true,
child: CInputForm(
readOnly: true,
iconData: Icons.location_city,
labelText: 'City',
controller: addresseeCityController,
textType: TextInputType.text,
typeValue: 'City',
focusNode: addresseePinCodeFocusNode,
),
),
Visibility(
visible: addresseePinCodeCityController.text.isEmpty
? false
: true,
child: CInputForm(
readOnly: true,
iconData: Icons.location_city,
labelText: 'State',
controller: addresseeStateController,
textType: TextInputType.text,
typeValue: 'State',
focusNode: addresseePinCodeFocusNode,
),
),
CInputForm(
readOnly: false,
iconData: MdiIcons.cellphone,
labelText: 'Mobile Number',
controller: addresseeMobileNumberController,
textType: TextInputType.number,
typeValue: 'MobileNumber',
focusNode: addresseeMobileFocusNode,
),
CInputForm(
readOnly: false,
iconData: MdiIcons.email,
labelText: 'Email',
controller: addresseeEmailController,
textType: TextInputType.emailAddress,
typeValue: 'Email',
focusNode: addresseeEmailFocusNode,
),
],
),
],
),
//Submit
Padding(
padding: const EdgeInsets.all(8.0),
child: Center(
child: ElevatedButton(
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all<Color>(Colors.white),
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
side: BorderSide(color: Colors.blueGrey)))),
onPressed: () async {
setState(() {
senderExpansion = !senderExpansion;
addresseeExpansion = !addresseeExpansion;
});
final ifPresent = await RegisterLetterTable()
.select()
.ArticleNumber
.equals(articleNumberController.text)
.toMapList();
if (ifPresent.isNotEmpty) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text('Article already scanned'),
behavior: SnackBarBehavior.floating,
));
} else {
if (articleNumberController.text.isEmpty) {
setState(() {
articleNumberFocusNode.requestFocus();
});
} else if (weightController.text.isEmpty) {
setState(() {
weightFocusNode.requestFocus();
});
} else if (insuranceCheck == true) {
if (insuranceController.text.isEmpty)
insuranceFocusNode.requestFocus();
} else if (valuePayableCheck == true) {
if (valuePayablePostController.text.isEmpty)
valuePayableFocusNode.requestFocus();
}
if (senderNameController.text.isEmpty ||
senderAddressController.text.isEmpty ||
senderPinCodeCityController.text.isEmpty) {
setState(() {
senderExpansion = true;
});
if (addresseeNameController.text.isEmpty ||
addresseeAddressController.text.isEmpty ||
addresseePinCodeCityController.text.isEmpty) {
setState(() {
addresseeExpansion = true;
});
} else
setState(() {
addresseeExpansion = false;
});
} else
senderExpansion = false;
if (addresseeNameController.text.isEmpty ||
addresseeAddressController.text.isEmpty ||
addresseePinCodeCityController.text.isEmpty) {
setState(() {
addresseeExpansion = true;
});
} else
setState(() {
addresseeExpansion = false;
});
if (formGlobalKey.currentState!.validate()) {
formGlobalKey.currentState!.save();
showDialog<void>(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return ConformationDialog(
articleNumber: articleNumberController.text,
weight: weightController.text,
prepaidAmount: prepaidAmountController.text,
acknowledgement: acknowledgementCheck,
insurance: insuranceCheck == true
? insuranceController.text
: '',
valuePayablePost: valuePayableCheck == true
? valuePayablePostController.text
: '',
amountToBeCollected:
amountToBeCollectedController.text,
senderName: senderNameController.text,
senderAddress: senderAddressController.text,
senderPinCode: senderPinCodeCityController.text,
senderCity: senderCityController.text,
senderState: senderStateController.text,
senderMobileNumber:
senderMobileNumberController.text,
senderEmail: senderEmailController.text,
addresseeName: addresseeNameController.text,
addresseeAddress: addresseeAddressController.text,
addresseePinCode:
addresseePinCodeCityController.text,
addresseeCity: addresseeCityController.text,
addresseeState: addresseeStateController.text,
addresseeMobileNumber:
addresseeMobileNumberController.text,
addresseeEmail: addresseeEmailController.text,
function: () {
Navigator.of(context).pop();
printFunction();
});
});
}
}
},
child: Padding(
padding: const EdgeInsets.all(8.0),
child: new Text(
'SUBMIT',
overflow: TextOverflow.ellipsis,
style: TextStyle(color: ColorConstants.kAmberAccentColor),
),
),
),
),
)
],
),
),
))
checkout below code it may help you,
class TestExpanTile extends StatefulWidget {
#override
TestExpanTileState createState() => new TestExpanTileState();
}
class TestExpanTileState extends State<TestExpanTile> {
String senderDet = 'Sender Details ';
bool formOpenFlag = true;
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
appBar: new AppBar(
title: const Text('ExpansionTile'),
),
body: new ExpansionTile(
key: GlobalKey(),
initiallyExpanded: formOpenFlag,
onExpansionChanged: (val) {
formOpenFlag = val; // update here on change
},
title: new Text(this.senderDet),
backgroundColor: Theme.of(context).accentColor.withOpacity(0.025),
children: <Widget>[
new ListTile(
title: const Text('Your Filling Form goes here'),
onTap: () {},
),
RaisedButton(
onPressed: () {
setState(() {
formOpenFlag = !formOpenFlag;
});
},
child: Text("Close Tile On Submit"),
)
],
),
),
);
}
}
Since your using Multiple ExpansionTiles, as said by #Jai Techie you need a key to control its state, but as per my knowledge we cannot provide the state of the ExpansionTile as the GlobalKey, so in order to acheive it create a new CustomExpansionTile.
import 'package:flutter/material.dart';
class FormExpansionTileCard extends StatefulWidget {
const FormExpansionTileCard({
Key? key,
this.leading,
required this.title,
this.subtitle,
this.onExpansionChanged,
this.children = const <Widget>[],
this.trailing,
this.borderRadius = const BorderRadius.all(Radius.circular(8.0)),
this.elevation = 2.0,
this.initialElevation = 0.0,
this.initiallyExpanded = false,
this.initialPadding = EdgeInsets.zero,
this.finalPadding = const EdgeInsets.only(bottom: 6.0),
this.contentPadding,
this.baseColor,
this.expandedColor,
this.expandedTextColor,
this.duration = const Duration(milliseconds: 200),
this.elevationCurve = Curves.easeOut,
this.heightFactorCurve = Curves.easeIn,
this.turnsCurve = Curves.easeIn,
this.colorCurve = Curves.easeIn,
this.paddingCurve = Curves.easeIn,
this.isThreeLine = false,
this.shadowColor = const Color(0xffaaaaaa),
this.animateTrailing = false,
}) : assert(initiallyExpanded != null),
super(key: key);
final bool isThreeLine;
final Widget? leading;
final Widget title;
final Widget? subtitle;
final ValueChanged<bool>? onExpansionChanged;
final List<Widget> children;
final Widget? trailing;
final bool animateTrailing;
final BorderRadiusGeometry borderRadius;
final double elevation;
final double initialElevation;
final Color shadowColor;
final bool initiallyExpanded;
final EdgeInsetsGeometry initialPadding;
final EdgeInsetsGeometry finalPadding;
final EdgeInsetsGeometry? contentPadding;
final Color? baseColor;
final Color? expandedColor;
final Color? expandedTextColor;
final Duration duration;
final Curve elevationCurve;
final Curve heightFactorCurve;
final Curve turnsCurve;
final Curve colorCurve;
final Curve paddingCurve;
#override
FormExpansionTileCardState createState() => FormExpansionTileCardState();
}
class FormExpansionTileCardState extends State<FormExpansionTileCard>
with SingleTickerProviderStateMixin {
static final Animatable<double> _halfTween =
Tween<double>(begin: 0.0, end: 0.5);
final ColorTween _headerColorTween = ColorTween();
final ColorTween _iconColorTween = ColorTween();
final ColorTween _materialColorTween = ColorTween();
late EdgeInsetsTween _edgeInsetsTween;
late Animatable<double> _elevationTween;
late Animatable<double> _heightFactorTween;
late Animatable<double> _turnsTween;
late Animatable<double> _colorTween;
late Animatable<double> _paddingTween;
late AnimationController _controller;
late Animation<double> _iconTurns;
late Animation<double> _heightFactor;
late Animation<double> _elevation;
late Animation<Color?> _headerColor;
late Animation<Color?> _iconColor;
late Animation<Color?> _materialColor;
late Animation<EdgeInsets> _padding;
bool _isExpanded = false;
#override
void initState() {
super.initState();
_edgeInsetsTween = EdgeInsetsTween(
begin: widget.initialPadding as EdgeInsets?,
end: widget.finalPadding as EdgeInsets?,
);
_elevationTween = CurveTween(curve: widget.elevationCurve);
_heightFactorTween = CurveTween(curve: widget.heightFactorCurve);
_colorTween = CurveTween(curve: widget.colorCurve);
_turnsTween = CurveTween(curve: widget.turnsCurve);
_paddingTween = CurveTween(curve: widget.paddingCurve);
_controller = AnimationController(duration: widget.duration, vsync: this);
_heightFactor = _controller.drive(_heightFactorTween);
_iconTurns = _controller.drive(_halfTween.chain(_turnsTween));
_headerColor = _controller.drive(_headerColorTween.chain(_colorTween));
_materialColor = _controller.drive(_materialColorTween.chain(_colorTween));
_iconColor = _controller.drive(_iconColorTween.chain(_colorTween));
_elevation = _controller.drive(
Tween<double>(begin: widget.initialElevation, end: widget.elevation)
.chain(_elevationTween));
_padding = _controller.drive(_edgeInsetsTween.chain(_paddingTween));
_isExpanded = PageStorage.of(context)?.readState(context) as bool? ??
widget.initiallyExpanded;
if (_isExpanded) _controller.value = 1.0;
}
#override
void dispose() {
_controller.dispose();
super.dispose();
}
// Credit: Simon Lightfoot - https://stackoverflow.com/a/48935106/955974
void _setExpansion(bool shouldBeExpanded) {
if (shouldBeExpanded != _isExpanded) {
setState(() {
_isExpanded = shouldBeExpanded;
if (_isExpanded) {
_controller.forward();
} else {
_controller.reverse().then<void>((void value) {
if (!mounted) return;
setState(() {
// Rebuild without widget.children.
});
});
}
PageStorage.of(context)?.writeState(context, _isExpanded);
});
if (widget.onExpansionChanged != null)
widget.onExpansionChanged!(_isExpanded);
}
}
void expand() {
_setExpansion(true);
}
void collapse() {
_setExpansion(false);
}
void toggleExpansion() {
_setExpansion(!_isExpanded);
}
Widget _buildChildren(BuildContext context, Widget? child) {
return Padding(
padding: _padding.value,
child: Material(
color: Colors.grey[200],
borderRadius: widget.borderRadius,
elevation: 0,
shadowColor: widget.shadowColor,
child: Container(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
InkWell(
customBorder:
RoundedRectangleBorder(borderRadius: widget.borderRadius),
onTap: toggleExpansion,
child: ListTileTheme.merge(
iconColor: _iconColor.value,
textColor: _headerColor.value,
child: Padding(
padding: const EdgeInsets.all(2.0),
child: ListTile(
isThreeLine: widget.isThreeLine,
contentPadding: widget.contentPadding,
leading: widget.leading,
title: widget.title,
subtitle: widget.subtitle,
trailing: RotationTransition(
turns: widget.trailing == null || widget.animateTrailing
? _iconTurns
: AlwaysStoppedAnimation(0),
child: widget.trailing ?? Icon(Icons.expand_more),
),
),
),
),
),
ClipRect(
child: Align(
heightFactor: _heightFactor.value,
child: child,
),
),
],
),
),
),
);
}
#override
void didChangeDependencies() {
final ThemeData theme = Theme.of(context);
_headerColorTween
..begin = theme.textTheme.subtitle1!.color
..end = widget.expandedTextColor ?? theme.accentColor;
_iconColorTween
..begin = theme.unselectedWidgetColor
..end = widget.expandedTextColor ?? theme.accentColor;
_materialColorTween
..begin = widget.baseColor ?? theme.canvasColor
..end = widget.expandedColor ?? theme.cardColor;
super.didChangeDependencies();
}
#override
Widget build(BuildContext context) {
final bool closed = !_isExpanded && _controller.isDismissed;
return AnimatedBuilder(
animation: _controller.view,
builder: _buildChildren,
child: closed ? null : Column(children: widget.children),
);
}
}
Initialize the key value in your dart file
final GlobalKey<FormExpansionTileCardState> cardA = new GlobalKey();
final GlobalKey<FormExpansionTileCardState> cardB = new GlobalKey();
//Sender Details
FormExpansionTileCard(
key: cardA,
trailing: (senderExpansion == false)
? Icon(
MdiIcons.toggleSwitchOffOutline,
size: 40,
color: Colors.black54,
)
: Icon(MdiIcons.toggleSwitchOutline, size: 40, color: Colors.red),
onExpansionChanged: (value) {
senderExpansion = value;
},
initiallyExpanded: senderExpansion,
title: Text(
'Sender Details',
style: TextStyle(
fontWeight: FontWeight.bold,
color: senderHeadingColor,
fontSize: 20,
letterSpacing: 1),
),
children: [
//...Your Widgets
],
),
//Addressee Details
FormExpansionTileCard(
key: cardB,
trailing: (senderExpansion == false)
? Icon(
MdiIcons.toggleSwitchOffOutline,
size: 40,
color: Colors.black54,
)
: Icon(MdiIcons.toggleSwitchOutline, size: 40, color: Colors.red),
onExpansionChanged: (value) {
addresseeExpansion = value;
},
initiallyExpanded: addresseeExpansion,
title: Text(
'AddresseeDetails',
style: TextStyle(
fontWeight: FontWeight.bold,
color: senderHeadingColor,
fontSize: 20,
letterSpacing: 1),
),
children: [
//...Your Widgets
],
),
I created a simple solution to this very problem. Hope this helps.
Solution: https://github.com/TreyThomas93/flutter-expansion-tile-demo
I have a problem with DataTable in flutter. I want to change the state of the row, when the user click on one of them, but I found just how to do this "manually" with selected: true, inside DataRow.
How can I let the user select just a single row, and deselect the rest, by changing the state?
content: Column(
children: <Widget>[
DataTable(
columns: [
DataColumn(label: Text('Language')),
DataColumn(label: Text('Translation')),
],
rows: [
DataRow(selected: true, cells: [
DataCell(
Text(
"RO",
textAlign: TextAlign.left,
style: TextStyle(fontWeight: FontWeight.bold),
),
onTap: () {
setState(() {
color = Colors.lightBlueAccent;
});
},
),
DataCell(
TextField(
decoration: InputDecoration(
border: InputBorder.none, hintText: 'paine'),
),
),
]),
DataRow(cells: [
DataCell(
Text(
"EN",
textAlign: TextAlign.left,
style: TextStyle(fontWeight: FontWeight.bold),
), onTap: () {
print('EN is clicked');
}),
DataCell(
TextField(
decoration: InputDecoration(
border: InputBorder.none, hintText: 'bread'),
),
),
]),
DataRow(cells: [
DataCell(
Text(
"FR",
textAlign: TextAlign.left,
style: TextStyle(fontWeight: FontWeight.bold),
), onTap: () {
print('FR is clicked');
}),
DataCell(
TextField(
decoration: InputDecoration(
border: InputBorder.none, hintText: 'pain'),
),
),
]),
],
),
],
),
You can copy past run full code below
You can use condition in selected like this 0 == selectedIndex where 0 is DataRow index
and change selectedIndex in onSelectChanged
code snippet
int selectedIndex = -1;
...
rows: [
DataRow(
selected: 0 == selectedIndex,
onSelectChanged: (val) {
setState(() {
selectedIndex = 0;
});
},
...
DataRow(
selected: 1 == selectedIndex,
onSelectChanged: (val) {
setState(() {
selectedIndex = 1;
});
},
working demo
full code
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Color color;
int selectedIndex = -1;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
children: <Widget>[
DataTable(
onSelectAll: (val) {
setState(() {
selectedIndex = -1;
});
},
columns: [
DataColumn(label: Text('Language')),
DataColumn(label: Text('Translation')),
],
rows: [
DataRow(
selected: 0 == selectedIndex,
onSelectChanged: (val) {
setState(() {
selectedIndex = 0;
});
},
cells: [
DataCell(
Text(
"RO",
textAlign: TextAlign.left,
style: TextStyle(fontWeight: FontWeight.bold),
),
onTap: () {
setState(() {
color = Colors.lightBlueAccent;
});
},
),
DataCell(
TextField(
decoration: InputDecoration(
border: InputBorder.none, hintText: 'paine'),
),
),
]),
DataRow(
selected: 1 == selectedIndex,
onSelectChanged: (val) {
setState(() {
selectedIndex = 1;
});
},
cells: [
DataCell(
Text(
"EN",
textAlign: TextAlign.left,
style: TextStyle(fontWeight: FontWeight.bold),
), onTap: () {
print('EN is clicked');
}),
DataCell(
TextField(
decoration: InputDecoration(
border: InputBorder.none, hintText: 'bread'),
),
),
]),
DataRow(
selected: 2 == selectedIndex,
onSelectChanged: (val) {
setState(() {
selectedIndex = 2;
});
},
cells: [
DataCell(
Text(
"FR",
textAlign: TextAlign.left,
style: TextStyle(fontWeight: FontWeight.bold),
), onTap: () {
print('FR is clicked');
}),
DataCell(
TextField(
decoration: InputDecoration(
border: InputBorder.none, hintText: 'pain'),
),
),
]),
],
),
],
),
),
);
}
}
When I needed to call something when I pressed on the DataRow I did the following:
DataRow(
onSelectChanged(_) {
// do something here
}
cells: [],
),
Maybe this will help?
EDIT: this is a simple example of how to select/deselect rows
import 'package:flutter/material.dart';
class Stack1 extends StatefulWidget {
#override
_Stack1State createState() => _Stack1State();
}
class _Stack1State extends State<Stack1> {
bool row1Selected = false;
bool row2Selected = false;
#override
Widget build(BuildContext context) {
return Scaffold(
body: DataTable(
columns: [
DataColumn(
label: Text('My Data'),
),
],
rows: [
DataRow(
selected: row1Selected,
onSelectChanged: (value) {
setState(() {
row1Selected = value;
});
},
cells: [
DataCell(
Text('Data 1'),
),
],
),
DataRow(
selected: row2Selected,
onSelectChanged: (value) {
setState(() {
row2Selected = value;
});
},
cells: [
DataCell(
Text('Data 2'),
),
],
),
],
),
);
}
}
DataTable(
dataTextStyle: TextStyle(
fontSize: 12,
),
headingTextStyle: TextStyle(fontSize: 12),
dataRowHeight: 100,
decoration: BoxDecoration(
color: Constants.backgroundColor,
borderRadius: BorderRadius.circular(20),
// border: Border.all(color: Colors.black),
boxShadow: [
BoxShadow(
color: Colors.grey,
spreadRadius: 2,
blurRadius: 2,
offset: Offset(1, 1),
),
],
),
dividerThickness: 2,
showCheckboxColumn: false,
onSelectAll: (value) {},
columns: [
DataColumn(
label: Text(
'Unit No.',
style: TextStyle(
fontWeight: FontWeight.bold, color: Constants.appColor2),
)),
DataColumn(
label: Text(
'Unit Type',
style: TextStyle(
fontWeight: FontWeight.bold, color: Constants.appColor2),
)),
DataColumn(
label: Text(
'Description',
style: TextStyle(
fontWeight: FontWeight.bold, color: Constants.appColor2),
)),
],
rows: List.generate(
data.length,
(index) => DataRow(
selected: selectedUnit == index,
onSelectChanged: (value) {
print(value);
setState(() {
selectedUnit = index;
unitNumber = data[index].unitId;
});
PersistentNavBarNavigator.pushNewScreen(context,
screen: ShowProductDetails(
unitId: data[index].unitId,
));
},
cells: [
DataCell(Text(
data[index].unitId,
style: TextStyle(
color: Constants.matGold,
),
)),
DataCell(Text(
data[index].unitType,
style: TextStyle(
color: Constants.peach,
),
)),
DataCell(Text(
data[index].decription,
style: TextStyle(
color: Constants.appColor,
),
)),
]),
),
),
I'm currently developing an app.
For this, I used the flutter stepper, but I have the problem that the inner content is not scrollable, I already tried several possibilities, but unsuccessfully.
I have inserted image + code
I hope you can help me.
Picture:
Stepper:
body: Container(
child: Stepper(
physics: BouncingScrollPhysics(),
steps: stepsStammdaten(),
currentStep: currentStep,
onStepContinue: next,
onStepTapped: (step) => goTo(step),
onStepCancel: cancel,
),
Step(
state: StepState.indexed,
isActive: true,
title: const Text('Rejkla'),
content: ListView.builder(
shrinkWrap: true,
itemCount: this.index,
itemBuilder: (context, index) => this._buildRow(index),
)
),ยดยดยด
The method buildRow() contains a ListView
return ListView(
physics: const AlwaysScrollableScrollPhysics(),
shrinkWrap: true,
children: <Widget>[
// Here are some text inputs
]);
This code works perfect for me.
By Replacing your below code
physics: BouncingScrollPhysics(),
with this
physics : ClampingScrollPhysics(),
It should be able to scroll perfectly.
Thanks to both of you Mukul and CodOg. I also got stuck in the same kind of problem, and I read your conversation, its helped me a lot to solve the problem. I tried this one. And this one is working.
import 'package:flutter/material.dart';
class AddMember extends StatefulWidget {
#override
_AddMemberState createState() => _AddMemberState();
}
class _AddMemberState extends State<AddMember> {
int _currentStep = 0;
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('ADD MEMBERS'),
backgroundColor: Colors.orange,
),
body: Theme(
data: ThemeData(primaryColor: Colors.orange),
child: Form(
child: new Stepper(
physics: ClampingScrollPhysics(),
steps: _myStep(),
currentStep: this._currentStep,
onStepTapped: (step) {
setState(() {
this._currentStep = step;
});
},
onStepContinue: () {
setState(() {
if (this._currentStep < this._myStep().length - 1) {
this._currentStep = this._currentStep + 1;
} else {
print('Completed, Check the Filed');
}
});
},
onStepCancel: () {
setState(() {
if (this._currentStep > 0) {
this._currentStep = this._currentStep - 1;
} else {
this._currentStep = 0;
}
});
},
),
),
),
);
}
List<Step> _myStep() {
List<Step> _steps = [
Step(
title: Text('Personal Details'),
content: new Container(
height: 500,
child: SingleChildScrollView(
child: Column(
children: <Widget>[
new TextFormField(
autofocus: true,
decoration: InputDecoration(
hintText: "First Name",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5.0),
borderSide: BorderSide(
color: Colors.orange,
style: BorderStyle.solid,
)),
),
),
new TextFormField(
autofocus: true,
decoration: InputDecoration(
hintText: "First Name",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5.0),
borderSide: BorderSide(
color: Colors.orange,
style: BorderStyle.solid,
)),
),
),
new TextFormField(
autofocus: true,
decoration: InputDecoration(
hintText: "First Name",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5.0),
borderSide: BorderSide(
color: Colors.orange,
style: BorderStyle.solid,
)),
),
),
new TextFormField(
autofocus: true,
decoration: InputDecoration(
hintText: "First Name",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5.0),
borderSide: BorderSide(
color: Colors.orange,
style: BorderStyle.solid,
)),
),
),
],
)
),
),
isActive: _currentStep >= 0,
),
Step(
title: Text('Residence Details'),
content: Form(child: TextField()),
isActive: _currentStep >= 1,
),
Step(
title: Text('Office Details'),
content: Form(child: TextField()),
isActive: _currentStep >= 2,
),
Step(
title: Text('Native Details'),
content: Form(child: TextField()),
isActive: _currentStep >= 3,
),
Step(
title: Text('Others Details'),
content: Form(child: TextField()),
isActive: _currentStep >= 4,
),
];
return _steps;
}
}