Good morning, I am trying to align the DropDown's arrow icon with the hint text but I can't understand why the render engine positions it so far below.
I tried to set the InputDecoration's contentPadding
property to EdgeInsets.zero
and it seemed to work. However, it ruined the DropDown's focusBorder. Furthermore, I didn't understand what element the padding is attached to.
class WorkpieceFilterBox extends StatefulWidget {
const WorkpieceFilterBox({
Key? key,
}) : super(key: key);
@override
State<WorkpieceFilterBox> createState() => _WorkpieceFilterBoxState();
}
class _WorkpieceFilterBoxState extends State<WorkpieceFilterBox> {
final FocusNode _statusFieldFocus = FocusNode();
final FocusNode _searchFieldFocus = FocusNode();
bool hasTextFieldSelected = false;
void _onFocusChange() {
setState(() {
hasTextFieldSelected =
_statusFieldFocus.hasFocus || _searchFieldFocus.hasFocus;
});
}
@override
void initState() {
super.initState();
_statusFieldFocus.addListener(_onFocusChange);
_searchFieldFocus.addListener(_onFocusChange);
}
@override
void dispose() {
super.dispose();
_statusFieldFocus.removeListener(_onFocusChange);
_statusFieldFocus.dispose();
_searchFieldFocus.removeListener(_onFocusChange);
_searchFieldFocus.dispose();
}
@override
Widget build(BuildContext context) {
return SizedBox(
height: 55.0,
child: Stack(
children: <Widget>[
_buildGroundLayer(),
_buildDividerLayer(),
_buildInputLayer(),
],
),
);
}
Widget _buildGroundLayer() {
return Container(
decoration: BoxDecoration(
color: Colors.transparent,
border: Border.all(
color: Color(0xFFD2D2D2),
width: 2.5,
),
borderRadius: BorderRadius.circular(27.0),
),
);
}
Widget _buildDividerLayer() {
return SizedBox(
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Expanded(
flex: 2,
child: SizedBox(),
),
Visibility(
visible: !hasTextFieldSelected,
child: VerticalDivider(
width: 8.0,
thickness: 2.0,
indent: 10.0,
endIndent: 10.0,
color: Color(0xFFD2D2D2),
),
),
Expanded(
flex: 3,
child: SizedBox(),
),
],
),
);
}
Widget _buildInputLayer() {
return Row(
children: <Widget>[
Expanded(
flex: 2,
child: _buildStatusField(),
),
Expanded(
flex: 3,
child: _buildSearchField(),
),
],
);
}
Widget _buildStatusField() {
return DropdownButtonFormField<String>(
focusNode: _statusFieldFocus,
icon: Icon(
Icons.expand_more,
size: 30.0,
color: Color(0xFF2E2E2E),
),
hint: Text(
'Status',
style: TextStyle(
fontSize: 18.0,
fontWeight: FontWeight.w500,
color: Color(0xFFA6A6A6),
),
),
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.transparent,
width: 2.5,
),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(27.0),
bottomLeft: Radius.circular(27.0),
),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Color(0xFFFF7321),
width: 2.5,
),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(27.0),
bottomLeft: Radius.circular(27.0),
),
),
),
items: widget.values
.map<DropdownMenuItem<String>>(
(WorkpieceStatus status) => DropdownMenuItem<String>(
value: status.text,
child: Text(
status.text,
style: TextStyle(
fontSize: 18.0,
fontWeight: FontWeight.w500,
color: status.color,
fontFamily: 'RobotoFlex-Regular',
),
),
),
)
.toList(),
onChanged: (String? value) => print(value),
);
}
Widget _buildSearchField() {
return TextField(
focusNode: _searchFieldFocus,
cursorColor: Color(0xFF131415),
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.transparent,
width: 2.5,
),
borderRadius: BorderRadius.only(
topRight: Radius.circular(27.0),
bottomRight: Radius.circular(27.0),
),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Color(0xFFFF7321),
width: 2.5,
),
borderRadius: BorderRadius.only(
topRight: Radius.circular(27.0),
bottomRight: Radius.circular(27.0),
),
),
prefixIcon: Icon(
Icons.search,
size: 24.0,
color: Color(0xFF2E2E2E),
),
hintText: 'Search by UII',
hintStyle: TextStyle(
fontSize: 18.0,
fontWeight: FontWeight.w500,
color: Color(0xFFA6A6A6),
),
),
onChanged: (String value) => print(value),
);
}
}
CodePudding user response:
DropdownButton is a material component as seen on
Here, you can see why setting the height is a bad idea on a Material Component.
Enough talking, what is the solution: Remove the height from SizedBox and any styling that is given by the material component:
return DropdownButtonFormField<String>(
icon: const Icon(
Icons.expand_more,
//size: 30.0,
color: Color(0xFF2E2E2E),
),
hint: const Text(
'Status',
style: TextStyle(
//fontSize: 18.0,
//fontWeight: FontWeight.w500,
color: Color(0xFFA6A6A6),
),
),
Now I know this will break your UI, but this is how Flutter works. Either you completely adopt the Material Design, or you will have a really bad time.
CodePudding user response:
Try this example code I wrote for you.
My code:
DropdownButtonHideUnderline(
child: DropdownButtonFormField<String>(
decoration: const InputDecoration(
border: OutlineInputBorder(),
),
icon: const Icon(
Icons.expand_circle_down, // Custom icon goes here.
),
iconSize: 30, // Icon height goes here.
hint: const Text('Choose item'),
value: _dropDownValue,
items: _dropDownList
.map(
(label) => DropdownMenuItem(
value: label,
child: Text(
label.toString(),
),
),
)
.toList(),
onChanged: (value) {
_dropDownValue = (value ?? _dropDownList[0]);
setState(() {});
},
),
),