본문 바로가기
프로젝트/웹툰 앱 만들기

[웹툰 앱 만들기] 번외: 뽀모도로 앱 만들기

by 두 그루 2023. 5. 7.

뽀모도로 앱을 따라 만들면서 flutter의 statefulWidget과 UI를 공부한 것을 기록한다.

 

강의 참고:

https://nomadcoders.co/flutter-for-beginners/lectures/4154

 

All Courses – 노마드 코더 Nomad Coders

초급부터 고급까지! 니꼬쌤과 함께 풀스택으로 성장하세요!

nomadcoders.co


순서는 크게 아래와 같다.

 

1. 파일 생성 및 UI 설계

2. 타이머 시작 & 정지 기능

3. 뽀모도로 개수 카운터 기능

4. 타이머 포맷 설정

5. 타이머 리셋 기능

 

* 한 뽀모도로를 25분으로 기본 설정하였으나, 디버깅 및 영상 촬영을 위해 5초로 설정하기도 함

 

 

 

1. 파일 생성 및 UI 설계

우선 flutter 프로젝트를 생성하고 main.dart에서 앱의 테마 색을 쉽게 이용하고자 theme을 설정한다. 그리고 화면에 띄울 home screen 파일을 만들고 import하고 화면에 나타낸다.

- main.dart에 ThemeData를 이용해 테마 설정

- Flexible을 이용해 비율대로 화면에 요소 나타내기(타이머: 1, 버튼: 2, 뽀모도로 개수: 1)

- Expanded를 이용해 화면 크기만큼 채운 박스로 요소 나타내기

 

https://github.com/soaringwave/Flutter-studying/commit/66699bd0116e1f8f51997f49435b85a2f2d5fa20

 

 

 

2. 타이머 시작 & 정지 기능

[시작]

- 1500(초) 정수 값을 가진 totalTimer 정의

- IconButton을 눌렀을 때 1초마다 onTick 함수를 실행하여 totalTime의 값이 1씩 감소

- 이를 setState를 이용해 화면에 표현

  int totalTime = 1500;
  late Timer timer;

  void onTick(Timer timer) {
    setState(() {
      totalTime = totalTime - 1;
    });
  }

  void onStartPressed() {
    timer = Timer.periodic(
      const Duration(seconds: 1),
      onTick,
    );
  }

https://github.com/soaringwave/Flutter-studying/commit/6a35caf1ca020f025bea9ea7f6fea97f48c37007

 

[정지]

- bool 값을 가진 isRunning 변수를 이용하여 타이머의 동작여부 파악

- isRunning 값에 따라 play, pause IconButton을 화면에 보이고 각각 onStartPressed, onPausePressed 함수 실행하기

- pause IconButton을 누르면 진행하던 timer 종료 후 isRunning 상태를 false로 설정

bool isRunning = false;

  void onPausePressd() {
    timer.cancel();
    setState(() {
      isRunning = false;
    });
  }


// ...
		IconButton(
                  iconSize: 120,
                  color: Theme.of(context).cardColor,
                  icon: const Icon(Icons.play_circle_filled_sharp),
                  onPressed: onStartPressed,
                  icon: Icon(isRunning
                      ? Icons.pause_circle_filled_rounded
                      : Icons.play_circle_filled_rounded),
                  onPressed: isRunning ? onPausePressd : onStartPressed,
                ),
// ...

https://github.com/soaringwave/Flutter-studying/commit/74c945d03c33dd2a06ba59d91dd401991af13af7

 

 

 

3. 뽀모도로 개수 카운터 기능

- totalPomodoros 변수의 값을 0으로 초기화

- 뽀모도로 타이머 시간이 종료되면(0이 되면) 총 뽀모도로 개수를 하나 추가하고 타이머는 25분으로 다시 초기화

  int totalPomodoros = 0;
  
  
  void onTick(Timer timer) {
    if (totalTime == 0) {
      setState(() {
        totalPomodoros = totalPomodoros + 1;
        isRunning = false;
        totalTime = 1500;
      });
      timer.cancel();
    } else {
      setState(() {
        totalTime = totalTime - 1;
      });
    }
  }

https://github.com/soaringwave/Flutter-studying/commit/8c9a9dc84fddfa4bef83a7b787a7cba7a1619bc6

 

 

 

4. 타이머 포맷 설정

- 초를 나타내는 정수 값을 인수로 받으면 'nn:nn' 문자열을 반환하는 timeFormat 함수 정의

- Duration을 이용하여 시간을 문자열으로 변환

  String timeFormat(int seconds) {
    String duration = Duration(seconds: seconds).toString();
    return duration.substring(2, 7);
  }

// ...
	Text(
                timeFormat(totalTime),
                style: TextStyle(
                  color: Theme.of(context).cardColor,
                  fontSize: 90,
                  fontWeight: FontWeight.w600,
                ),
              ),
// ...

 

+ 문자열 format 참고

https://github.com/soaringwave/Flutter-studying/commit/bd46933a635a0a609e9692d30e22f0a5c01b2852

 

 

 

5. 타이머 리셋 기능

코드 챌린지로 타이머 리셋 기능을 추가했다. play 버튼 아래의 stop 버튼을 클릭하면 타이머가 초기화된다.

  void onRestartPressed() {
    timer.cancel();
    setState(() {
      totalTime = twentyFiveMin;
      isRunning = false;
    });
  }
  
 // ...
  		    const SizedBox(
                      height: 30,
                    ),
                    IconButton(
                      iconSize: 60,
                      color: Theme.of(context).cardColor,
                      icon: const Icon(Icons.stop_circle_outlined),
                      onPressed: onRestartPressed,
                    ),
// ...

https://github.com/soaringwave/Flutter-studying/commit/90ab80152f49aa526c156e18fd7363c77aef776b

 

결과

 

댓글