bottom navigation tab 만들기

2022. 1. 10. 11:49Flutter

반응형

앱 화면 하단에 나올 네비게이션 바를 만드는 방법에 대해 알아보자

강의에서 들은 방법 말고도 다른 방법이 있어 기록한다

 

일단 앱을 위한 기본설정을 하자

 

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp();
  }
}

네비게이션바는 동적으로 화면이 변하기 때문에 Stateful Widget을 사용한다

 

1. DefaultTabController 사용하기

 

강의에서 나온 방법이다.

DefaultTabController의 child로 Scaffold가 있고

Scaffold의 body에 TabBarView, Scaffold의 bottomNavigationBar에 TabBar를 준다.

TabBar에는 tabs가 있고 그 아래 각각의 Tab이 들어간다.

 

class _MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Navigation',
      theme: ThemeData(
        brightness: Brightness.dark,
        primaryColor: Colors.black,
      ),
      home: DefaultTabController(
        length: 4, 
        child: Scaffold(
          body: TabBarView(
            physics:
                NeverScrollableScrollPhysics(), 
            children: [
              Container(
                child: Center(
                  child: Text("Home"),
                ),
              ),
              Container(
                child: Center(
                  child: Text("Search"),
                ),
              ),
              Container(
                child: Center(
                  child: Text("save"),
                ),
              ),
              Container(
                child: Center(
                  child: Text("more"),
                ),
              ),
            ],
          ),
          bottomNavigationBar: Bottom(),
        ),
      ),
    );
  }
}

 

DefaultTabController는 TabBar와 TabBarView를 연결해준다. length는 탭의 수.

TabBarView는 탭이 선택될 때 보여줄 컨텐트로, body에 작성한다.

NeverScrollableScrollPhysics는 사용자가 직접 손가락 모션을 통해 스크롤하는 것을 막아준다. 즉 손가락 움직임으로 탭을 전환할 수 없게 된다.

 

class Bottom extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.black,
      child: Container(
        height: 50,
        child: TabBar(
          labelColor: Colors.white,
          unselectedLabelColor: Colors.white60,
          indicatorColor: Colors.transparent,
          tabs: [
            Tab(
              icon: Icon(
                Icons.home,
                size: 18,
              ),
              child: Text(
                "홈",
                style: TextStyle(fontSize: 9),
              ),
            ),
            Tab(
              icon: Icon(
                Icons.search,
                size: 18,
              ),
              child: Text(
                "검색",
                style: TextStyle(fontSize: 9),
              ),
            ),
            Tab(
              icon: Icon(
                Icons.save_alt,
                size: 18,
              ),
              child: Text(
                "저장한 콘텐츠 목록",
                style: TextStyle(fontSize: 9),
              ),
            ),
            Tab(
              icon: Icon(
                Icons.list,
                size: 18,
              ),
              child: Text(
                "더보기",
                style: TextStyle(fontSize: 9),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

 

bottomNavigationBar에는 TabBar로 사용할 탭을 구성해준다. Tab을 통해 컨텐츠를 호출할 탭들을 등록시킨다.

TabBar를 Container로 감싸게 되면 원하는 모양으로 TabBar를 커스텀할 수 있다.

- labelColor => 선택된 탭의 label 색

- unselectedLabelColor => 선택되지 않은 탭의 label 색

- indicatorColor : Colors.transparent => indicator 없애기 

 

2. BottomNavigationBar() 사용하기

class _MyAppState extends State<MyApp> {
  int screenIndex = 0;
  List<Widget> screenList = [
    Center(child: Text('Home')),
    Center(child: Text('Search')),
    Center(child: Text('save')),
    Center(child: Text('more')),
  ];

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "Navigation",
      theme: ThemeData(
        brightness: Brightness.dark,
        primaryColor: Colors.black,
      ),
      home: Scaffold(
        body: screenList[screenIndex],
        bottomNavigationBar: BottomNavigationBar(
          backgroundColor: Colors.black,
          type: BottomNavigationBarType.fixed,
          selectedItemColor: Colors.white,
          unselectedItemColor: Colors.white60,
          currentIndex: screenIndex,
          items: [
            BottomNavigationBarItem(
              icon: Icon(Icons.home),
              label: '홈',
            ),
            BottomNavigationBarItem(
              icon: Icon(Icons.search),
              label: '검색',
            ),
            BottomNavigationBarItem(
              icon: Icon(Icons.save_alt),
              label: '저장한 콘텐츠 목록',
            ),
            BottomNavigationBarItem(
              icon: Icon(Icons.list),
              label: '더보기',
            ),
          ],
          onTap: (value) {
            setState(() {
              screenIndex = value;
            });
          },
        ),
      ),
    );
  }
}

 

List로 보여질 컨텐츠(위젯)를 미리 정해주고 탭을 선택할 때

Scaffold의 body에서 변화하도록 하는 방법이다.

BottomNavigationBar는 currentIndex라는 선택된 탭의 번호를 지정하는 속성을 가진다.

이 속성의 값은 탭의 선택에 따라 자동으로 변경되는 것이 아니라 onTap을 통해 바꿔주어야 한다.

onTab에서 screenIndex를 변경하면 body의 screenList, currentIndex가 변경되어 화면과 탭이 바뀌게 된다.

 

 

 

 

 

 

 

 

아직은 두 방법의 장단점을 모르겠다....

사용하다 보면 뭐가 편한지 알 수 있겠지....?.....

 

 

 

반응형

'Flutter' 카테고리의 다른 글

Stack과 Positioned  (0) 2022.01.11
Null safety 이해하기  (0) 2022.01.10
Flutter의 기본 구조를 알아보자  (0) 2022.01.07
Flutter Widget이 뭔가요  (0) 2022.01.06
Error launching application on Android SDK built for x86.  (0) 2022.01.06