Flutter Dropdown list expanding instead of scrolling - flutter

So im making my first Dropdown but when i have a lot of Strings it expands upwards, is there a way to compact the list and make it scrollable or am i using the wrong Widget?
class _DropdownBehaivorButton extends StatefulWidget {
const _DropdownBehaivorButton({super.key});
#override
State<_DropdownBehaivorButton> createState() => _DropdownBehaivorButtonState();
}
class _DropdownBehaivorButtonState extends State<_DropdownBehaivorButton> {
String dropdownvalue = 'Agresivo';
var tipos = [
'Agresivo',
'Tranquilo',
'Travieso',
'Docil',
'Travieso',
'Travieso',
'Travieso'
];
#override
Widget build(BuildContext context) {
return
DropdownButtonHideUnderline(
child: DropdownButton(
borderRadius: BorderRadius.circular(25),
isExpanded: true,
iconEnabledColor: Color(0xff525252),
dropdownColor: Colors.white,
style: _textStyle(),
value: dropdownvalue,
icon: const Icon(Icons.keyboard_arrow_down),
items: tipos.map((String items) {
return DropdownMenuItem(
value: items,
child: Center(child: Text(items)),
);
}).toList(),
onChanged: (String? newValue) {
setState(() {
dropdownvalue = newValue!;
});
},
),
);
}
TextStyle _textStyle() => TextStyle(
fontSize: 18,color: Color.fromARGB(123, 82, 82, 82),fontWeight: FontWeight.w400) ;}
I was expecting a compact dropdown list like this

DropdownButton(
menuMaxHeight: 100, // this line
hint: const Text(
"Please select Child / Patient"),
underline: const SizedBox(),
isExpanded: true,
iconEnabledColor: Colors.blue[800],
dropdownColor: Colors.grey[100],
style: TextStyle(
letterSpacing: 2,
fontWeight: FontWeight.bold,
fontSize: 12,
color: Colors.grey[800]),
value: patientName,
items: patients.map((patient) {
return DropdownMenuItem(
value: patient,
child: Text(patient.childName),
);
}).toList(),
onChanged: (value) {
setState(() {
patientName = value;
debugPrint(patientName!
.toJson()
.toString());
});
}),
try changing the menu max height

Try to add dropdownMaxHeight: 200
Here you will find what you need https://pub.dev/packages/dropdown_button2

Related

Flutter dropdown with getX not working properly on some devices

I'm using getx for state management,here's the video of the problem
https://drive.google.com/file/d/1tm2M46pkXVnGuf4vyh9rNs2HY2TdtBD8/view?usp=sharing
here is my code
class ActivitiesController extends GetxController {
late List<String> statusList = ["All", "Approved", "Unapproved"];
var selectedStatus = "Approved".obs;
}
#override
ActivitiesController get controller => Get.put(ActivitiesController());
in view:
const RequiredText(text: "Status"),
const SizedBox(height: Constants.defaultPadding / 2),
Obx(
() => GlobalDropDownContainer(
hintText: "All",
items: controller.statusList.toList(),
onChange: (value) {
controller.selectedStatus(value);
},
selectedValue: controller.selectedStatus.value,
)),
Here is the "GlobalDropDownContainer" code
import 'package:flutter/material.dart';
import 'package:get/get.dart';
class GlobalDropDownContainer extends StatelessWidget {
final String hintText;
final List<String> items;
final double? width;
final Color? isNotValid;
final Function(String?) onChange;
final String? selectedValue;
const GlobalDropDownContainer({
Key? key,
required this.hintText,
required this.items,
this.width,
this.isNotValid,
required this.onChange,
this.selectedValue,
}) : super(key: key);
#override
Widget build(BuildContext context) {
Size size = Get.size;
return Container(
width: width != null ? (size.width * width!) : Get.width,
padding: const EdgeInsets.symmetric(horizontal: 10),
decoration: BoxDecoration(
border: Border.all(
width: 1,
color: isNotValid ??
Theme.of(context).colorScheme.onSurface.withOpacity(0.5),
),
color:Theme.of(context).colorScheme.background,
borderRadius: BorderRadius.circular(5)),
child: DropdownButton<String>(
dropdownColor: Theme.of(context).colorScheme.background,
value: selectedValue != null && selectedValue!.isNotEmpty
? selectedValue
: null,
isExpanded: true,
underline: const SizedBox(),
hint: Text(
hintText,
style: const TextStyle(
color: Color(0xFF666666),
),
),
style: TextStyle(
color: Theme.of(context).colorScheme.onBackground,
),
items: items.map((String value) {
return DropdownMenuItem<String>(
value: value != null && value.isNotEmpty ? value : null,
child: Text(
value,
style: TextStyle(
color: Theme.of(context).colorScheme.onBackground),
),
);
}).toList(),
onChanged: onChange,
));
}
}
I searched for a day and i didn't find anything, i tried debug the code but it gives no warning or error. Can Anyone help me?
Try this one
Make an instance of a controller, which i presumed u have done already.
final controller = Get.put(yourgetxcontrollername());
The Widget code
Obx(
() => DropdownButton<String>(
isExpanded: true,
value: controller.selectedStatus.value,
icon: const Icon(Icons.arrow_drop_down),
iconSize: 24,
elevation: 16,
style: const TextStyle(
color: Colors.blue,
fontSize: 14,
),
onChanged: (value) {
controller.selectedStatus(
value,
);
},
items: controller.statusList.map<DropdownMenuItem<String>>(
(String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(
value,
style: const TextStyle(
color: Colors.black,
),
),
);
},
).toList(),
),
)

how to make the value of DropDown Button updated?

so i aim to use a dropDownButton if already i have selected an option i find it selected ( the value is saved in DataBase) and of course it can be modified else if i didn't choose any option i choose . so this is using the attribute value : value: box.read("optioSaved") ?? dropDownValue, but here if the user has already choose a value he can't modified it
how can i do ?
this is the full code :
child: DropdownButton<String>(
icon: const Icon(Icons.keyboard_arrow_down),
isExpanded: true,
style: const TextStyle(
color: Colors.black,
fontSize: 17,
fontFamily: 'SFProRegular',
),
underline: Container(
height: 1,
color: Colors.black,
),
onChanged: (String? newValue) {
setState(() {
dropDownValue = newValue;
});
},
items: <String>[
"option1",
"option 2",
].map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
value: box.read("optioSaved") ?? dropDownValue,
hint: const Text("choose"),
),
assign box.read("optioSaved") to dropDownValue in initState and then just value: dropDownValue

How to make DropdownButton menu width to fit text?

I want to have a dropdown button that has a width based on the menu text length. The dropdown arrow does not have any additional spacing between text.
Like this:
Currently, I am getting this:
My dropdown button arrow is positioned based on the longest text.
My code:
Widget dropdownList(){
return Container(
child: DropdownButton<Location>(
value: _selectedValue,
icon: const Icon(Icons.expand_more),
iconSize: 30,
underline: SizedBox(),
onChanged: (Location? newValue) {
setState(() {
_selectedValue = newValue!;
});
},
style: const TextStyle(color: Colors.blue),
selectedItemBuilder: (BuildContext context) {
return locationList.map((Location value) {
return Container(
child: Text(
value.name,
style: const TextStyle(color: Colors.black,fontSize: 30,
fontWeight: FontWeight.w300),
),
);
}).toList();
},
items: locationList.map<DropdownMenuItem<Location>>((Location value) {
return DropdownMenuItem<Location>(
value: value,
child: Text(value.name, style: TextStyle(color: Colors.black,fontSize: 15,
fontWeight: FontWeight.w300)),
);
}).toList(),
),
);
}
According to the documentations there is a property for DropDownButton called isExpanded:
isExpanded → bool
Set the dropdown's inner contents to horizontally fill its parent. [...]
final
so just set:
isExpanded = true;

Dropdownbutton restrict shown items

Ive got the following Problem:
I want the user to choose a day of month with a dropdownbutton. So my items are the numbers 1 to 31. Now the list got pretty long and the Dropdownbutton is really large. Is there a Solution to show e.g. only 5 Elements at the same time?
Widget buildDropdownMonthlyTurnus() {
return DropdownButton<int>(
value: _selectedDay,
icon: Icon(Icons.arrow_downward),
iconSize: 24,
elevation: 16,
style: TextStyle(color: Colors.blue),
underline: Container(
height: 2,
color: Colors.blue,
),
onChanged: (int newValue) {
setState(() {
_selectedDay = newValue;
});
},
items: Constants.daysOfMonth.map((int value) {
return new DropdownMenuItem<int>(
value: value,
child: new Text(
value.toString(),
style: new TextStyle(color: Colors.black),
),
);
}).toList());
}
In the link you see my problem with the large list.
enter image description here
For this problem you can use listview, inside a container and show manage its size according to the list items shown, you don't need to use dropdown items at all.
Use the menuMaxHeight property of the DropdownButton class. It's a recent addition to control the height of the menu.
Widget buildDropdownMonthlyTurnus() {
return DropdownButton<int>(
menuMaxHeight: 200.0,
value: _selectedDay,
icon: Icon(Icons.arrow_downward),
iconSize: 24,
elevation: 16,
style: TextStyle(color: Colors.blue),
underline: Container(
height: 2,
color: Colors.blue,
),
onChanged: (int newValue) {
setState(() {
_selectedDay = newValue;
});
},
items: Constants.daysOfMonth.map((int value) {
return new DropdownMenuItem<int>(
value: value,
child: new Text(
value.toString(),
style: new TextStyle(color: Colors.black),
),
);
}).toList());

Updating parent form from child using Radio

I am developing a form with 11 multiple choice questions.
Ive created a statefull widget which takes the question and displays this along with 3 radio buttons as below.
Each question needs to update different property in a model defined within the parent widget.
for example:
RadioQuestionWidget("What colour is the sky?", model.ColourOfSky),
RadioQuestionWidget("What colour is the grass?", model.ColourOfGrass)
Below is my RadioQuestionWidget
import 'package:flutter/material.dart';
class RadioQuestionWidget extends StatefulWidget {
RadioQuestionWidget({Key key, this.question}) : super(key: key);
final String question;
#override
_RadioQuestionWidgetState createState() => _RadioQuestionWidgetState();
}
class _RadioQuestionWidgetState extends State<RadioQuestionWidget> {
String question;
var _radioValue;
#override
void initState() {
super.initState();
question = widget.question;
}
#override
Widget build(BuildContext context) {
return Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Text(
question,
style: new TextStyle(
fontSize: 16.0,
color: Colors.black,
fontWeight: FontWeight.bold),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: <Widget>[
Radio(
value: "Yes",
groupValue: _radioValue,
onChanged: (val) {
setState(() {
_radioValue = val;
});
},
activeColor: Colors.green,
focusColor: Colors.black,
),
new Text(
'Yes',
style: new TextStyle(fontSize: 16.0, color: Colors.black),
),
Radio(
value: "No",
groupValue: _radioValue,
onChanged: (val) {
setState(() {
_radioValue = val;
});
},
activeColor: Colors.green,
focusColor: Colors.black,
),
new Text(
'No',
style: new TextStyle(fontSize: 16.0, color: Colors.black),
),
Radio(
value: "Three",
groupValue: _radioValue,
onChanged: (val) {
setState(() {
_radioValue = val;
});
},
activeColor: Colors.red,
focusColor: Colors.black,
),
new Text(
'Not applicable',
style: new TextStyle(fontSize: 16.0, color: Colors.black),
),
],
),
),
],
),
);
}
}
First of all, define one function in your parent widget with required arguments i.e your question number and answer.
void _updateProperty(int que_num, String ans) {
//update property according to your question number and ans
}
Now pass your function to child widget as the Constructor argument.
RadioQuestionWidget(question : "What colour is the sky?", updatePropertyHandler : _updateProperty)
Receive your function in child widget like below.
class RadioQuestionWidget extends StatefulWidget {
RadioQuestionWidget({Key key, this.question, this.updatePropertyHandler}) : super(key: key);
final String question;
final Function updatePropertyHandler;
#override
_RadioQuestionWidgetState createState() => _RadioQuestionWidgetState();
}
Now in your child widget while you answering the question, call _updateUi function as per your need.
Radio(
value: "Yes",
groupValue: _radioValue,
onChanged: (val) {
setState(() {
_radioValue = val;
//here questionNum is int value you need to handle question no
widget.updatePropertyHandler(questionNum, _radioValue);
});
},
activeColor: Colors.green,
focusColor: Colors.black,
)
Firstly please mark the above answer as the correct one as i couldn't have got it working without the help of #Alpesh.
I had to slightly amend the answer in order to update the correct property of the model.
This in my parent widget:
RadioQuestionWidget(
question: 'Question 1',
updatePropertyHandler: (String ans) => {
setState(() {
_qc.speedForSpeedChaeckCompleted = ans;
})
},
),
and this is my RadioQuestionWidget:
import 'package:flutter/material.dart';
class RadioQuestionWidget extends StatefulWidget {
RadioQuestionWidget({Key key, this.question, this.updatePropertyHandler})
: super(key: key);
final String question;
final Function updatePropertyHandler;
#override
_RadioQuestionWidgetState createState() => _RadioQuestionWidgetState();
}
class _RadioQuestionWidgetState extends State<RadioQuestionWidget> {
String question;
var _groupValue;
Function(String) onCountChange;
#override
void initState() {
super.initState();
question = widget.question;
_groupValue = 'Not Applicable';
}
#override
Widget build(BuildContext context) {
return Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Text(
question,
style: new TextStyle(
fontSize: 16.0,
color: Colors.black,
fontWeight: FontWeight.bold),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: <Widget>[
Radio(
value: "Yes",
groupValue: _groupValue,
onChanged: (val) {
setState(() {
_groupValue = val;
//here questionNum is int value you need to handle question no
widget.updatePropertyHandler(val);
});
},
activeColor: Colors.green,
focusColor: Colors.black,
),
new Text(
'Yes',
style: new TextStyle(fontSize: 16.0, color: Colors.black),
),
Radio(
value: "No",
groupValue: _groupValue,
onChanged: (val) {
setState(() {
_groupValue = val;
//here questionNum is int value you need to handle question no
widget.updatePropertyHandler(val);
});
},
activeColor: Colors.green,
focusColor: Colors.black,
),
new Text(
'No',
style: new TextStyle(fontSize: 16.0, color: Colors.black),
),
Radio(
value: "Not Applicable",
groupValue: _groupValue,
onChanged: (val) {
setState(() {
_groupValue = val;
//here questionNum is int value you need to handle question no
widget.updatePropertyHandler(val);
});
},
activeColor: Colors.red,
focusColor: Colors.black,
),
new Text(
'Not applicable',
style: new TextStyle(fontSize: 16.0, color: Colors.black),
),
],
),
),
],
),
);
}
}