Flutter (23.03.20)

상목·2023년 3월 20일
0

Flutter

목록 보기
2/3

1. 화면구성

<default 디렉토리 만들기>

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

controller : 상태관리 다트 파일

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

view : Page dart 파일

화면 웨젯 3가지 

1. 직계자식이 가질수 없는 위젯 -> Text,image, Divider 등등

2. 직계자식을 하나만 가질 수 있는 위젯 -> 머터리얼앱, 스캐폴드, safearea)

3. 직계자식을 여러개 가질수 있는 위젯 -> Column, Row, ListView

<default_page.dart 소스코드> : StatelessWidget

// 화면을 만들면 가장 먼저 할 것.
import 'package:flutter/material.dart';

// StatelessWidget 사용
class DefaultPage extends StatelessWidget {
  const DefaultPage({Key? key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(

        // title: Text("나의 정보"),

        // 타이틀 중간 정렬 두가지 방법 (서로 위치 다름),
        // title: Center(child: Text("나의 정보"))는 다른 글자가 들어와도 중간
        title: Center(child: Text("나의 정보")),


        // 다른글자가 들어오면 글자의 공간만큼 밀려남
        // title : Text("가운데정렬"),
        // centerTitle: true,
        actions: [
          // all 은 모든 방향 패딩 only는 한쪽 방향만 설정할 때
          Padding(padding: const EdgeInsets.only(right: 30),
           child : Icon(Icons.move_to_inbox),
          ),
      ],

      ),
      bottomNavigationBar: BottomNavigationBar(
        // Items에는 2개 이상의 네비게이션바가 있어야 함
        items: [
          // label과 icon이 필수
          BottomNavigationBarItem(
              label: "home",
              icon: Icon(Icons.access_alarm_outlined)),
          BottomNavigationBarItem(
              label: "myinfo",
              icon: Icon(Icons.cable)),
        ],
      ),
      body: SafeArea(
        child: Container(color: Colors.green),
      ),
    );
  }
}

2. 상태 관리(지역, 전역)

상태(state) : 변하는 데이터(UI에 동적으로 표현되는 데이터, 사용자의 액션에 따라 변경)

상태 관리 : 계속 변화하는 데이터를 관리 하기 위해서 필요한 것.


상태 관리 왜 필요한가?

기존의 JSP 
 -> 댓글을 작성 후 버튼 클릭후 서버에서 DB에 댓글을 넣고 화면 전체를 리턴

상태관리를 이용
->서버에서 댓글란만 갱신 하는 방법을 선택
-> 개발자들이 노가다 진행
-> 이를 편하게 하기위해 나온 개념이 상태(State)
stateless위젯 : 화면 변경이 안됨
stateful 위젯 : 상태에 따라 화면 변경 됨
stateless위젯 + 상태 라이브러리 : 상태에 따라 화면 변경

라이브러리 위젯(HookWidget) : 라이브러리가 시키는 방법에 따라 진행하면 화면 변경
*중요* 
0. 일반변수(상태가 아닌 변수)는 바뀌더라도 화면이 변하지 않는다.
1. 데이터가 변하면 화면이 변한다.
2. 데이터를 넣어 주는 방식을 기억한다.
2-1 상태주입(HookWidget, MultiProvider)
2=2 상태변경(만든함수 controller.change())
2-3 상태관찰(controller.isChecked)

3. 기능

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

4. 페이지 내에서 화면전환

1. 페이지에 종속된 위젯들을 조건에 맞게 출력

5. 페이지 이동

1. Navigtor를 이용

<전체코드>

<default_page.dart> HookWidget

// 화면을 만들면 가장 먼저 할 것.
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
// serEffect 등이 있다.
// Hook은 build 함수 안에 적는다.

class DefaultPage extends HookWidget {
   DefaultPage({Key? key}) : super(key: key);

  //const 때문에 클래스 단위에서 생성 금지
   // 한 페이지 내에서 화면 전환 방법 (지역)
  // List widgetItems = [
  //   Container(color: Colors.yellow,),
  //   Container(color: Colors.blue,),
  // ];
   
  // 위젯 객체를 만드는 함수를 생성, 메모리 생성 용량 감소
   // SafeArea에 value뒤에 () 붙히기
  //  List widgetItems = [
  //    (color) => Container(color: Colors.yellow,),
  //    () => Container(color: Colors.blue,),
  //  ];

   // 다른 파일에서 페이지 전환 (전역)



   
  Widget build(BuildContext context) {
     final checkController = context.watch<CheckController>();

     List widgetItems = [
           () => DefaultFirstItem(checkController.isChecked),

           () => DefaultSecondItem(),
     ];

     final navlndex = useState(0);

    print("DefaultPage 빌드됨" + navlndex.value.toString());

    //페이지 내에서 변화
    // 빌드에 List를 만들면 빌드변화때만 실행
    // List widgetItems = [
    //
    // ];

    return Scaffold(
      appBar: AppBar(

        // title: Text("나의 정보"),

        // 타이틀 중간 정렬 두가지 방법 (서로 위치 다름),
        // title: Center(child: Text("나의 정보"))는 다른 글자가 들어와도 중간
        title: Center(child: Text("나의 정보")),


        // 다른글자가 들어오면 글자의 공간만큼 밀려남
        // title : Text("가운데정렬"),
        // centerTitle: true,

        actions: [
          // all 은 모든 방향 패딩 only는 한쪽 방향만 설정할 때
          InkWell(
            onTap: (){
              Navigator.push(

                  context, MaterialPageRoute(builder: (context)=>CheckPage()));
            },
            child: Padding(padding: const EdgeInsets.only(right: 30),
             child : Icon(Icons.move_to_inbox),
            ),
          ),
      ],

      ),
      bottomNavigationBar: BottomNavigationBar(
        onTap: (int idx){
          // 버튼 선택시 생성되는 idx를 넣음
          navlndex.value = idx;
        },
        currentIndex: navlndex.value,
        // Items에는 2개 이상의 네비게이션바가 있어야 함
        items: [
          // label과 icon이 필수
          BottomNavigationBarItem(
              label: "home",
              icon: Icon(Icons.access_alarm_outlined)),
          BottomNavigationBarItem(
              label: "myinfo",
              icon: Icon(Icons.cable)),
        ],
      ),
      body: SafeArea(
        // child: Container(color: Colors.green),
        // 빌드될때 마다 화면 전환
        child: widgetItems[navlndex.value](),
      ),
    );
  }
}

<default_first.dart>

import 'package:flutter/material.dart';

class DefaultFirstItem extends StatelessWidget {
  final bool isChecked;

  const DefaultFirstItem(bool this.isChecked, {Key? key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return Container(
      color: Colors.yellow,
      child: Center(
        child: Text("확인 : ${isChecked}"),
      ),
    );
  }
}

<default_second.dart>

import 'package:flutter/material.dart';

class DefaultSecondItem extends StatelessWidget {
  const DefaultSecondItem({Key? key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return Container(color: Colors.blue,);
  }
}

<check_controller.dart>

import 'package:flutter/material.dart';


// 여러 페이지에서 사용하기 위해 따로 파일 분리

class CheckController extends ChangeNotifier{
  // bool의 변수는 보통 is변수 사용
  bool _isChecked = false;

  bool get isChecked => _isChecked;

  //값을 바꿔주는 함수
  void change(){
    // !는 NOT이랑 같음
    _isChecked = !_isChecked;

    // 값을 바꿨는지 알려주는것 (필수)
    notifyListeners();

  }
}

<check_page>

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

  
  Widget build(BuildContext context) {
    // watch : 상태를 계속 관찰 하겠다. (데이터가 바뀌는 것을 관할 할 수 있다.), (context.read + 관찰)
    
    final checkController = context.read<CheckController>();
//   read-> 상태를 한번만 확인하겠다.
//   상태가 바뀌어도 화면에 영향을 끼치지 못함, 상태를 변화 시키는 함수는 사용가능 
//  final checkController = context.watch<CheckController>();


    return Scaffold(
      appBar: AppBar(),
      body: SafeArea(
        child: Center(
          child: Column(
            children: [
              Text("체크페이지"),
              ElevatedButton(
                  onPressed:(){
                    checkController.change();
                  },
                child: Text("값 변경"),
                  ),
            ],
          ),
        ),
      ),
    );
  }
}

<main.dart>

// 위젯을 가져오는 import
import 'dart:js';

import 'package:flutter/material.dart';
import 'package:flutter_hrd_page/default/view/default_page.dart';
import 'package:provider/provider.dart';

import 'check/controller/check_controller.dart';

void main(){
   runApp(
     // MultiProvider는 전역적으로 사용하기 위해 사용
     MultiProvider(
       providers: [
         ChangeNotifierProvider(create: (context) => CheckController()),
       ],
       child: MyApp(),
     ),
   );
}

// stl
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  
  Widget build(BuildContext context) {
    print("메인 빌드됨");
    return MaterialApp(
      //default_page.dart파일에서 DefaultPage() 클래스 가져오기 , import 자동생성
      home: DefaultPage(),
    );
  }
}
profile
풀스택 개발 이야기

0개의 댓글