공식 문서에서 상태관리를 설명을 위한 gif파일이 있습니다.
이번 장에서는 provider를 이용해서 이를 토대로 비슷하게 구현해보겠습니다.
문서를 토대로 클래스간 관계를 설정했습니다. (MyAppBar는 없음)
각 클래스의 책임
A RenderFlex overflowed by ~~ pixels on the bottom.
notifyListeners()
호출main
void main() {
runApp(
ChangeNotifierProvider(
create: (context) => Cart(),
child: const MyApp(),
),
);
}
MyApp
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
static PageController pageController = PageController(initialPage: 0);
static void previousPage() {
pageController.previousPage(duration: kTabScrollDuration, curve: Curves.ease);
}
static void nextPage() {
pageController.nextPage(duration: kTabScrollDuration, curve: Curves.ease);
}
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false, // debug 표시 해제
home: Scaffold(
body: PageView(
scrollDirection: Axis.horizontal,
controller: pageController,
children:const <Widget>[
MyLoginScreen(),
MyCatalog(),
MyCart()
],
),
),
);
}
}
MyLoginScreen
class MyLoginScreen extends StatelessWidget {
const MyLoginScreen({Key? key}) : super(key: key);
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text("Welcome")),
body: Container(
margin:const EdgeInsets.all(30),
child:Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget> [
const Text('Login',style: TextStyle(fontSize: 28)),
const TextField(
decoration: InputDecoration(
border: OutlineInputBorder(),
),
),
const Text('Password',style: TextStyle(fontSize: 28)),
const TextField(
decoration: InputDecoration(
border: OutlineInputBorder(),
),
),
ElevatedButton(onPressed: (){
FocusScope.of(context).unfocus();
MyApp.nextPage();},
child: const Text('Enter')),
])
)
);
}
}
MyCatalog
class MyCatalog extends StatelessWidget {
const MyCatalog ({Key? key}) : super(key: key);
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: const Icon(Icons.menu),
onPressed: (){},
),
actions: [
IconButton(
icon: const Icon(Icons.shopping_cart),
onPressed: () {
MyApp.nextPage();
},
),
],
title: const Text('Catalog'),
),
body: ListView(children:[
MyListItem(0),
MyListItem(1),
MyListItem(2),
MyListItem(3),
MyListItem(4)
]));
}
}
MyListItem
class MyListItem extends StatelessWidget {
int index;
MyListItem(this.index, {Key? key}) : super(key: key);
Widget build(BuildContext context) {
bool isIn = context.select((Cart cart) => cart.itemList[index]);
TextButton button;
if(isIn) {
button = TextButton(
child: const Icon(Icons.check,color: Colors.red),
onPressed: (){}
);
}else {
button = TextButton(
child: const Text("add"), onPressed: (){
context.read<Cart>().addItem(index);
}
);
}
return Row(children: [
Container(width:150,height:50, margin:const EdgeInsets.all(10),color: Cart.itemInfo[index][0]),
button
]);
}
}
MyCart
class Cart extends ChangeNotifier {
List itemList = [];
Cart() : itemList = [false, false, false, false, false];
static List itemInfo = [
// 컬러값 가격
[Colors.blue[100], (42*0.5).toInt()],
[Colors.blue[300], 42],
[Colors.blue[500], 42*2],
[Colors.blue[700], 42*3],
[Colors.blue[900], 42*4],
];
void addItem(int index) {
itemList[index] = true;
notifyListeners();
}
void clearItem() {
itemList = [false, false, false, false, false];
notifyListeners();
}
}