본문 바로가기

개발/Flutter

Flutter Tab layout (TabBar, TabBarView, TabController)

반응형

Flutter에서 tab 레이아웃을 만드는 방법에 대해서 알아보자

 


우선 flutter에서 tab의 기본구조에 대해서 알아보자면

tab layout을 만들기 위해서는 TabBar, TabBarView, TabController 이렇게 3개의 위젯이 필요하다.

TabBar는 상단 tab

TabBarView는 tab의 인덱스에 따라 바뀌어야 하는 View 이고

TabController는 이 둘을 연결해 주는 역할을 하는 연결자라고 보면 이해하기 쉽다.

 


우선 가장 기본적으로 사용하는 방법에 대해서 알아보자.

다음 애니메이션은 flutter.dev에서 제공하는 기본 코드를 실행한 결과 이다.

 

 

 

위 동작을 가능하게 해주는 코드 이다.

import 'package:flutter/material.dart';

void main() {
  runApp(const TabBarDemo());
}

class TabBarDemo extends StatelessWidget {
  const TabBarDemo({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
            //tabbar와 tabbarView를 연결해 주는 controller 
      home: DefaultTabController(
        length: 3, // tab의 갯수 
        child: Scaffold(
          appBar: AppBar(
            // tab
            bottom: const TabBar(
              tabs: [
                Tab(icon: Icon(Icons.directions_car)),
                Tab(icon: Icon(Icons.directions_transit)),
                Tab(icon: Icon(Icons.directions_bike)),
              ],
            ),
            title: const Text('Tabs Demo'),
          ),
            // tab과 연결되어 보여주는 view 
          body: const TabBarView(
            children: [
              Icon(Icons.directions_car),
              Icon(Icons.directions_transit),
              Icon(Icons.directions_bike),
            ],
          ),
        ),
      ),
    );
  }
}

 

 


 

 

TabBar와 TabBarView, TabController의 관계를 이용하면 다음과 같이 TabBar를 바닥에 두는 것도 가능하다.

 

 

 

변경한 소스 코드를 참고해 보자.

import 'package:flutter/material.dart';

void main() {
  runApp(const TabBarDemo());
}

class TabBarDemo extends StatelessWidget {
  const TabBarDemo({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: DefaultTabController(
        length: 3,
        child: Scaffold(
          body: Column(
            children: [
              const Expanded(
                child: TabBarView(
                  children: [
                    Icon(Icons.directions_car),
                    Icon(Icons.directions_transit),
                    Icon(Icons.directions_bike),
                  ],
                ),
              ),
              SizedBox(
                height: 80,
                child: Container(
                  color: Colors.green,
                  child: const TabBar(
                    tabs: [
                      Tab(icon: Icon(Icons.directions_car)),
                      Tab(icon: Icon(Icons.directions_transit)),
                      Tab(icon: Icon(Icons.directions_bike)),
                    ],
                  ),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

 

 

조금 더 분리해서 3 위젯간의 관계에 대해서 좀 더 알아보자

위 예제에서는 DefaultTabController를 중심으로 안에 TabBar와 TabBarView를 구성하고 있는데 이를 분리할 수 있다. 다음 예제를 잘 살펴 보자

 

 

DefaultTabController로 감싸는 대신 TabController를 이용하여 TabBar와 TabBarView를 연결해 줬다.

TabBar와 TabBarView의 위치가 더욱더 자유로워 질수 있겠다는 생각이 저절로 들지 않는가??

TabController를 이용해서 좀 더 자유롭게 Tab Layout을 구현해 보자.

 

 

 

import 'package:flutter/material.dart';

void main() {
  runApp(const TabBarDemoStf());
}

class TabBarDemoStf extends StatefulWidget {
  const TabBarDemoStf({Key? key}) : super(key: key);
  @override
  State<TabBarDemoStf> createState() => _TabBarDemoStfState();
}

class _TabBarDemoStfState extends State<TabBarDemoStf>
    with TickerProviderStateMixin {
  late TabController _tabbarController;

  @override
  void initState() {
    super.initState();
    _tabbarController = TabController(length: 3, vsync: this);
  }

  @override
  void dispose() {
    _tabbarController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: Column(children: [
          Container(
            color: Colors.green,
            child: TabBar(
              controller: _tabbarController,
              tabs: [
                Tab(icon: Icon(Icons.directions_car)),
                Tab(icon: Icon(Icons.directions_transit)),
                Tab(icon: Icon(Icons.directions_bike)),
              ],
            ),
          ),

                    Center(child: Text('I\'m Middle'),),

                    Expanded(
            child: TabBarView(
              controller: _tabbarController,
              children: [
                Icon(Icons.directions_car),
                Icon(Icons.directions_transit),
                Icon(Icons.directions_bike),
              ],
            ),
          ),
        ],),
      ),
    );
  }
}

 

 


 

tab의 구성을 이해하면 나누고 합치기가 쉬워진다. 그리고 싶은 대로 그릴수 있다. 얼마나 아름다운가~ :)

반응형