import 'package:flutter/material.dart'; import 'package:syncrow_web/utils/color_manager.dart'; class DialogTextfieldDropdown extends StatefulWidget { final List items; final ValueChanged onSelected; final String? initialValue; const DialogTextfieldDropdown({ Key? key, required this.items, required this.onSelected, this.initialValue, }) : super(key: key); @override _DialogTextfieldDropdownState createState() => _DialogTextfieldDropdownState(); } class _DialogTextfieldDropdownState extends State { bool _isOpen = false; OverlayEntry? _overlayEntry; final TextEditingController _controller = TextEditingController(); final FocusNode _focusNode = FocusNode(); List _filteredItems = []; @override void initState() { super.initState(); _controller.text = widget.initialValue ?? ''; _filteredItems = List.from(widget.items); _focusNode.addListener(() { if (!_focusNode.hasFocus) { _closeDropdown(); } }); } void _toggleDropdown() { if (_isOpen) { _closeDropdown(); } else { _openDropdown(); } } void _openDropdown() { _overlayEntry = _createOverlayEntry(); Overlay.of(context).insert(_overlayEntry!); _isOpen = true; } void _closeDropdown() { if (_isOpen && _overlayEntry != null) { _overlayEntry!.remove(); _overlayEntry = null; _isOpen = false; } } OverlayEntry _createOverlayEntry() { final renderBox = context.findRenderObject() as RenderBox; final size = renderBox.size; final offset = renderBox.localToGlobal(Offset.zero); return OverlayEntry( builder: (context) { return GestureDetector( onTap: _closeDropdown, behavior: HitTestBehavior.translucent, child: Stack( children: [ Positioned( left: offset.dx, top: offset.dy + size.height, width: size.width, child: Material( elevation: 4.0, child: Container( color: ColorsManager.whiteColors, constraints: const BoxConstraints(maxHeight: 200.0), child: StatefulBuilder( builder: (context, setStateDropdown) { return ListView.builder( shrinkWrap: true, itemCount: _filteredItems.length, itemBuilder: (context, index) { final item = _filteredItems[index]; return ListTile( title: Text(item, style: Theme.of(context) .textTheme .bodyMedium ?.copyWith( color: ColorsManager.textPrimaryColor)), onTap: () { _controller.text = item; widget.onSelected(item); _closeDropdown(); }, ); }, ); }, ), ), ), ), ], ), ); }, ); } @override Widget build(BuildContext context) { return GestureDetector( onTap: () => FocusScope.of(context).unfocus(), behavior: HitTestBehavior.opaque, child: Container( padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 8.0), decoration: BoxDecoration( border: Border.all(color: ColorsManager.transparentColor), borderRadius: BorderRadius.circular(8.0), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( child: TextFormField( controller: _controller, focusNode: _focusNode, onFieldSubmitted: (value) { widget.onSelected(value); _closeDropdown(); }, onTapOutside: (event) { widget.onSelected(_controller.text); _closeDropdown(); }, style: Theme.of(context).textTheme.bodyMedium, decoration: const InputDecoration( hintText: 'Enter or Select a tag', border: InputBorder.none, ), ), ), GestureDetector( onTap: _toggleDropdown, child: const Icon(Icons.arrow_drop_down), ), ], ), ), ); } }