[Flutter] 이미지 자동 슬라이드 프로젝트(PageView,Timer)

2022. 10. 22. 15:35프로그래밍 언어/Flutter

완성본 : 플러터 프로젝트 - 전자액자

출처: https://www.inflearn.com/course/%ED%94%8C%EB%9F%AC%ED%84%B0-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8/unit/106196

 

이미지 5개 슬라이드로 보는 프로젝트인데,

PageView 를 이용해 슬라이드하는 기능을 구현하고, 

1.스마트폰 전체 fit 에 맞추는 법

2. List 로 중복제거 하는법 

3. Timer 사용법

4. Controller 로 이미지 넘기기

5. 상단 배너 (시계,배터리잔량) 색 변경 

알려드림.

 

0. 이미지 슬라이드 위젯 

PageView(
	children:[
    	Image.asset(이미지 위치),
        ...
    ])

이미지들을 넣어놓으면 수동 슬라이드가 가능하다.  

 

1. 스마트폰 전체 fit 에 맞추는 법

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: [
          Image.asset(
          'asset/img/image_1.jpeg',
          fit: BoxFit.cover,
        ),
          Image.asset('asset/img/image_2.jpeg'),
          Image.asset('asset/img/image_3.jpeg'),
          Image.asset('asset/img/image_4.jpeg'),
          Image.asset('asset/img/image_5.jpeg'),
        ],
      )
    );
  }
}

결과 

좌: 다 찬거 / 우 : 사진 사이즈만큼 

2. List 로 중복제거 하는법  : map.toList() 

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

 

3. Timer 사용법

Timer 함수를 사용하면, 시간지날때마다 동작을 하게 만들수있다.

아래는

1초마다 'Timer!' 를 출력하는 코드

메모리를 계속 잡아 먹을 수있으니, dispose에서 Timer를 꼭 제거해줄것!

 

참고: initState() 를하고 저장해도 Timer 적용안된다.

이유는 initState는 State 실행시 최초 1회가 이미 실행되었기 때문이다.

restart 해야 initState가 재 호출된다. 

 

import 'dart:async'; // async 에서 가져온다. 

class _HomeScreenState extends State<HomeScreen> {
  Timer? timer; // Timer 선언 null 일수도 있음.

  @override
  void initState() {
    super.initState();
    
    timer = Timer.periodic(Duration(seconds: 1), (timer) { // Timer 동작
      print('Timer!');
    });
  }
@override
  void dispose() {
  if(timer != null){ // 계속 실행되면 메모리를 많이 잡아먹을 수 있으니 dispose 에서 timer를 없애준다.
    timer!.cancel();
  }
    super.dispose();
  }

 

4. Controller 로 이미지 넘기기


1) Pagecontroller 선언  

  PageController controller = PageController( // controller 선언
    initialPage: 0, // 몇번째 page 부터 시작할래
  );
  
  int currentPage = controller.page!.toInt(); //현재 화면

controller 의 page 타입은 double? 다.

1) ? 가 붙은 이유: controller 가 선언만 돼있고, PageView 에 정의되있지 않으면 

page를 알수 없기 떄문이다.

2) double 인 이유: 반만 돌아가면 0.5 이기 때문이다.

2) 특정 페이지로 넘기는 함수:  animateToPage()

 controller.animateToPage(
          nextPage, // 다음페이지로 넘겨.
          duration: Duration(milliseconds: 400), // 이동하는 속도
          curve: Curves.linear // 동일한 속도
      );

3) PageView 에 controller로 선언  

 body: PageView(
          controller: controller, //controller 로 PageVIew 조정 가능

4) controller 도 메모리를 위해 dispose 필요

 void dispose() {
    controller.dispose();
 }

 

완성 코드

class _HomeScreenState extends State<HomeScreen> {
  Timer? timer;
  PageController controller = PageController( // controller 선언
    initialPage: 0, // 몇번째 page 부터 시작할래
  );

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

    timer = Timer.periodic(Duration(seconds: 4), (timer) {
      int currentPage = controller.page!.toInt(); //현재 화면
      int nextPage = currentPage + 1; // 다음 화면

      if (nextPage > 4) { // page 끝에 도달시 첫화면으로 돌아감.
        nextPage = 0;
      }
      controller.animateToPage(
          nextPage, // 다음페이지로 넘겨.
          duration: Duration(milliseconds: 400), // 이동하는 속도
          curve: Curves.linear // 동일한 속도
      );
    });
  }

  @override
  void dispose() {
    controller.dispose();
    if (timer != null) {
      timer!.cancel();
    }
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: PageView(
          controller: controller, //controller 로 PageVIew 조정 가능
          children: [1, 2, 3, 4, 5].map((e) =>
              Image.asset(
                'asset/img/image_$e.jpeg',
                fit: BoxFit.cover,)
          ).toList(),
        )
    );
  }
}

5. 상단 배너 (시계,배터리잔량) 색 변경 

 

  @override
  Widget build(BuildContext context) {
    SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.dark); //상단 배너 색 
    
  }

좌: 기본 / 우: dark 적용