Pull to refresh without packages and able to custom loader

53 Views Asked by At

I'm trying to build my own pull to refresh w/o packages. But its very hard for me explain the requirements because I dont have any idea what this design called.

this is what I want to achieve

While the data still refreshing, user scroll down. The loader still loads but it just hidden away at the top.

Currently, the position always stuck on top of the page, while scroll down.

enter image description here

please help me with this one


class RefreshWidget extends StatefulWidget {
  final Function onRefresh;
  final Widget? child;

  RefreshWidget({required this.onRefresh, required this.child});

  @override
  _RefreshWidgetState createState() => _RefreshWidgetState();
}

class _RefreshWidgetState extends State<RefreshWidget> {
  bool _isRefreshing = false;
  bool _isScrolling = false;
  double _dragOffset = 0;

  Future<void> _handleRefresh() async {
    setState(() {
      _isRefreshing = true;
    });
    try {
      await Future.delayed(Duration(seconds: 10)); // Simulating a delay
      await widget.onRefresh();
    } catch (e) {
      print('Error during refresh: $e');
    } finally {
      if (mounted) {
        setState(() {
          _isRefreshing = false;
          _dragOffset = 0;
        });
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return NotificationListener<ScrollNotification>(
      onNotification: (scrollNotification) {
        if (scrollNotification is ScrollStartNotification &&
            scrollNotification.metrics.extentBefore == 0) {
          // Detects the start of a scroll at the top
          setState(() {
            _isScrolling = true;
          });
          return true;
        } else if (scrollNotification is ScrollUpdateNotification &&
            scrollNotification.metrics.extentBefore == 0 &&
            !_isRefreshing &&
            scrollNotification.dragDetails != null &&
            scrollNotification.dragDetails!.delta.dy > 0) {
          // Detects the downward scroll movement at the top
          _handleRefresh();
          return true;
        } else if (scrollNotification is ScrollEndNotification) {
          setState(() {
            _isScrolling = false;
          });
        }
        return false;
      },
      child: Stack(
        children: [
          Transform.translate(
            offset: Offset(0, _isRefreshing ? 110.0 : 0), // Offset the content if refreshing
            child: widget.child,
          ),
          if (_isRefreshing && !_isScrolling)
            Positioned(
              top: 50,
              left: 0,
              right: 0,
              child: Align(
                alignment: Alignment.topCenter,
                child: Container(
                  color: Colors.transparent,
                  child: CircularProgressIndicator(),
                ),
              ),
            ),
        ],
      ),
    );
  }
}

this is what is inside in widget.child

      body: Container(
        child: Stack(
          children: [
            SingleChildScrollView(...
0

There are 0 best solutions below