[Flutter] TabBarView 페이징을 따라 애니메이팅 되는 Widget 만들기

이상화(와상)·2022년 4월 1일
2

짧은 기록

목록 보기
2/12
post-thumbnail

TabBarViewTabController를 활용하여 탭 인덱스에 따라 페이드되는 위젯을 구현할 수 있다.

  • TabController.animation : 탭 이동에 따라 변화가 발생하는 listener로, 이것을 listen하여 AnimatedBuilder를 만들면 탭 이동에 따라 변화하는 위젯을 작성할 수 있다.

  • TabController.indexIsChanging : TabBarView의 index가 변화 중일 때, 변화가 스와이프로 이루어졌는지, TabBar 조작이나 animateTo 등의 메소드로 변화했는 지를 체크할 수 있다.
    인덱스가 2 이상 변화했을 때, 전체 변화가 liner하게 적용되는 PageView와 달리 TabBarView는 변화가 1 이상인 경우 중간 페이지를 스킵하게 되기 때문에, 페이지 이동을 직접 참조하는 경우 이 변수의 사용이 중요해진다.

  • TabController.previousIndex : TabController.indexIsChangingtrue인 경우, 이 값을 사용해 변화가 시작된 시점의 탭 인덱스를 구할 수 있다. 현재 진행 목표 인덱스인 TabController.index와 함께 사용해서 교차 등을 구현할 수 있다.

  • TabController.offset : 탭이 변화 중일 때 현재 중간 인덱스의 상대 값을 나타낸다. 때문에 인덱스 2 이상 이동하여 중간 탭이 스킵되더라도 liner한 값으로 offset이 표기된다.

위 기능을 활용하여 페이지 변화에 따라 Fade되는 위젯을 구현한 샘플이다.

 Widget _buildFadeWidgetByTabIndex(TabController tabController) {
    return AnimatedBuilder(
    	//animation을 참조해야 중간 인덱스 변화를 참조할 수 있다.
        animation: tabController.animation!,
        builder: (_, __) {
          int previousIndex;
          double progress; //현재 이동 진행 상태를 0-1 값으로 연산

		  //탭이 TabBar 조작 등으로 변경되고 있는 경우
          if (tabController.indexIsChanging) {
            previousIndex = tabController.previousIndex;
            var distance = tabController.previousIndex - tabController.index;
            progress = 1 - tabController.offset / distance;
          } else {
          	//스와이프 등으로 좌우 이동하는 경우, offset의 음수 양수 여부를 통해 이동 예정 위치를 구한다
            var offset = tabController.offset;
            previousIndex =
                max((tabController.index + (offset < 0 ? -1 : 1)), 0);
            progress = 1 - offset.abs();
          }

          return Stack(
            children: [
              _buildSomeWidgetByTabIndex(previousIndex),
              Opacity(
              	//progress값을 투명도에 적용, Fade모션을 구현한다
                opacity: progress,
                child: _buildSomeWidgetByTabIndex(tabController.index),
              ),
            ],
          );
        });
  }
profile
크로스플랫폼 클라이언트 개발자(Flutter, Unity), 5년차

0개의 댓글