seong

Flutter - BottomNav 더블 탭시 화면의 스크롤 가장 위로 보내기 본문

Flutter/Flutter

Flutter - BottomNav 더블 탭시 화면의 스크롤 가장 위로 보내기

hyeonseong 2024. 8. 9. 17:27

전제 조건

- BottomNav의 총 index는 4개 

 

BottomNav의 index가 총 4개, 관리 해야할 scroll이 4개이므로 ScrollController을 List로 선언 

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

final scrollControllersProvider =
    StateNotifierProvider<ScrollControllerNotifier, List<ScrollController>>(
        (ref) {
  return ScrollControllerNotifier();
});

class ScrollControllerNotifier extends StateNotifier<List<ScrollController>> {
  ScrollControllerNotifier()
      : super(List.generate(4, (_) => ScrollController()));

// 화면의 가장 위로 스크롤
  void resetScrollPosition(int index) {
    if (index < state.length) {
      state[index].animateTo(0,
          duration: const Duration(milliseconds: 300), curve: Curves.easeOut);
    }
  }

}

 

 

각 스크롤이 필요한 화면에 scroll의 상태 값을 watch

SingleChildScrollView의 controller에 추가

 @override
  Widget build(BuildContext context) {
    final scrollController = ref.watch(scrollControllersProvider)[2];
   
    return Scaffold(
      body: RefreshIndicator(
        onRefresh: () async {
          vm.init();
        },
        SingleChildScrollView(
        // controller 추가
          controller: scrollController,
          ...
          )

 

BottomNav의 onTap함수

index를 변경 할때 현재 내가 있는 index == value값이 동일 하다면 scroll 함수 동작

          bottomNavigationBar: SizedBox(
            child: Theme(
              data: Theme.of(context).copyWith(
                  canvasColor: Colors.white,
                  primaryColor: IhpColors.gray50,
                  textTheme: Theme.of(context).textTheme.copyWith(
                      bodySmall: const TextStyle(color: Colors.yellow))),
              child: BottomNavigationBar(
                type: BottomNavigationBarType.fixed,
                currentIndex: vm.selectedIndex,
                selectedFontSize: 15,
                unselectedFontSize: 15,
                onTap: (value) {
                  switch (value) {
                    case 0:
                      vm.changeIndex(value);
                      break;
                    case 1:
                      vm.changeIndex(value,
                          context: context, localization: localization);
                      break;
                    case 2:
                      if (vm.selectedIndex == 2) {
                        ref
                            .read(scrollControllersProvider.notifier)
                            .resetScrollPosition(2);
                      }
                      vm.changeIndex(value);
                      ReportViewModel().scrollToStep(false);
                      break;
                    case 3:
                      if (vm.selectedIndex == 3) {
                        ref
                            .read(scrollControllersProvider.notifier)
                            .resetScrollPosition(3);
                      }
                      vm.changeIndex(value);
                      break;
                  }
                },
                items: [
                  setBarItem(ImgRes.pill, localization.record),
                  setWatchBarItem(),
                  setBarItem(ImgRes.report, localization.report),
                  setBarItem(ImgRes.profile, localization.profile),
                ],
              ),
            ),
          )