UI 작성

시작 / 일시정지 버튼 영역 UI 작성하기

  • bottomNavigationBar : 어떤 위젯도 배치할 수 있음

타이머 영역 UI 작성

  • Positioned

 

 


타이머 구현하기

  • Duration 클래스 주기

 

 

 

타이머 클래스와 필요한 변수들

 

시작 / 일시정지 /초기화 기능

 

시간표시하기

  •  ~/ 몫을 구하는 연산자,   초 부분 구하기
  • 1/100초 구하기 (00~99 표현하기)

 


 

랩타임 기록하기

 

랩타임 표시하기

 

 

전체코드⬇︎

더보기

 

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


void main() => runApp(MyApp());

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'StopWatch',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),

      home: StopWatchPage(),
    );
  }
}


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

  @override
  _StopWatchPageState createState() => _StopWatchPageState();
}

class _StopWatchPageState extends State<StopWatchPage> {

  Timer _timer;  // 타이머 선언

  var _time = 0;    // 0.01초마다 1씩 증가시킬 정수형 변수
  var _isRunning = false;   // 현재 시각 상태를 나타낼 변수 (타이머 시작하거나 멈추기 위함)

  List<String> _lapTimes = [];  // 랩타임에 표시할 시간을 저장할 리스트

  @override
  void dispose(){
    _timer?.cancel();  // 앱화면이 종료되면 타이머가 취소됨
    // ?. 는 타이머를 한 번도 동작시키지 않았을 때도(null인 상태) 안전하게 동작을 취소하기 위해 사용

    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('스탑워치!~'),
      ),

      body: _buildBody(),

      bottomNavigationBar: BottomAppBar(
        child: Container(
          height: 50.0,
        ),
      ),

      // ↱ _clickButton() 메서드가 실행됨
      floatingActionButton: FloatingActionButton(
        onPressed: () => setState((){
          _clickButton();
        }),

        // ↱_isRunning이  true인 경우면(스탑워치 진행중) pause아이콘 보여지고,  false면 시작 아이콘 보여짐
        child: _isRunning ? Icon(Icons.pause) : Icon(Icons.play_arrow),
      ),

      // ↱floatingActionButton 위젯의 위치를 지정
      floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
    );
  }

  // 내용 부분
  Widget _buildBody(){

    // 초 부분과, 1/100초 부분을 분리하여 계산하기
    // ↱ _time 변수는 _start() 메서드로 인해 시간을 1/100초 단위로 저장함->
    //   이 것을 100을 나눌경우 몫이 초가 됨, 그리고 나머지가  1/100초 단위가 됨
    var sec = _time ~/ 100;  // " ~/ " 는 몫을 구하는 연산자이다.

    // 1/100 표현하기   ↱ 나머지 구하기  ↱ 문자열을 2자리로, 왼쪽의 빈곳을 0으로 채워 넣음
   var hundredth = '${_time % 100}'.padLeft(2, '0');

    return Center(
      child: Padding(
        padding: const EdgeInsets.only(top: 30),

        child: Stack(
          children: <Widget>[
            Column(
              children: <Widget>[
                // 시간 표시하는 영역
                Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment: CrossAxisAlignment.end,
                  children: <Widget>[
                    Text( // 초
                      '$sec',
                      style: TextStyle(fontSize: 50.0),
                    ),
                    Text('$hundredth'),  //  1/100초
                  ],
                ),

                // 랩타임을 표시하는 영역
                Container(
                  width: 100,
                  height: 200,
                  child: ListView(
                    //        _lapTimes리스트를 -> map을 이용해 각각 Text 형태로 변환 후 -> 다시 리스트 형태로 반환
                    children: _lapTimes.map((t) => Text(t)).toList(),
                  ),
                ),
              ],
            ),

            // 초기화 버튼 (왼쪽 아래에 위치시키기 위해 Positioned 위젯으로 감쌈)
            Positioned(
              left: 10,
              bottom: 10,
              child: FloatingActionButton(
                backgroundColor: Colors.deepOrange,
                onPressed: _reset,  // 리셋 메서드 실행
                child: Icon(Icons.rotate_left),
              ),
            ),

            // 랩타임 버튼
            Positioned(
              right: 10,
              bottom: 10,
              child: ElevatedButton(
                onPressed: (){
                  setState(() {
                    //              ↱ x.xx 형태로 연결하여 전달
                    _recordLapTime('$sec.$hundredth');
                  });
                },
                child: Text('랩타임'),
              ),
            ),
          ],
        ),
      ),
    );
  }

  // 시작 또는 일시정지 버튼 클릭
  void _clickButton(){
    _isRunning = !_isRunning;  // 클릭할 때마다 boolean 값 변경

    if(_isRunning){
      _start();
    }else{
      _pause();
    }
  }


  // Timer 객체를 초기화하고 0.01초에 한 번씩 반복하게 하기
  void _start(){
    // 첫 번째 인수 Duration 인수를 설정하면 -> 두 번째 인수로 받은 함수에서 실행됨
    //                                   ↱0.01초
    _timer = Timer.periodic(Duration(milliseconds: 10), (timer) {
      setState(() {
        _time++; // 0.01초마다 _time변수의 값을 1씩 증가 시킴
      });
    });
  }

  // 타이머 일시정지하기
  void _pause(){
    _timer?.cancel();
  }

  // 초기화
  void _reset(){
    setState(() {
      _isRunning = false;
      _timer?.cancel();
      _lapTimes.clear();
      _time = 0;
    });
  }


  // 랩타임 기록하기
  void _recordLapTime(String time){
    //               ↱_lapTimes 리스트의 맨 앞에 추가하기
    _lapTimes.insert(0, '스탑워치 ${_lapTimes.length +1} 번째 실행 $time');
  }

}

+ Recent posts