dart - Adjust the size of the DropdownMenuItem in Flutter - Stack Overflow

admin2025-04-28  4

I have created a textfield, which has a dropdown button with the history of the textfield. What concerns me is that this field will be used to display IP address, which does not fit as I want in the history dropdown:

as you can see, the address is on two lines instead of one, which is as big as the textfield for example (200px in this case). I tried wrapping the DropdownMenuItem in a SizedBox and fixing its width to 200px for example but did not work.. Here is my Widget:

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';

class HistoryTextField extends StatefulWidget {
  final String fieldType;
  final String hintText;

  const HistoryTextField(
      {super.key, required this.fieldType, required this.hintText});

  @override
  State<HistoryTextField> createState() => _HistoryTextFieldState();
}

class _HistoryTextFieldState extends State<HistoryTextField> {
  final TextEditingController _controller = TextEditingController();
  final List<String> _history = [];
  String? _selectedHistory;

  @override
  void initState() {
    super.initState();
    // Load history from storage
    _loadHistory();
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  Future<void> _loadHistory() async {
    // Load history from storage
    final preferences = await SharedPreferences.getInstance();

    setState(() {
      _history.addAll(preferences.getStringList(widget.fieldType) ?? []);

      if (_history.isNotEmpty) {
        _selectedHistory = _history.first;
        _controller.text = _selectedHistory!;
      }
    });
  }

  Future<void> _saveHistory() async {
    // Save history to storage
    final preferences = await SharedPreferences.getInstance();
    preferences.setStringList(widget.fieldType, _history);
  }

  void _addToHistory(String text) {
    if (text.isNotEmpty && !_history.contains(text)) {
      _history.insert(0, text);
      // Save history to storage
      _saveHistory();
    }
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: BoxDecoration(
        color: Theme.of(context).scaffoldBackgroundColor,
        border: Border.all(color: Theme.of(context).dividerColor),
        borderRadius: BorderRadius.circular(5),
      ),
      padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
      child: Row(
        children: [
          Expanded(
            child: TextField(
              cursorColor: Theme.of(context).dividerColor,
              decoration: InputDecoration(
                  border: InputBorder.none, hintText: widget.hintText),
              controller: _controller,
              onChanged: (value) {
                setState(() {
                  _selectedHistory = null;
                });
              },
              onSubmitted: (value) {
                _addToHistory(value);
              },
            ),
          ),
          SizedBox(
            width: 50,
            child: DropdownButtonHideUnderline(
              child: DropdownButton<String>(
                isExpanded: true,
                value: _selectedHistory,
                onChanged: (String? newValue) {
                  setState(() {
                    _selectedHistory = newValue;
                    _controller.text = newValue!;
                  });
                },
                selectedItemBuilder: (BuildContext context) {
                  return _history.map<Widget>((String value) {
                    return Container();
                  }).toList();
                },
                items: _history.map<DropdownMenuItem<String>>((String value) {
                  return DropdownMenuItem<String>(
                    value: value,
                    child: Text(
                      value,
                      textAlign: TextAlign.left,
                    ),
                  );
                }).toList(),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

and here is how I have it used:

class _IpSelection extends StatelessWidget {
  const _IpSelection();

  @override
  Widget build(BuildContext context) {
    return const Row(
      children: [
        Text("IP Адрес: ", style: TextStyle(fontWeight: FontWeight.bold)),

        SizedBox(width: 20),

        // IP Address text field
        SizedBox(
            width: 200,
            child: HistoryTextField(
              fieldType: "ipField",
              hintText: "Въведете IP адрес",
            ))
      ],
    );
  }
}

I have created a textfield, which has a dropdown button with the history of the textfield. What concerns me is that this field will be used to display IP address, which does not fit as I want in the history dropdown:

as you can see, the address is on two lines instead of one, which is as big as the textfield for example (200px in this case). I tried wrapping the DropdownMenuItem in a SizedBox and fixing its width to 200px for example but did not work.. Here is my Widget:

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';

class HistoryTextField extends StatefulWidget {
  final String fieldType;
  final String hintText;

  const HistoryTextField(
      {super.key, required this.fieldType, required this.hintText});

  @override
  State<HistoryTextField> createState() => _HistoryTextFieldState();
}

class _HistoryTextFieldState extends State<HistoryTextField> {
  final TextEditingController _controller = TextEditingController();
  final List<String> _history = [];
  String? _selectedHistory;

  @override
  void initState() {
    super.initState();
    // Load history from storage
    _loadHistory();
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  Future<void> _loadHistory() async {
    // Load history from storage
    final preferences = await SharedPreferences.getInstance();

    setState(() {
      _history.addAll(preferences.getStringList(widget.fieldType) ?? []);

      if (_history.isNotEmpty) {
        _selectedHistory = _history.first;
        _controller.text = _selectedHistory!;
      }
    });
  }

  Future<void> _saveHistory() async {
    // Save history to storage
    final preferences = await SharedPreferences.getInstance();
    preferences.setStringList(widget.fieldType, _history);
  }

  void _addToHistory(String text) {
    if (text.isNotEmpty && !_history.contains(text)) {
      _history.insert(0, text);
      // Save history to storage
      _saveHistory();
    }
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: BoxDecoration(
        color: Theme.of(context).scaffoldBackgroundColor,
        border: Border.all(color: Theme.of(context).dividerColor),
        borderRadius: BorderRadius.circular(5),
      ),
      padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
      child: Row(
        children: [
          Expanded(
            child: TextField(
              cursorColor: Theme.of(context).dividerColor,
              decoration: InputDecoration(
                  border: InputBorder.none, hintText: widget.hintText),
              controller: _controller,
              onChanged: (value) {
                setState(() {
                  _selectedHistory = null;
                });
              },
              onSubmitted: (value) {
                _addToHistory(value);
              },
            ),
          ),
          SizedBox(
            width: 50,
            child: DropdownButtonHideUnderline(
              child: DropdownButton<String>(
                isExpanded: true,
                value: _selectedHistory,
                onChanged: (String? newValue) {
                  setState(() {
                    _selectedHistory = newValue;
                    _controller.text = newValue!;
                  });
                },
                selectedItemBuilder: (BuildContext context) {
                  return _history.map<Widget>((String value) {
                    return Container();
                  }).toList();
                },
                items: _history.map<DropdownMenuItem<String>>((String value) {
                  return DropdownMenuItem<String>(
                    value: value,
                    child: Text(
                      value,
                      textAlign: TextAlign.left,
                    ),
                  );
                }).toList(),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

and here is how I have it used:

class _IpSelection extends StatelessWidget {
  const _IpSelection();

  @override
  Widget build(BuildContext context) {
    return const Row(
      children: [
        Text("IP Адрес: ", style: TextStyle(fontWeight: FontWeight.bold)),

        SizedBox(width: 20),

        // IP Address text field
        SizedBox(
            width: 200,
            child: HistoryTextField(
              fieldType: "ipField",
              hintText: "Въведете IP адрес",
            ))
      ],
    );
  }
}
Share Improve this question asked Jan 9 at 17:55 GeoGeo 2481 silver badge11 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 1

The reason why your content fit 2 strings inside dropdown, is that you explicitly wrap your DropdownButtonHideUnderline inside SizedBox with width: 50 (in your first code sample). That width controls your DropdownButton's width.

Also There is a menuWidth inside DropdownButton widget. Its documentation says:

If it is not provided, the width of the menu is the width of the button.

So you can provide menuWidth with desired size, or provide double.infinite to make it fill all available space.

转载请注明原文地址:http://anycun.com/QandA/1745782500a91223.html