Flutter – image carousel (토이 프로젝트)

  • 주요 스택
    • PageView(스와이프 좌우 스크롤)
    • Timer (특정 기간마다 콜백함수 실행)
    • StatefulWidget
    • Life Cycle

PageView (이미지 스크롤)

import 'package:flutter/material.dart';

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

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

class _HomeScreenState extends State<HomeScreen> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: PageView(
        // PageView 로 감싸면 이 자체에서 바로 swipe 가 가능하다
        children: [
          Image.asset(
            'asset/img/image_1.jpeg',
            fit: BoxFit.cover, // 전체 꽉찬 화면 (비율대로 늘어나므로 화면이 짤릴 수 있다)
          ),
          Image.asset(
            'asset/img/image_2.jpeg',
            fit: BoxFit.cover,
          ),
          Image.asset(
            'asset/img/image_3.jpeg',
            fit: BoxFit.cover,
          ),
          Image.asset(
            'asset/img/image_4.jpeg',
            fit: BoxFit.cover,
          ),
          Image.asset(
            'asset/img/image_5.jpeg',
            fit: BoxFit.cover,
          ),
        ],
      ),
    );
  }
}

코드 정리

반복되는 코드 정리 !

import 'package:flutter/material.dart';

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

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

class _HomeScreenState extends State<HomeScreen> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: PageView(
        children: [1, 2, 3, 4, 5].map(
          (e) => Image.asset(
            'asset/img/image_$e.jpeg',
            fit: BoxFit.cover,
          ),
        ).toList(),
      ),
    );
  }
}

Timer 이용하여 자동으로 스크롤 되게

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

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

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

class _HomeScreenState extends State<HomeScreen> {
  // Timer 선언
  Timer? timer;
  PageController controller = PageController(
    initialPage: 0,
  );

  @override
  void initState() {
    timer = Timer.periodic(Duration(seconds: 3), (timer) {
      int currentPage = controller.page!.toInt(); // page 는 double? 임. null 이 될 수 있고, 이미지가 넘어갈때는 page 번호가 소수점이 될 수 있으므로
      int nextPage = currentPage + 1;

      if (nextPage > 4) {
        // 이미지가 5개 이므로, 0번 인덱스로 돌려줌
        nextPage = 0;
      }

      controller.animateToPage(
        nextPage,
        duration: Duration(milliseconds: 400),
        curve: Curves.linear,
      );
    });
  }

  @override
  void dispose() {
    controller.dispose(); // 선언한 controller 들도 모두 메모리 관리를 위해 dispose처리
    if (timer != null) {
      timer!.cancel(); // timer 멈춤 (timer가 백그라운드에서 계속 돌아가는건 좋지 않으므로, HomeScreen state가 사라질때 메모리 초기화를 위해 timer dispose)
    }
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.light); // 최상단 휴대폰 상태바 color 를 변경해줄 수 있음.
    return Scaffold(
      body: PageView(
        controller: controller, // 생성한 controller 주입
        children: [1, 2, 3, 4, 5]
            .map(
              (e) => Image.asset(
                'asset/img/image_$e.jpeg',
                fit: BoxFit.cover,
              ),
            )
            .toList(), // map 은 iterable 을 return 해주는데 children 는 List[] 로 전달해야함
      ),
    );
  }
}