하단 바를 만들고, 아이콘을 탭하면 정해진 화면을 렌더하도록 하자.
1. 상태가 바뀌는 것이니 stful 위젯으로 설정
2. Scaffold의 bottomNavigationBar 속성으로 BottomNavigationBar을 주고 그 아이템으로 BottomNavigationBarItem을 던져줍니다.
3. 페이지가 바뀔 때는 렌더하고 싶은 위젯을 그냥 던져주는 것이 아니라 IndexedStack를 사용합니다. 생성된 위젯을 그냥 던져주면 매번 페이지를 새로 렌더해야 합니다. 리소스 낭비인 거죠.
그러나 IndexedStack를 선택하면, 우선 렌더해야 할 위젯을 stack 쌓아둔 후 필요한 위젯을 최상단으로 가져오고 그 이전에 존재하는 위젯을 다른 곳에 보관하는 방식으로 작동합니다.
4. onTap 속성에 주는 함수로 페이지 이동시키면 됩니다. 또, onTap에는 자동으로 아이콘의 index가 주어집니다. 이를 이용하시면 됩니다.
class MainPage extends StatefulWidget {
@override
_MainPageState createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> {
int _selectedIndex = 0;
// 화면에 렌더링할 위젯들
static List<Widget> _widgetOptions = [
Container(color: Colors.primaries[0],),
Container(color: Colors.primaries[1],),
Container(color: Colors.primaries[2],),
Container(color: Colors.primaries[3],),
Container(color: Colors.primaries[4],),
];
// 탭 할 때마다 index를 바꿔줍니다.
void _onItemTapped(int index) {
print(index);
setState(() {
_selectedIndex = index;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title : Text("test")),
body: IndexedStack(
index: _selectedIndex,
children: _widgetOptions,
),
bottomNavigationBar: BottomNavigationBar(
// 선택한 아이템의 레이블 표시할 건가? (왜냐하면 BottomNavigationBarItem의 title이 필수값이라서)
showSelectedLabels: false,
// 선택하지 않은 아이템의 레이블 표시할 건가?
showUnselectedLabels: false,
// 선택한 아이템의 색
selectedItemColor: Colors.black,
// 선택하지 않은 아이템의 색
unselectedItemColor: Colors.grey[900],
// animate and labels fade in when they are tapped.
// 어차피 shifting, fixed 밖에 없습니다.
type: BottomNavigationBarType.shifting,
// 하단 바의 배경 색깔
backgroundColor: Color.fromRGBO(249, 249, 249, 1),
// 하단 바가 가질 아이템들
items: [
_buildBottomNavigationBarItem(activeIconPath: "assets/home_selected.png", iconPath: "assets/home.png"),
_buildBottomNavigationBarItem(activeIconPath: "assets/search_selected.png", iconPath: "assets/search.png"),
_buildBottomNavigationBarItem(iconPath: "assets/add.png"),
_buildBottomNavigationBarItem(activeIconPath: "assets/heart_selected.png", iconPath: "assets/heart.png"),
_buildBottomNavigationBarItem(activeIconPath: "assets/profile_selected.png", iconPath: "assets/profile.png"),
],
// 선택한 아이템의 index
currentIndex: _selectedIndex,
// 아이템을 선택했을 때 할 액션
onTap: (index) => _onItemTapped(index)
),
);
}
}
BottomNavigationBarItem _buildBottomNavigationBarItem({String activeIconPath, String iconPath}) {
return BottomNavigationBarItem(
// 선택되었을 때 사용할 아이콘
activeIcon: activeIconPath == null ? null : ImageIcon(AssetImage(activeIconPath)),
// 선택 안 되었을 때의 아이콘
icon: ImageIcon(AssetImage(iconPath)),
// BottomNavigationBarItem은 title 속성이 필수값입니다.
title: Text(''),
);
}
'📱 Mobile > 📱 (old) Flutter v 1.0' 카테고리의 다른 글
Widget 정리 (상시 업데이트) (0) | 2020.05.15 |
---|---|
속성 정의가 길어질 때 Widget 분리 (0) | 2020.05.14 |
외부 라이브러리 사용 (0) | 2020.05.14 |
GridView : SliverGridDelegateWithFixedCrossAxisCount (0) | 2020.05.14 |
Flutter 프로젝트 구성과 기본적인 코딩 + assets + Fixes (0) | 2020.04.30 |