본문 바로가기
Dart/Flutter

[Flutter] 탭바(Tabbar) 스크롤 위치 기억하기 `Render Visible`

by 검은냥냥이 2022. 12. 23.

플러터에서 탭바를 이용하다 보면, 다른 탭에 갔다가 오게 되면 스크롤 위치가 초기화되는 현상이 있습니다. 스크롤을 유지하기 위해서는 별도의 옵션을 주고 처리해야 합니다. 다만, 각 탭 이동시 렌더링은 이후 계속 유지하고 있습니다.

`StatefulWidget`에서 오버라이드(override)를 활용하여 `wantKeepAlive` 옵션을 `true` 값을 주면 됩니다.

 

예제

/// 탭바 위젯
class TabbarWidget extends GetView<TabbarController> {
  const TabbarWidget({super.key});

  @override
  Widget build(BuildContext context) {
    return Obx(
      () => TabBar(
        controller: controller.tabController.value,
        isScrollable: true,
        labelColor: Colors.red,
        unselectedLabelColor: Colors.grey.shade800,
        labelPadding: const EdgeInsets.symmetric(horizontal: 15),
        indicatorPadding: const EdgeInsets.only(
          left: 10,
          right: 10,
        ),
        indicator: UnderlineTabIndicator(
          borderSide: BorderSide(
            width: 3.w,
            color: Colors.red,
          ),
        ),
        labelStyle: TextStyle(
          fontSize: 14.sp,
        ),
        onTap: (value) {
          // 탭바 인덱스 변경
        },
        tabs: List.generate(
          controller.tabMenuData.length,
          (index) => SizedBox(
            height: 42.w,
            child: Tab(
              text: controller.tabMenuData[index].gnbName,
            ),
          ),
        ),
      ),
    );
  }
}

/// 레이아웃 위젯
class LayoutWidget extends StatefulWidget {
  const TabbarWidget({
    super.key,
    required this.index,
  });

  final int index;

  @override
  State<LayoutWidget> createState() => _LayoutWidgetState();
}

class _LayoutWidgetState extends State<LayoutWidget>
    with AutomaticKeepAliveClientMixin {
  @override
  bool get wantKeepAlive => true;

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: MediaQuery.of(context).size.width,
      child: ContentWidget(index: widget.index),
    );
  }
}

/// 컨텐츠 위젯
class ContentWidget extends GetView<TabbarController> {
  const ContentWidget({
    super.key,
    required this.index,
  });

  final int index;

  @override
  Widget build(BuildContext context) {
    return Obx(
      () => ListView.builder(
        controller: controller.scrollController[index],
        physics: const AlwaysScrollableScrollPhysics(),
        itemCount: controller.data[index].length,
        itemBuilder: (context, doubleIndex) {
          return Column(
            mainAxisSize: MainAxisSize.min,
            crossAxisAlignment: CrossAxisAlignment.start,
            children: List.generate(
              controller.data[index].item[doubleIndex].length,
              (templateIndex) {
                /// 위젯 결과 리턴
              },
            ),
          );
        },
      ),
    );
  }
}
728x90
사업자 정보 표시
레플라 | 홍대기 | 경기도 부천시 부일로 519 화신오피스텔 1404호 | 사업자 등록번호 : 726-04-01977 | TEL : 070-8800-6071 | Mail : support@reafla.co.kr | 통신판매신고번호 : 호 | 사이버몰의 이용약관 바로가기