diff --git a/packages/core/lib/presentation/widget/overlay_dropdown_widget/view.dart b/packages/core/lib/presentation/widget/overlay_dropdown_widget/view.dart new file mode 100644 index 0000000..8d8496d --- /dev/null +++ b/packages/core/lib/presentation/widget/overlay_dropdown_widget/view.dart @@ -0,0 +1,143 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:rasadyar_core/presentation/common/app_color.dart'; +import 'package:rasadyar_core/presentation/common/app_fonts.dart'; + + + +class OverlayDropdownWidget extends StatefulWidget { + final List items; + final T? selectedItem; + final T? initialValue; + final Widget Function(T item) itemBuilder; + final Widget Function(T? selected) labelBuilder; + final void Function(T selected)? onChanged; + final EdgeInsets? contentPadding; + + const OverlayDropdownWidget({ + super.key, + required this.items, + required this.itemBuilder, + required this.labelBuilder, + this.initialValue, + this.onChanged, + this.selectedItem, + this.contentPadding + }); + + @override + State> createState() => _OverlayDropdownState(); +} + +class _OverlayDropdownState extends State> { + final GlobalKey _key = GlobalKey(); + OverlayEntry? _overlayEntry; + final RxBool _isOpen = false.obs; + T? selectedItem ; + + @override + void initState() { + super.initState(); + selectedItem = widget.selectedItem ?? widget.initialValue; + } + + void _showOverlay() { + final renderBox = _key.currentContext!.findRenderObject() as RenderBox; + final size = renderBox.size; + final offset = renderBox.localToGlobal(Offset.zero); + + _overlayEntry = OverlayEntry( + builder: + (_) => GestureDetector( + onTap: _removeOverlay, + behavior: HitTestBehavior.translucent, + child: Stack( + children: [ + Positioned( + left: offset.dx, + top: offset.dy + size.height + 4, + width: size.width, + child: Material( + elevation: 4, + borderRadius: BorderRadius.circular(8), + child: Container( + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: AppColor.darkGreyLight), + borderRadius: BorderRadius.circular(8), + ), + child: ListView( + padding: EdgeInsets.zero, + shrinkWrap: true, + children: + widget.items.map((item) { + return InkWell( + onTap: () { + widget.onChanged?.call(item); + setState(() { + selectedItem = item; + }); + _removeOverlay(); + }, + child: Padding( + padding:widget.contentPadding?? const EdgeInsets.symmetric(horizontal: 8, vertical: 4), + child: widget.itemBuilder(item), + ), + ); + }).toList(), + ), + ), + ), + ), + ], + ), + ), + ); + + Overlay.of(context).insert(_overlayEntry!); + _isOpen.value = true; + } + + void _removeOverlay() { + _overlayEntry?.remove(); + _overlayEntry = null; + _isOpen.value = false; + } + + @override + void dispose() { + _removeOverlay(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return GestureDetector( + key: _key, + onTap: () { + _isOpen.value ? _removeOverlay() : _showOverlay(); + }, + child: Container( + height: 40, + width: Get.width, + padding: const EdgeInsets.symmetric(horizontal: 12), + decoration: BoxDecoration( + border: Border.all(color: AppColor.darkGreyLight), + borderRadius: BorderRadius.circular(8), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + widget.labelBuilder(selectedItem), + Icon( + _isOpen.value + ? CupertinoIcons.chevron_up + : CupertinoIcons.chevron_down, + ), + ], + ), + ), + ); + } +}