2023. 1. 27. 13:50ㆍ모바일어플개발/Flutter
안녕하세요~ totally 개발자입니다.
오늘 다룰 부분은 Scaffold 위젯에 있는 bottomNavigationBar 속성을 이용하여 화면 하단 네비게이션 바를 배치해보는 것에 대해 살펴보도록 하겠습니다. 보통 인스타그램, 카카오톡 등 요즘 어플들을 보면 화면 하단에 네비게이션바가 위치하고 있는 것을 알 수 있습니다. 대부분의 이유로는 화면 하단에 있기 때문에 한 손가락으로 쉽게 누르면서 조작할 수 있다는 장점이 있습니다.
예제로 바로 들어가보도록 하겠습니다.
Step1: 9번째 줄에 with SingleTickerProviderStateMixin을 추가하고 10, 11번째 줄에 TabController와 tab을 선택했을 때 선택한 인덱스 값을 담을 수 있는 integer 변수를 하나 선언해줍니다.

Step2: initState와 dispose 상태에서 tabController에 addListener를 추가해서 tab 메뉴를 선택했을 때 _selectedIndex 값을 _tabController.index로 assign해줄 수 있도록 해주시고 setState를 통해 상태 업데이트를 해주면 됩니다.

Step3: Scaffold 위젯에서 bottomNavigationBar를 추가해주고 33~58번째 줄같이 작성해주시면 됩니다. 제가 여기에서 SizedBox 위젯부터 적은 이유는 height를 별도로 명시해주시기 위함이며 기본 height값으로 괜찮은 경우에는 생략하셔도 됩니다. 그 다음 TabBar 위젯을 적고 controller, tabs에 다음처럼 적어주면 되며 여기에는 배열 형태로 들어가게 되므로 여러 값이 들어갈 수 있습니다. Tab 위젯을 활용하면 되고 icon, text 등 여러 속성을 담을 수 있습니다.


위와 같이 결과가 나오면 성공입니다. 다만 아직 아래에 네비게이션 메뉴를 눌러보아도 변경되는 점은 아직은 없습니다. 이번에는 각 메뉴를 클릭했을 때 각 다른 탭의 내용이 나올 수 있도록 구성해보도록 하겠습니다.

하단 네비게이션 메뉴를 클릭했을 때 탭의 내용이 달라지도록 변경해본 모습입니다. 각 탭 메뉴를 클릭할 때 아이콘도 변경해줌으로서, 어떤 메뉴를 클릭했는지 알 수 있도록 했습니다. 결과는 아래와 같습니다.
![]() |
![]() |
![]() |
각 메뉴를 클릭했을 때 다른 컨테이너가 나오도록 한 코드는 ? 물음표 기호와 : 콜론을 사용한 Conditional (ternary) operator입니다. if else 대신 이것을 사용하여 아래처럼 나타낼 수 있습니다. _selectedIndex == 0 ? [0이면 이것 실행] : [0이 아니면 이것 실행] 이런 방식으로 구현됩니다. 그리고 동일한 구조의 Container 위젯이 3번 사용되기 때문에 별도 컨테이너로 분리했습니다.

아래 전체 소스 코드를 첨부했으니 참고하시기 바랍니다. 감사합니다.
[전체 소스 코드]
import 'package:flutter/material.dart'; | |
class TestView extends StatefulWidget { | |
@override | |
State<TestView> createState() => _TestViewState(); | |
} | |
class _TestViewState extends State<TestView> | |
with SingleTickerProviderStateMixin { | |
TabController _tabController; | |
int _selectedIndex = 0; | |
@override | |
void initState() { | |
super.initState(); | |
_tabController = TabController(length: 3, vsync: this); | |
_tabController.addListener( | |
() => setState(() => _selectedIndex = _tabController.index)); | |
} | |
@override | |
void dispose() { | |
_tabController.dispose(); | |
super.dispose(); | |
} | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: AppBar( | |
title: Text("Test Title"), | |
), | |
bottomNavigationBar: SizedBox( | |
height: 80, | |
child: TabBar( | |
indicatorColor: Colors.transparent, | |
labelColor: Colors.black, | |
controller: _tabController, | |
tabs: <Widget>[ | |
Tab( | |
icon: Icon( | |
_selectedIndex == 0 ? Icons.person : Icons.person_2_outlined, | |
), | |
text: "Friends", | |
), | |
Tab( | |
icon: Icon( | |
_selectedIndex == 1 ? Icons.chat : Icons.chat_outlined, | |
), | |
text: "Chats", | |
), | |
Tab( | |
icon: Icon( | |
_selectedIndex == 2 ? Icons.settings : Icons.settings_outlined, | |
), | |
text: "Settings", | |
), | |
], | |
), | |
), | |
body: _selectedIndex == 0 | |
? tabContainer(context, Colors.indigo, "Friends Tab") | |
: _selectedIndex == 1 | |
? tabContainer(context, Colors.amber[600], "Chats Tab") | |
: tabContainer(context, Colors.blueGrey, "Settings Tab"), | |
); | |
} | |
Container tabContainer(BuildContext context, Color tabColor, String tabText) { | |
return Container( | |
width: MediaQuery.of(context).size.width, | |
height: MediaQuery.of(context).size.height, | |
color: tabColor, | |
child: Center( | |
child: Text( | |
tabText, | |
style: TextStyle( | |
color: Colors.white, | |
), | |
), | |
), | |
); | |
} | |
} |
[유튜브 강좌 영상]
'모바일어플개발 > Flutter' 카테고리의 다른 글
[028] 플러터 (Flutter) 배우기 - 애니메이션 만들기2: 카드 뒤집기 (TweenAnimationBuilder, Transform 사용) (0) | 2023.01.30 |
---|---|
[027] 플러터 (Flutter) 배우기 - 애니메이션 만들기1 (AnimatedContainer 사용) (0) | 2023.01.29 |
[025] 플러터 (Flutter) 배우기 - TTS(Text To Speech): 텍스트를 소리로 나타내기 (0) | 2023.01.20 |
[024] 플러터 (Flutter) 배우기 - Lifecycle (플러터 생명주기) (0) | 2023.01.17 |
[023] 플러터 (Flutter) 배우기 - Shared Preferences (디스크에 간단한 데이터 저장) (0) | 2022.12.11 |