반응형
방법을 찾아보다가 결론은 직접 만들어서 써야 한다.
아이디어는 다음과 같다.
- 스크롤 컨트롤러의 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,
);
}))
반응형
'Flutter' 카테고리의 다른 글
iOS에서 상하단에 색이 생길 때 해결방법 (0) | 2024.02.03 |
---|---|
PageRouteBuilder에서 iOS backSwipe가 안될 때 (0) | 2024.02.03 |
Flutter와 파이어베이스로 게시판 만들때 부딪힌 경험들 (3) | 2024.01.25 |
Delay가 있는 TweenAnimationBuilder (0) | 2024.01.05 |
AnimatedSwitcher가 동작하지 않을 때 해결방법 (1) | 2024.01.03 |
댓글