IndexedStack
에 등록된 페이지를 한번에 렌더링 한다.
다른 페이지를 보여주지 않을뿐 로그를 확인하면 모두 렌더링 되어 있는것을 알 수 있다.
네이게이션바에 선택된 인덱스 상태로 IndexedStack
에 등록된 페이지를 렌더링 하게 된다.
class MainPage extends StatefulWidget {
const MainPage({Key? key}) : super(key: key);
State<MainPage> createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> {
int _selectedIndex = 0;
Widget build(BuildContext context) {
return Scaffold(
body: IndexedStack(
index: _selectedIndex,
children: const [
HomePage(),
MapNearbyPlacePage(),
SearchKeywordPage(),
MyPage(),
],
),
bottomNavigationBar: CustomBottomNavigationBar(
selectedIndex: _selectedIndex,
onTabTapped: (int index) {
setState(() {
_selectedIndex = index;
});
},
),
);
}
}
하지만 한번에 모든 페이지가 렌더링 되면 안될수도 있고
위 코드로는 뒤로가기시 앱이 그대로 종료 되어버리는 문제가 발생한다.
페이지뷰의 특성대로 한번에 하나의 페이지만 렌더링 한다.
인덱스에 선태된 페이지만 렌더링 하므로 다른 페이지를 미리 렌더링 하지 않는다.
class _MainPageState extends State<MainPage> {
final PageController _pageController = PageController();
int _selectedIndex = 0;
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
if (_selectedIndex != 0) {
setState(() {
_selectedIndex = 0;
_pageController.jumpToPage(0);
});
return false;
} else {
final exit = await showDialog<bool>(
context: context,
builder: (context) => AlertDialog(
content: const Text("앱을 종료하시겠습니까?"),
actions: <Widget>[
TextButton(
onPressed: () => Navigator.pop(context, true),
child: const Text('확인'),
),
TextButton(
onPressed: () => Navigator.pop(context, false),
child: const Text('취소'),
),
],
),
);
// showDialog의 결과로부터 뒤로 가기 버튼의 동작을 결정합니다.
return exit ?? false;
}
},
child: Scaffold(
body: PageView(
controller: _pageController,
physics: const NeverScrollableScrollPhysics(), // 스와이프 막아줌
children: [
const HomePage(),
const MapNearbyPlacePage(),
SearchKeywordPage(),
const MyPage(),
],
),
bottomNavigationBar: CustomBottomNavigationBar(
selectedIndex: _selectedIndex,
onTabTapped: (int index) {
setState(() {
_selectedIndex = index;
_pageController.jumpToPage(index);
});
},
),
));
}
}
만약 지정한 인덱스에서 뒤로가기를 눌렀을 경우 원하는 위젯을 렌더링 할 수 있다.
위 코드 에서는 홈화면 ( 0 번 인덱스 ) 에서 뒤로가기를 눌렀을 경우에만 한번더 뒤로가기를 누르면 종료된다는 메세지를 표시 했다.
또한 홈화면이 아닐경우 홈화면으로 이동되도록 컨트롤러의 JumpToPage()
를 이용했다.