외로운 Nova의 작업실

Flutter 프로그래밍 - 5(전자액자 만들기) 본문

Programming/Flutter

Flutter 프로그래밍 - 5(전자액자 만들기)

Nova_ 2024. 1. 7. 17:31

안녕하세요, 이번장에서는 flutter로 전자액자를 3초마다 옆으로 넘어가고 옆으로 슬라이드하면 넘어가는 액자로 총 5개의 사진을 넣어서 만들어보도록 하겠습니다. 사전지식을 익히고 바로 만들어보겠습니다.

 

- 사전 지식

위젯 생명주기는 위젯이 화면에 그려지는 순간부터 삭제되는 순간까지의 주기를 의미합니다. 플러터에서 UI를 표현할때 사용되는 대표적인 위젯인 StatlessWidget과 StatefulWidget의 생명주기를 알아보겠습니다.

 

<StatelessWidget>

상태가 없는 위젯으로 화면 변경이 안됩니다. 따라서 생명주기는 간단합니다.

스테이트리스 위젯은 불변이기 떄문에 한번 생성된 인스턴스의 build() 함수는 재실행되지 않습니다. 대신 인스턴스를 아예 새로 생성한 기존 인스턴스를 대체해서 변경 사항을 화면에 반영합니다.

 

<StatefulWidget>

스테이트풀위젯은 외부에서 위젯 생성자의 매개변수를 변경해주면 위젯이 새롭게 생성되고 State 자체적으로 build()를 실행시킬 수 있습니다.

 

매개변수를 변경하게되면 didUpdateWidget() 함수가 실행됩니다. 한번 생명주기를 보면 아래와 같습니다.

 

createState()함수는 필수로 오버라이드해야하는 함수로 StatefulWidge과 연동되는 State를 생성합니다. State가 생성되면 initState()가 실행되며 initState()는 State가 생성되는 순간에만 단 한번 실행되고 절대 실행되지 않습니다.

 

State 자체적으로 build()를 재실행하는 경우는 setState()함수로 재실행하는 경우입니다. 한번 생명주기를 보면 아래와같습니다.

 

- 사전 준비

먼저 프로젝트를 만들고 파일들을 업로드해주겠습니다.

asset에 이미지파일 5개를 넣어줍니다.

 

- pubspec.yaml 설정

아재 추가된 에셋을 등록해주겠습니다.

 

- 프로젝트 초기화

이제 screen 폴더를 생성하고 기본 위젯으로 home_screen.dart를 생성해주겠습니다.

import 'package:flutter/material.dart';

class HomeScreen extends StatelessWidget {
  const HomeScreen({Key? key}) : super(key: key);
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Text('Home Screen'),
    );
  }
}

 

아래는 main.dart입니다.

import 'package:flutter/material.dart';
import 'package:image_carousel/screen/home_screen.dart';

void main() {
  runApp(
    MaterialApp(
      home: HomeScreen(),
    )
  );
}

 

- 페이지뷰 만들기

pageview는 여러개의 위젯을 독단적인 페이지로 생성하고 가로 또는 세로 스와이프로 페이지를 넘길 수 있게하는 위젯입니다. 아래는 Home_Screen.dart입니다.

import 'package:flutter/material.dart';

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: PageView(
        children: [1, 2, 3, 4, 5]
        .map(
            (number) => Image.asset('asset/img/image_$number.jpeg'),
        )
        .toList(),
      ),
    );
  }
}

 

이렇게하면 map함수가 children에서 숫자를 가져와서 그 숫자를 사용해서 Image 위젯으로 매핑해줍니다. 따라서 children에는 위젯 리스트가 만들어집니다. 한번 실행해보겠습니다.

 

 

잘 나오고있습니다. 하지만 여백이 보여서 액자로서 보기어렵습니다. 따라서 BoxFit.Cover를 설정해주면 이미지가 최대한 전체 화면을 차지하도록 늘어납니다.

import 'package:flutter/material.dart';

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

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

 

전체화면으로 꽉 찬것을 확인할 수 있습니다.

 

- 타이머 추가하기

이제 타이머를 추가할텐데, HomeScreen 웨짓을 StatefulWidget으로 변경해야 Timer를 사용할 수 있습니다. 또한, buid()함수에 Timer를 생성하면 build()함수가 불릴때마다 매번 새로운 Timer가 생성됩니다. 그러면 메모리 릭이 생기니 initState()함수에 Timer를 생성해주겠습니다. TIme는 dart:async를 임포트해줘야합니다.

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

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

  @override //필수 오버라이딩
  State<HomeScreen> createState() => _HomeScreenState();

}

//실제 state 클래스
class _HomeScreenState extends State<HomeScreen> {

  @override
  void initState(){
    super.initState();

    Timer.periodic(
      Duration(seconds: 3),
        (timer){
        print('실행!');
        }
    );
  }

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

 

 

- Timer에 다른 페이지 변경

이제 Timer에 람다함수로 페이지를 변경하는 코드를 넣어보겠습니다.

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

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

  @override
  State<HomeScreen> createState() => _HomeScreenState();

}

class _HomeScreenState extends State<HomeScreen> {
  
  final PageController pageController = PageController();

  @override
  void initState(){
    super.initState();

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

  @override
  Widget build(BuildContext context) {
    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(),
      ),
    );
  }
}

 

이제 실행시켜보면 액자처럼 저절로 넘어가는 것을 확인할 수 있습니다.

Comments