view -> page 다트 파일
controller -> 상태 관리 다트 파일
model -> 서버 통신 및 데이터 형태를 정의하는 다트 파일, 통신 기능 구현 다트 파일
widgets -> 해당 페이지에 필요한 위젯들
화면 위젯 3가지
1. 자식을 가질 수 없는 위젯
(Text, Image)
2. 자식을 하나만 가질 수 있는 위젯
(MaterialApp, Scaffod, SafeArea, Container, Center)
3. 자식을 여러 개 가질 수 있는 위젯
(Column, Row, ListView)
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_hrd_page/check/controller/check_controller.dart';
import 'package:flutter_hrd_page/check/view/check_page.dart';
import 'package:flutter_hrd_page/default/widgets/default_first_item.dart';
import 'package:flutter_hrd_page/default/widgets/default_second_item.dart';
import 'package:provider/provider.dart';
//페이지 내부의 상태를 관리하기 위해 HookWidget 사용
//사용할 수 있는 Hook
//useState, useEffect 등이 있다.
//Hook은 build 함수 안에 적는다.
class DefaultPage extends HookWidget {
DefaultPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final checkController = context.watch<CheckController>();
List widgetItems = [
() => DefaultFirstItem(checkController.isChecked),
() => DefaultSecondItem(),
];
final navIndex = useState(0);
print("DefalutPage 빌드됨" + navIndex.value.toString());
return Scaffold(
appBar: AppBar(
title: Center(child: Text("나의 정보")),
//title: Text("나의 정보"),
actions: [
InkWell(
onTap: () {
Navigator.push(
//pushreplacement 뒤로가기 없음
context,
MaterialPageRoute(builder: (context) => CheckPage()),
);
},
child: Padding(
padding: const EdgeInsets.only(right: 30.0),
child: Icon(Icons.move_to_inbox),
),
),
], //centerTitle: true,
),
bottomNavigationBar: BottomNavigationBar(
onTap: (int idx) {
navIndex.value = idx;
},
currentIndex: navIndex.value,
items: [
BottomNavigationBarItem(
icon: Icon(
Icons.account_circle_outlined,
),
label: "나의정보"),
BottomNavigationBarItem(
icon: Icon(
Icons.cabin,
),
label: "다른정보"),
],
),
body: SafeArea(
child: widgetItems[navIndex.value](),
),
);
}
}
상태는 변화하는 데이터
stateless 위젯은 화면 변경이 안됨
stateful 위젯은 상태에 따라 화면 변경됨
stateless 위젯 + 상태 라이브러리 - 상태에 따라 화면 변경됨
라이브러리 위젯(HookWidget) - 라이브러리가 시키는 방법에 따라 진행하면 화면 변경된다.
- 일반 변수(상태가 아닌 변수)는 바뀌더라도 화면이 변하지 않는다.
- 데이터가 변하면 화면이 변한다.(재빌드)
- 데이터를 넣어 주는 방식을 기억한다.
2-1. 상태주입(HookWidget, MultiProvider)
2-2. 상태변경(만든 함수 controller.chage())
2-3. 상태관찰(controller.isChecked)
context.watch -> 상태를 계속 관찰하겠다.
(데이터가 바뀌는 것을 관찰할 수 있다.)
(데이터 관찰하기 때문에 데이터가 바뀌면 화면에 영향끼침)
(context.read+관찰)
/
context.read -> 상태를 한번만 확인하겠다.
(상태가 바뀌어도 화면에 영향을 끼치지 못함)
(상태를 변화시켜는 함수는 사용가능)
navIndex로 바꿀 수 있음
List widgetItems = [
Container(color: Colors.yellow,) ,
Container(color: Colors.blue,) ,
];
//
body: SafeArea(
child: widgetItems[navIndex.value],
),
);
List widgetItems = [
() => DefaultFirstItem(),
() => DefaultSecondItem()
];
body: SafeArea(
child: widgetItems[navIndex.value](),
),
);
///first
import 'package:flutter/material.dart';
class DefaultFirstItem extends StatelessWidget {
const DefaultFirstItem({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(color: Colors.yellow,);
}
}
///second
import 'package:flutter/material.dart';
class DefaultSecondItem extends StatelessWidget {
const DefaultSecondItem({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(color: Colors.blue,);
}
}
값변경 페이지에서 값변경 버튼을 누르면 화면은 바로 안 보이지만 run에 보면 DefaultPage가 빌드된 걸 볼 수 있다.
actions: [
InkWell(
onTap: () {
Navigator.push( //pushreplacement 뒤로가기 없음
context,
MaterialPageRoute(
builder: (context) => CheckPage()),
);
}
페이지에 종속된 위젯들을 조건에 맞게 출력
우측 상단에 버튼을 누르면 값변경 페이지로 들어가고 값변경 버튼을 누르면 default페이지의 값이 변경된다.
lib/check/controller/check_controller.dart
import 'package:flutter/foundation.dart';
class CheckController extends ChangeNotifier{
bool _isChecked = false;
bool get isChecked => _isChecked;
void change(){
_isChecked = !_isChecked;
notifyListeners(); //Provider에서 값을 바꿀때는 알려줘야함
}
}
import 'package:flutter/material.dart';
import 'package:flutter_hrd_page/check/controller/check_controller.dart';
import 'package:provider/provider.dart';
class CheckPage extends StatelessWidget {
const CheckPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final checkController = context.watch<CheckController>();
return Scaffold(
appBar: AppBar(),
body: SafeArea(
child: Container(
child: Center(
child: Column(
children: [
Text("체크페이지"),
ElevatedButton(
onPressed: (){
checkController.change();
},
child: Text("값변경"),
)
],
),
),
),
),
);
navigator를 이용
@override
Widget build(BuildContext context) {
final navIndex = useState(0);
print("DefalutPage 빌드됨" + navIndex.value.toString());
return Scaffold(
appBar: AppBar(
title: Center(child: Text("나의 정보")),
//title: Text("나의 정보"),
actions: [
InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => CheckPage()),
);
},
child: Padding(
padding: const EdgeInsets.only(right: 30.0),
child: Icon(Icons.move_to_inbox),
),
),
], //centerTitle: true,
),
import 'dart:js';
import 'package:flutter/material.dart';
import 'package:flutter_hrd_page/check/controller/check_controller.dart';
import 'package:flutter_hrd_page/default/view/default_page.dart';
import 'package:provider/provider.dart';
void main(){
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(create: (context)=>CheckController()),
],
child: MyApp(),
)
);
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
print("메인 빌드됨");
return MaterialApp(
home: DefaultPage(),
);
}
}