Flutter/UI Widget

[Flutter] BottomNavigationBar & TabBarView (+ TickerProviderStateMixin)

개발자킹콩 2023. 4. 10. 17:48

목차

  • TabBarView & BottomNavigationBar 위젯 소개
  • Sample Code(TabController)
  • TickerProvideMixin(애니메이션 효율) & vsync(수직동기화)

 

 

 


 

 

1. TabBarView & BottomNavigationBar 위젯 소개

 

Flutter 에서 TabBarView는 아래와 같은 Widget을 의미합니다.

 

 

TabBarView와 BottomNavigationBar를 연결하면 아래와 같이 시중에 가장 많이 사용되는 형태의 앱을 만들 수 있습니다.

 

 

 

 


 

 

 

2. Sample Code

 

일반적으로 보이지 않는 이해 안 되는 키워드가 존재할 것입니다. 

'TickerProviderStateMixin'와 'vsync' 는 아래에서 따로 설명 하겠습니다.

 

TabBarView와 BottomNavigationBar 를 연결하는 템플릿이라 생각하고 원리가 이해되면 암기하면 됩니다.

1) 우선 TabBarView를 관리하기 위해서는 TabController를 사용해야 합니다.

 

2) TabController 과 더불어 Controller를 제어자이고 이는 한번만 생성되야 하므로 StatefulWidget을 사용합니다.

 

3) 생성 시 단 한번만 실행되는 initState()에 TabController를 생성합니다.  length에는 탭의 갯수를 int형으로 넣습니다. vsync에는 TickerProviderStateMixin이 추가된 State 클래스 자체인 this를 넣어줍니다.

 

4) TabBarView와 BottomNavigationBar는 다른 위젯이며 우리가 인위적으로 묶어주는 형태입니다. TabBarView는 스와이프로 화면전환이 가능합니다. 그럼 화면 전환 시 BottomNavigationBar도 이동을 해야겠죠. 그래서 어떤 이벤트가 발생하면 다시 build() 함수를 실행하도록 Listener를 controller에 등록합니다. 그리고 BottomNavigationBar의 currentIndex를 TabController의 index가 되도록 강제했습니다.

 

5) 중급 개발자의 필수 항목 중 하나는 메모리 관리 입니다. 생성한 메모리나 열어준 Stream이 있다면 객체가 소멸할 때 모두 제거해주어야 합니다. 그렇지 않으면 사용되지 않는 리소스가 계속 위치하고 자리잡아 있습니다. 물론 최근 언어에서는 Garbage Collection 과 같은 자동 메모리 관리하는 기능이 탑재되어 있지만 모든 것을 관리할 수는 없습니다. 생성과 소멸, 열기와 닫기는 기본중의 기본입니다.

 

 

import 'package:flutter/material.dart';

class TabBarTestScreen extends StatefulWidget {
  const TabBarTestScreen({Key? key}) : super(key: key);

  @override
  State<TabBarTestScreen> createState() => _TabBarTestScreenState();
}

class _TabBarTestScreenState extends State<TabBarTestScreen>
    with TickerProviderStateMixin {
  TabController? controller;

  @override
  void initState() {
    super.initState();

    controller = TabController(length: 2, vsync: this);
    controller?.addListener(tabListener);
  }

  @override
  void dispose() {
    controller?.removeListener(tabListener);

    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      bottomNavigationBar: renderBottomNavigationBar(),
      body: TabBarView(
        controller: controller,
        children: renderChildren(),
      ),
    );
  }

  void tabListener() {
    setState(() {});
  }

  BottomNavigationBar renderBottomNavigationBar() {
    return BottomNavigationBar(
      currentIndex: controller!.index,
      items: const [
        BottomNavigationBarItem(
          icon: Icon(Icons.phonelink_ring_sharp),
          label: '주사위',
        ),
        BottomNavigationBarItem(
          icon: Icon(Icons.settings),
          label: '설정',
        ),
      ],
      onTap: (int index) {
        controller?.animateTo(index);
      },
    );
  }

  List<Widget> renderChildren() {
    return const [
      Center(
        child: Text("주사위 페이지"),
      ),
      Center(
        child: Text("설정 페이지"),
      )
    ];
  }
}

 

 

 


 

 

 

3. TickerProviderMixin(애니메이션 효율) & vsync(수직동기화)

 

TabController를 초기화하려면 vsync 기능이 필요합니다. 이것은 State 위젯에 TickerProviderMixin을 mixin으로 제공해줘야 사용할 수 있습니다. TickerProviderMixin과 SingleTickerProviderMixin은 애니메이션의 효율을 올려주는 역할을 합니다. TabController에는 탭 개수를 int 값으로 제공합니다. vsync에는 TickerProviderMixin을 사용하는 State 클래스를 this 형태로 넣어주면 됩니다.

 

 


 

 

vsync(수직 동기화)

우선 vsync는 수직 동기화를 의미합니다. 그래픽카드(어플리케이션, 게임 등)의 프레임과 디스플레이(스마트폰, 게임 등)의 주사율을 일치시켜주는 기능을 합니다. vsync 가 실행되어 있지 않으면, 이 두가지가 성능이 달라 동기화되지 않으면 화면 위와 아래의 형태가 달라 테어링이라는 화면 찟어짐이 발생합니다. 애니메이션이 들어가는 경우 특별한 경우가 아니면 사용하는 것이 좋습니다. 조금 더 자세하게 알고 싶다면 아래의 링크에 정리를 해두었습니다.

 

https://yeongwoo-cho.tistory.com/entry/VSync-수직동기화란

 

VSync 수직동기화란?

VSync 수직동기화란 애플리케이션의 초당 프레임을 디스플레이의 주사율을 동기화 시켜주는 것입니다. 단어 설명 애플리케이션 여기서는 게임이나 애니메이션이 있는 스마트폰 어플을 말합니다

yeongwoo-cho.tistory.com

 

 

 

Flutter에서 TickerProviderStateMixin과 vsync란?

Ticker(똑딱똑딱 소리내는 것, 혹은 체크하는 사람) Provider(공급자) Mixin(전투, 싸움, 분쟁): 애니메이션 효율성을 부여하는 놈

 

플러터는 60 ~ 120FPS(초당 프레임)를 지원합니다. 스마트폰의 주사율은 보통 60Hz, 120Hz 입니다. (아이폰14와 아이폰 14Pro 기준) 즉, 이를 통일시켜 주지 않으면 테어링(화면 찢어짐)이 발생하거나 자원의 비효율이 발생합니다.

 

TickerProviderMixin을 사용하면 정확히 한 틱(1FPS)마다 애니메이션을 실행합니다. TickerProviderstateMixin를 사용하지 않고 간혹 애니메이션 코드를 작성하다 보면, 실제로 화면에 그릴 수 있는 주기보다 더 자주 렌더링을 실행하게 될 때가 있습니다. 리소스 낭비, 비효율이 발생하는 것입니다. TickerProviderMixin을 사용하면 이런 비효율적인 상황을 막아줍니다. 그래서 TabController vsync에 TickerProviderStateMixin를 제공함으로써 애니메이션 렌더링에 효율성을 부여합니다.

 

 

 

 

 

 


 

 

 

Reference

 

https://medium.com/flutter-community/flutter-widgets-tabbar-tabbarview-the-whole-picture-dad81c952544

 

Flutter Widgets (TabBar & TabBarView) The Whole Picture

TabBar Flutter widget and TabBar View Flutter widget is a convenient way to create Tab layout in Flutter. Read in detail on how to create…

medium.com

 

https://api.flutter.dev/flutter/material/BottomNavigationBar-class.html

 

BottomNavigationBar class - material library - Dart API

A material widget that's displayed at the bottom of an app for selecting among a small number of views, typically between three and five. The bottom navigation bar consists of multiple items in the form of text labels, icons, or both, laid out on top of a

api.flutter.dev

 

https://link.coupang.com/a/UB3Sk

 

Must Have 코드팩토리의 플러터 프로그래밍:Dart & Flutter 입문부터 실전에 유용한 10가지 앱 개발과

COUPANG

www.coupang.com

"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."