8단계 전자액자

송기영·2023년 12월 12일
0

플러터

목록 보기
10/25

이미지 5개를 롤링해보여주는 액자 앱을 만든다. 좌우 스와이프해 이미지를 변경할 수 있다.

8.1. 사전지식

8.1.1. 위젯 생명주기

  • StatelessWidget StatelessWidget이 빌그되면 생성자가 실행된다. → 이어서 오버라이드해야 하는 build() 함수가 실행된다. → build() 함수에 반환한 위젯이 화면에 렌더링된다. Widget 클래스는 불변 특성을 가지고 있기때문에 build() 함수에서 매개변수 값을 사용하고 있다면, build() 함수를 재실행해야 하지만 StatlessWidget는 불변이기 때문에 인스턴스를 새로 생성한 후 기존 인스턴스를 대체해서 변경 사항을 화면에 반영한다.
  • StatefulWidget Widget클래스와 State클래스 2개로 구성되어 있고 생명주기가 복잡하다.

상태 변경이 없는 생명주기

  1. StatefulWidget 생성자 실행

  2. createState() 함수 실행

    필수로 오버라이드해야 하는 함수로 StatefulWidget과 연동되는 State를 생성한다

  3. State가 생성되면 initState() 실행

    initState는 State가 생성되는 순간에만 단 한번 실행되고 절대로 다시 실행되지 않는다.

  4. didChangeDependencies() 실행

    BuildContext가 제공되고 State가 의존하는 값이 변경되면 재실행된다.

  5. State의 상태가 dirty로 설정

    dirty상태는 build()가 재실행돼야 하는 상태이다.

  6. build() 함수 실행

    build 함수가 실행되고 UI가 반영된다.

  7. build() 실행이 완료되면 상태가 clean상태로 변경

    화면에 변화가 없으면 이 상태를 유지한다.

  8. 위젯이 위젯 트리에서 사라지면 deacivate() 실행

    deactivate()는 State가 일시적, 영구적으로 살제될 때 실행된다.

  9. dispose() 실행

    위젯이 영구적으로 삭제될 때 실행된다

StatefulWidget 생성자의 매개변수가 변경됐을 때 생명주기

  1. StatefulWidget 생성자 실행
  2. State의 didUpdateWidget() 함수 실행
  3. State가 dirty상태로 변경
  4. build() 함수 실행
  5. State의 상태가 clean으로 변경

State 자체적으로 build()를 재실행할 때 생명주기

State클래스는 setState() 함수를 실행해서 build() 함수를 자체적으로 재실행할 수 있다.

  1. setState() 함수 실행
  2. State가 dirty 상태로 변경
  3. build() 함수 실행
  4. State의 상태가 clean으로 변경

8.1.2. Timer

특정 시간이 지난 후에 일회성 또는 지속적으로 함수를 실행한다.

Timer.periodic(
	Duration(seconds: 3),
	(Timer timer){},
);

생성자는 Timer(), Timer.periodic() 두개가 존재한다.

8.2. 레이아웃 구상

위젯을 좌우로 스와이프할 수 있는 PageView하나로 구성되어있다.

8.3. 구현하기

8.3.1. 페이지뷰 구현하기

// lib/screen/home_screen.dart

import "package:flutter/material.dart";

class HomeScreen extends StatelessWidget {
  const HomeScreen({Key? key}) : super(key: key);
  
  Widget build(BuildContext context) {
    return (Scaffold(
      body: PageView(
        children: [1, 2, 3, 4, 5]
            .map((number) => Image.asset(
                  "asset/img/image_$number.jpeg",
                  fit: BoxFit.cover,
                ))
            .toList(),
      ),
    ));
  }
}

8.3.2. 상태바 색상변경하기

// lib/screen/home_screen.dart

import "package:flutter/material.dart";
import "package:flutter/services.dart";

class HomeScreen extends StatelessWidget {
  const HomeScreen({Key? key}) : super(key: key);
  
  Widget build(BuildContext context) {
    SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.light);
    return (Scaffold(
      body: PageView(
        children: [1, 2, 3, 4, 5]
            .map((number) => Image.asset(
                  "asset/img/image_$number.jpeg",
                  fit: BoxFit.cover,
                ))
            .toList(),
      ),
    ));
  }
}
  • SystemUiOverlayStyle.light


  • SystemUiOverlayStyle.dark

    SystemChrome 클래스는 시스템 UI의 그래픽 설정을 변경하는 기능을 제공한다.

    함수설명
    setEnabledSystemUIMode()앱의 풀스크린 모드를 지정한다. 예를 들어 핸드폰 상단의 시간이나 배터리 잔량이 보이지 않게 가릴 수 있다.
    setPreferredOrientations()앱을 실행하는 방향을 지정한다. (가로, 가로 좌우 반전, 세로, 세로 좌우 반전)
    setSystemUIChangeCallback()시스템 UI가 변경되면 콜백 함수를 실행합니다.
    setSystemUIOverlayStyle()시스템 UI의 색상을 변경합니다.

8.3.3. 타이머 추가하기

일정 기간마다 자동으로 페이지가 변경되는 기능을 추가, StatefulWidget의 initState()를 사용해서 State가 생성될때 딱 한번만 Timer를 생성할 수 있다.

import "package:flutter/material.dart";
import "package:flutter/services.dart";
import "dart:async";

// StatefulWidget 정의
class HomeScreen extends StatefulWidget {
  const HomeScreen({Key? key}) : super(key: key);

  // creatState함수는 state를 반환
  
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  // 조작을 위한 pageController 선언
  final PageController pageController = PageController();

  
  void initState() {
    // 부모 initState() 실행
    super.initState();

    // Timer.periodic() 등록
    Timer.periodic(Duration(seconds: 3), (timer) {
      // 현재 페이지 가져오기
      int? nextPage = pageController.page?.toInt();

      if (nextPage == null) {
        return;
      }

      if (nextPage == 4) {
        nextPage = 0;
      } else {
        nextPage++;
      }
      pageController.animateToPage(nextPage,
          duration: Duration(milliseconds: 500), curve: Curves.ease);
    });
  }

  
  Widget build(BuildContext context) {
    SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.light);

    return (Scaffold(
      body: PageView(
          controller: pageController,
          children: [1, 2, 3, 4, 5]
              .map((number) => Image.asset(
                    "asset/img/image_$number.jpeg",
                    fit: BoxFit.cover,
                  ))
              .toList()),
    ));
  }
}
profile
업무하면서 쌓인 노하우를 정리하는 블로그🚀 풀스택 개발자를 지향하고 있습니다👻

0개의 댓글