본문 바로가기
Flutter

Bottom에서 Pull to refresh하기

by 붕어사랑 티스토리 2024. 1. 31.
반응형

방법을 찾아보다가 결론은 직접 만들어서 써야 한다.

 

 

아이디어는 다음과 같다.

 

 

  • 스크롤 컨트롤러의 position값을 추적해 offset을 구한다
  • offset을 0에서 1.1 사이로 nomarlize한다
  • refresh indicator를 partially하게 0.1단위 간격으로 값을 보내어 위젯을 다시 그리도록 한다
  • 1.1이 될 경우 데이터를 불러오고 refresh indicaotr를 full로 그린다.

 

대충 코드로 설명하는게 편할듯

 

 

 

먼저 일단 나의 위젯이 사이즈가 너무 커져서 그냥 setState할경우 디버그모드에서 버벅이는게 보였다. 고로 하위 위젯만 rebuild 될 수 있도록 StreamController와 StreamBuilder를 활용하기로 하였다.

double _bounceProgress = 0.0;
bool _fetchMoreComment = false;
late StreamController<double> _progressStream;
 
 
 @override
  void initState() {
    // TODO: implement initState
    super.initState();
    
    _progressStream = StreamController();
    
    _scrollController.addListener(() {
      if (_scrollController.position.pixels -
              _scrollController.position.maxScrollExtent >=
          0) {
        var accelerate = 1.1;

        var offset = _scrollController.position.pixels - _scrollController.position.maxScrollExtent;
        var val = ((offset * accelerate) / 10).floor() / 10;

        if (val <= 1 && _bounceProgress != val) {
          _bounceProgress = val;
          if(val == 0){
            setState(() {
              _fetchMoreComment = false;
            });
          }
          _progressStream.add(_bounceProgress);
        } else if (val >= 1.1 && !_fetchMoreComment) {
          setState(() {
            _fetchMoreComment = true;
          });
          HapticFeedback.vibrate();
          refreshData();
        }
      }
    });
  }

 

 

 

 

아래는 실제 위젯트리에서 refresh indicator를 나타내는 내용

 

if (_fetchMoreComment)
  SliverToBoxAdapter(
      child: StreamBuilder<double>(
        stream: _progressStream.stream,
        builder: (context, snapshot) {
          double r = 15 * (snapshot.data ?? 0);
          if(r == 0) r= 0.01;
          return CupertinoActivityIndicator(radius: r);
        }
      ))
else
  SliverToBoxAdapter(
      child: StreamBuilder<double>(
          stream: _progressStream.stream,
          builder: (context, snapshot) {
            return CupertinoActivityIndicator
                .partiallyRevealed(
              progress: snapshot.data ?? 0.0,
              radius: 15,
            );
          }))
반응형

댓글