23/03/20(flutter+HRD앱)

조영문·2023년 3월 20일
0

flutter

목록 보기
1/9

HRD 앱 flutter Example

구현하고자 하는 목표 화면

pubspec.yaml 파일 수정

화면구성

view -> page 다트 파일

controller -> 상태 관리 다트 파일

model -> 서버 통신 및 데이터 형태를 정의하는 다트 파일, 통신 기능 구현 다트 파일

widgets -> 해당 페이지에 필요한 위젯들

화면 위젯 3가지
1. 자식을 가질 수 없는 위젯
(Text, Image)
2. 자식을 하나만 가질 수 있는 위젯
(MaterialApp, Scaffod, SafeArea, Container, Center)
3. 자식을 여러 개 가질 수 있는 위젯
(Column, Row, ListView)

defualt_page.dart

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) - 라이브러리가 시키는 방법에 따라 진행하면 화면 변경된다.

  1. 일반 변수(상태가 아닌 변수)는 바뀌더라도 화면이 변하지 않는다.
  2. 데이터가 변하면 화면이 변한다.(재빌드)
  3. 데이터를 넣어 주는 방식을 기억한다.
    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],
      ),
    );

OR

  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가 빌드된 걸 볼 수 있다.

기능

onTap 등 유저의 반응을 통해서 함수수행

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에서 값을 바꿀때는 알려줘야함
  }

}

lib/check/controller/check.dart

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,
      ),   

main.dart

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(),
    );
  }
}

git

https://github.com/youngmoon97/flutter_example

0개의 댓글