앱의 하단부 네비게이션바를 통해서 화면전환을 해보자.
IndexedStack
은 자식 위젯 중 하나만 보이도록 하는 위젯이다.
index
속성을 이용해서 전환되는 페이지들을 children
에 넣는다.
return Scaffold(
body: IndexedStack(
index: _selectedIndex,
children: [
FriendScreen(),
ChatScreen(),
MoreScreen(),
],
),
화면이 전환되므로 상위 위젯은 Stateful이 되어야 한다.
_selectedIndex
에 선택된 index
를 저장한다.
class MainScreen extends StatefulWidget {
const MainScreen({Key? key}) : super(key: key);
State<MainScreen> createState() => _MainScreenState();
}
class _MainScreenState extends State<MainScreen> {
int _selectedIndex = 0;
void changeScreen(index){
setState(() {
_selectedIndex = index;
});
}
화면을 전환하기 위해 BottomNavigationBar
을 추가한다.
bottomNavigationBar: BottomNavigationBar(
showSelectedLabels: false, // 선택된 탭 움직임
showUnselectedLabels: false,
selectedItemColor: Colors.black,
unselectedItemColor: Colors.black87,
currentIndex: _selectedIndex,
backgroundColor: Colors.grey[200],
onTap: (index){
changeScreen(index);
},
items: [
BottomNavigationBarItem(
icon: Icon(FontAwesomeIcons.user),
label: ""
),
BottomNavigationBarItem(
icon: Icon(FontAwesomeIcons.comment),
label: ""
),
BottomNavigationBarItem(
icon: Icon(FontAwesomeIcons.ellipsisH),
label: ""
),
],
),
네비게이션바를 누르면 onTap
에 의해서 changeScreen
이 호출되고 선택된 index가 변경되어 화면이 다시 렌더링된다.
리스트를 생성하는 방법
List.generate
는 미리 전체 아이템 리스트를 생성한다. 메모리를 더 먹게 된다.
Expanded(
child: ListView(
children:
List.generate(friends.length, (index) => // friends 는 유저정보 리스트
ProfileCard(user: friends[index])
)
),
)
ListView.builder
는 lazy loading 기법을 사용하여 리스트 뷰 아이템이 필요할 때만 생성하고 화면에 표시한다.
itemBuilder
콜백함수를 이용해서 필요할때만 생성하므로 대규모 데이터에 적합하다.
반면에 빌더로 작은 아이템을 생성하면 연산자원이 낭비된다.
Expanded(
child: ListView.builder(
itemCount: friends.length, // 몇개를 홤ㄴ
itemBuilder: (context, index) =>
ProfileCard(user: friends[index])),
),
itemCount
로 리스트의 수를 유지한다.
프로필을 누른다면
child: ListTile(
onTap: (){
Navigator.push(
context,
MaterialPageRoute(builder: (context)=>
ProfileScreen(user: user,),
)
);
},
leading: _avatar(),
title: _title(),
subtitle: _subtitle(),
),
Navigator.push
가 스택 위로 새로운 화면을 그린다.