1. New Project
- 이전 방식과 동일
2. Model 생성
- 미리 사용할 아이콘 및 서버에서 받아올 데이터를 설정
- 아래 파일을 lib/models 폴더 아래에 복사 후 붙여 넣어서 사용
3. 화면 캐싱
- 화면 전환 시 Stack에 Screen 또는 Container를 화면에 보이도록 설정
- Container를 출력시킴으로써 페이지를 이동할 때마다 모든 화면이 다시 rebuild 되는 것을 막음
- 선택한 화면만 rebuild
Scaffold(
body: IndexedStack(
index: selectedIndex,
children: [
loadPages.contains(0) ? HomeScreen() : Container(),
loadPages.contains(1) ? NeighborhoodScreen() : Container(),
loadPages.contains(2) ? NearMeScreen() : Container(),
loadPages.contains(3) ? ChattingScreen() : Container(),
loadPages.contains(4) ? MyCarrotScreen() : Container(),
],
),
bottomNavigationBar: _bottomNavigationBar(context),
);
- 각 화면 예시 : 화면 설명만 작성
import 'package:flutter/material.dart';
class HomeScreen extends StatelessWidget {
const HomeScreen();
@override
Widget build(BuildContext context) {
print("Home Screen build");
return Scaffold(
body: Center(child: Text("Home Screen")),
);
}
}
- const : 최초로 접속하는 화면만 메모리에 올려두고, 이후에 해당 페이지를 접속할 경우 메모리에 저장된 화면을 불러옴
- Page의 Index를 선택 시 추가 (화면 저장용)
- const로 설정되어 있기 때문에 화면 내부의 데이터를 변경할 수 없음
- 변경이 필요할 시 StatefulWidget 필요 → 화면이 계속 새로 로딩되는 문제
class MainScreens extends StatefulWidget {
@override
State<MainScreens> createState() => _MainScreensState();
}
class _MainScreensState extends State<MainScreens> {
int selectedIndex = 0;
List<int> loadPages = [0];
void selectBottomMenu(int index) {
selectedIndex = index;
if (!loadPages.contains(index)) loadPages.add(index); // 0 , 1
setState(() {});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: IndexedStack(
index: selectedIndex,
children: [
loadPages.contains(0) ? const HomeScreen() : Container(),
loadPages.contains(1) ? const NeighborhoodScreen() : Container(),
loadPages.contains(2) ? const NearMeScreen() : Container(),
loadPages.contains(3) ? const ChattingScreen() : Container(),
loadPages.contains(4) ? const MyCarrotScreen() : Container(),
],
),
bottomNavigationBar: _bottomNavigationBar(context),
);
}
Theme _bottomNavigationBar(BuildContext context) {
return BottomNavigationBar(
/* // 지금 사용 안함
showSelectedLabels: true,
showUnselectedLabels: false,
*/
type: BottomNavigationBarType.fixed,
selectedItemColor: Colors.deepOrange,
unselectedItemColor: Colors.black54,
selectedFontSize: 12.0,
unselectedFontSize: 12.0,
currentIndex: selectedIndex,
// 매개변수 자동 전달
onTap: selectBottomMenu,
items: [
BottomNavigationBarItem(label: "홈", icon: Icon(CupertinoIcons.home)),
BottomNavigationBarItem(label: "동네 생활", icon: Icon(CupertinoIcons.square_on_square)),
BottomNavigationBarItem(label: "내 근처 정보", icon: Icon(Icons.location_on)),
BottomNavigationBarItem(label: "채팅", icon: Icon(CupertinoIcons.chat_bubble_text)),
BottomNavigationBarItem(label: "내 당근", icon: Icon(CupertinoIcons.person)),
],
),
);
}
}
- initState() → 미리 List를 null로 build시킨 후 멤버로 추가
class MainScreens extends StatefulWidget {
@override
State<MainScreens> createState() => _MainScreensState();
}
class _MainScreensState extends State<MainScreens> {
int selectedIndex = 0;
final List<Widget?> _screens = List.filled(5, null);
@override
void initState() {
super.initState();
_screens[0] = HomeScreen(); // 처음은 미리 생성
}
void selectBottomMenu(int index) {
if (_screens[index] == null) {
_screens[index] = _buildScreen(index); // 처음 클릭 시 생성
}
setState(() {
selectedIndex = index;
});
}
Widget _buildScreen(int index) {
switch (index) {
case 0:
return HomeScreen();
case 1:
return NeighborhoodLifeScreen();
case 2:
return NearMeScreen();
case 3:
return ChattingScreen();
case 4:
return MyCarrotScreen();
default:
return Container();
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: IndexedStack(
index: selectedIndex,
children: _screens.map((screen) => screen ?? Container()).toList(),
),
bottomNavigationBar: _bottomNavigationBar(),
);
}
BottomNavigationBar _bottomNavigationBar() {
return BottomNavigationBar(
type: BottomNavigationBarType.fixed,
selectedFontSize: 12.0,
unselectedFontSize: 12.0,
selectedItemColor: Colors.orange,
unselectedItemColor: Colors.black54,
currentIndex: selectedIndex,
onTap: selectBottomMenu,
items: const [
BottomNavigationBarItem(label: "홈", icon: Icon(CupertinoIcons.home)),
BottomNavigationBarItem(label: "동네생활", icon: Icon(CupertinoIcons.square_on_square)),
BottomNavigationBarItem(label: "내근처", icon: Icon(CupertinoIcons.placemark)),
BottomNavigationBarItem(label: "채팅", icon: Icon(CupertinoIcons.chat_bubble_2)),
BottomNavigationBarItem(label: "나의당근", icon: Icon(CupertinoIcons.person)),
],
);
}
}
CORS
- Web으로 프로젝트를 실행할 경우, 그림이 보이지 않는 현상 발생
- CORS 정책으로 인해 github 또는 외부의 주소로 그림을 받아 출력할 수 없음
- Chrome으로 구동 시에는 이미지를 picsum 또는 asset에 저장하여 사용할 것

Share article