결과

NavigationBar 클래스 이용
- destinations: 리스트 형식으로 메뉴 형성
- selectedIndex: 위의 리스트에서 선택한 순서값을 저장
- onDestinationSelected : destinations의 리스트 중 하나가 선택되면 호출
NavigationBar의 destinations 에서 요소들 중 한 개를 클릭하면 onDestinationSelected가 호출되고,
콜백으로 selectedIndex의 값을 업데이트한다.
selectedIndex가 업데이트 되면 NavigationBar는 다시 빌드되면서 선택한 요소로 이동!
int tabPageIndex = 0;
@override
Widget build(BuildContext context) {
return NavigationBar(
destinations: [
NavigationDestination(
icon: Icon(Icons.home_outlined),
selectedIcon: Icon(Icons.home),
label: "Home"
),
NavigationDestination(
icon: Icon(Icons.add_comment_outlined),
selectedIcon: Icon(Icons.add_comment),
label: "Memory"
),
NavigationDestination(
icon: Icon(Icons.people_outline),
selectedIcon: Icon(Icons.people),
label: "Community"
),
NavigationDestination(
icon: Icon(Icons.star_border_outlined),
selectedIcon: Icon(Icons.star),
label: "My"
)
],
selectedIndex: tabPageIndex,
onDestinationSelected: (value) {
setState(() {
tabPageIndex = value;
});
},
indicatorColor: Colors.amberAccent,
);
}
indicatorColor는 선택 시 요소의 배경 색을 설정한 것이다.
여기에 Provider 적용
https://pub.dev/packages/provider/install
provider install | Flutter package
A wrapper around InheritedWidget to make them easier to use and more reusable.
pub.dev
pubspec.yaml 파일의 dependencies에
provider: ^6.1.2
입력 후 Pub get
dart 파일 하나 생성 후 코드 입력
import 'package:flutter/material.dart';
class NavigationIndexProvider extends ChangeNotifier{
int _currentPageIndex = 0;
int get currentPageIndex => _currentPageIndex;
void setCurrentPageIndex(int index){
_currentPageIndex = index;
notifyListeners();
}
}
provider를 쓰는 이유!
-> main.dart에 모든 코드를 넣지 않을 거라서!
다른 파일에서 생긴 변화를 다른 파일에서 감지하고 화면에 반영해야하기에
연결할 Provider 사용
main_bottom_navigation_bar
@override
Widget build(BuildContext context) {
var navigationIndexProvider = Provider.of<NavigationIndexProvider>(context, listen: false);
return NavigationBar(
destinations: [
NavigationDestination(
icon: Icon(Icons.home_outlined),
selectedIcon: Icon(Icons.home),
label: "Home"
),
NavigationDestination(
icon: Icon(Icons.add_comment_outlined),
selectedIcon: Icon(Icons.add_comment),
label: "Memory"
),
NavigationDestination(
icon: Icon(Icons.people_outline),
selectedIcon: Icon(Icons.people),
label: "Community"
),
NavigationDestination(
icon: Icon(Icons.star_border_outlined),
selectedIcon: Icon(Icons.star),
label: "My"
)
],
selectedIndex: navigationIndexProvider.currentPageIndex,
onDestinationSelected: (value) {
setState(() {
navigationIndexProvider.setCurrentPageIndex(value);
});
},
indicatorColor: Colors.amberAccent,
);
}
selectedIndex에서는 currentPageIndex값을 가져오는 get함수를 사용했고,
onDestinationSelected에서는 setCurrentPageIndex인 set함수를 사용해 바뀐 index값으로 저장했다.
main_screen
@override
Widget build(BuildContext context) {
var navigationIndexProvider = Provider.of<NavigationIndexProvider>(context, listen: false);
var currentIndex = navigationIndexProvider.currentPageIndex;
navigationIndexProvider.addListener(() {
setState(() {
currentIndex = navigationIndexProvider.currentPageIndex;
});
});
return Container(
child: [
Center(child: Text("Home")),
Center(child: Text("Memory")),
Center(child: Text("Community")),
Center(child: Text("My"))
][currentIndex]
);
}
main화면에서도 Provider를 선언하고 Provider의 리스너 등록했다.
Container의 index값을 currentIndex값으로 바꿨다.
여기서 addListener는
provider 파일의 setCurrentPageIndex함수 안의
notifyListeners();에 의해 동작한다.
notifyListeners()는 provider에 등록된 모든 리스너 실행하기 때문이다.
main
home: ChangeNotifierProvider(
create: (BuildContext context) => TabPageIndexProvider(),
child: Scaffold(
bottomNavigationBar: MainBottomNavigationBar(),
body: MainScreen(),
),
),
마지막으로 main의 home에서는
ChangeNotifierProvider로 변화에 대한 구독을 하고,
create를 사용해서 ChangeNotifier를 생성한다.
ChangeNotifierProvider는 하나만 구독할 수 있으니 여러 개를 하려면
MultiProvider를 이용해야 한다.
Provider의 상태를 받아오는 방법
1. Provider.of: 해당 위젯 전체가 리빌드
-> 가벼운 위젯은 괜찮음
- 자동 리빌드(필요에 의해 방지 가능)
- 간편함(코드 짧음), 일관성(상태에 직접 접근)
2. Consumer: 변화가 필요한 위젯만 리빌드 (자식 위젯 중에서)
-> 여러 효과나 연산이 복잡한 위젯일 경우 추천
- 코드 양 더 많음
- 최적화(성능 향상)
- 유연성: 상태 변경 시 반영할 콜백 함수 제공
현재 코드에서는 상태가 변경될 때마다 해당 위젯이 리빌드되어야 하므로
Provider.of를 사용하는 것이 더 간단하고 적합하다.
MainBottomNavigationBar는 하단 네비게이션 바이기 때문에 해당 상태가 변경될 때마다 리빌드되는 것이 일반적이다.