import 'package:flutter/material.dart'; class ExpandableWidget extends StatefulWidget { const ExpandableWidget({ super.key, required this.child, required this.dragWidget, this.initHeight, this.maxHeight, this.minHeight, this.onScrollChange, this.dragWidgetOffset, this.dragWidgetPadding = const EdgeInsets.all(8), }); final Widget child; final Widget dragWidget; final double? initHeight; final double? maxHeight; final double? minHeight; final Offset? dragWidgetOffset; final EdgeInsets? dragWidgetPadding; final Function(bool isScrolling)? onScrollChange; @override ExpandableWidgetState createState() => ExpandableWidgetState(); } class ExpandableWidgetState extends State { double _currentHeight = 0, _maxHeight = 0, _minHeight = 0; @override void initState() { _minHeight = widget.minHeight ?? 100; // default min height as needed _currentHeight = widget.initHeight ?? _minHeight; _maxHeight = widget.maxHeight ?? double.infinity; super.initState(); } @override Widget build(BuildContext context) { return Stack( children: [ SizedBox(height: _currentHeight, child: widget.child), Positioned( bottom: 0 + (widget.dragWidgetOffset?.dy ?? 0), right: 0 + (widget.dragWidgetOffset?.dx ?? 0), child: Listener( onPointerUp: (event) => widget.onScrollChange?.call(false), onPointerDown: (event) => widget.onScrollChange?.call(true), onPointerMove: (event) { _currentHeight += event.delta.dy; setState(() { _currentHeight = _currentHeight.clamp(_minHeight, _maxHeight); }); }, child: Container( padding: widget.dragWidgetPadding, child: widget.dragWidget, ), ), ), ], ); } }