반응형
Key Points
- Timer 클래스
: 비동기 방식(요청을 보냈을 때 응답과 상관없이 다음 동작 수행가능). Timer 클래스는 앱을 종료할 때 동작을 취소해줘야 하기 때문에 dispose() 메소드가 꼭 필요합니다.. 아니면 백그라운드에서 계속해서 돌아갑니다.
- setState()
: state에서 무언가 변화가 일어났음을 알려주는 함수. setState()를 통해서 UI가 변경될 수 있게 다시 build됩니다. 또한 StatefulWidget에서 상태 변경을 나타내기 위해 가장 많이 사용합니다.
- Map()
: Map 함수는 iterable한 값을 가공하여, iterable로 반환하는 함수인데, forEach 함수는 단순 루프인것에 반해 Map함수는 반환 값이 존재합니다.
import 'package:flutter/material.dart';
import 'dart:async';
class Stopwatch extends StatefulWidget {
const Stopwatch({Key? key}) : super(key: key);
@override
_StopwatchState createState() => _StopwatchState();
}
class _StopwatchState extends State<Stopwatch> {
late Timer _timer; // 타이머 선언
var _time = 0; // 변수 선언
var _isRunning = false; // 시작 상태 확인
List<String> _lapTimes = []; // laptime을 기록할 리스트 생성
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('StopWatch'),
backgroundColor: Colors.lightGreen,
),
body: _buildBody(),
bottomNavigationBar: BottomAppBar(
child: Container(
height: 50,
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => setState(() {
_clickButton();
}),
child: _isRunning ? Icon(Icons.pause) : Icon(Icons.play_arrow),
backgroundColor: Colors.lightGreen, // 시작 상태를 확인하면 버튼 변경
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
);
}
Widget _buildBody() {
// 초를 계산하는 위젯
var sec = _time ~/ 100; // 초
var hundredth = '${_time % 100}'.padLeft(2, '0'); // 1/100초
return Container(
child: Padding(
padding: const EdgeInsets.only(top: 30),
child: Stack(
// Stack 위젯을 사용하여 여러 위젯을 겹치게 사용
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text(
'$sec',
style: TextStyle(fontSize: 50),
),
Text('$hundredth'),
],
),
SizedBox(
height: 30,
),
Container(
width: 30,
height: 200,
child: ListView(
children:
_lapTimes.map((time) => Text(time)).toList(),
// 리스트의 값을 text로 바꾸고, 다시 List로 변환
))
],
),
Positioned(
left: 10,
bottom: 10,
child: FloatingActionButton(
backgroundColor: Colors.deepOrange,
onPressed: _reset,
child: Icon(Icons.rotate_left),
)),
Positioned(
right: 10,
bottom: 10,
child: RaisedButton(
onPressed: () {
setState(() {
_recordLapTime('$sec.$hundredth');
});
},
child: Text('Lab'),
))
],
)));
}
void _clickButton() {
// 시작 버튼
_isRunning = !_isRunning;
if (_isRunning) {
// _isRunning의 값에 따라서 _start(),_pause() 실행
_start();
} else {
_pause();
}
}
void _start() {
// 시작
_timer = Timer.periodic(Duration(milliseconds: 10), (timer) {
// Duration()을 사용하여, 1/100초에 한번씩 1 증가
setState(() {
_time++;
});
});
}
void _pause() {
// 멈춤
_timer?.cancel();
}
void _reset() {
// 초기화
setState(() {
_isRunning = false;
_timer?.cancel();
_lapTimes.clear();
_time = 0;
});
}
@override
void dispose() {
// Controller 객체가 제거될 때 변수에 할당된 메모리를 해제하기 위해 dispose 메소드 사용
_timer?.cancel();
super.dispose();
}
void _recordLapTime(String time) {
// 랩타임
_lapTimes.insert(0, '$time');
}
}
반응형
'Flutter' 카테고리의 다른 글
[flutter] W/System: Ignoring header X-Firebase-Locale because its value was null (0) | 2022.07.18 |
---|---|
[flutter] Firebase has not been correctly initialized (0) | 2022.07.13 |
[Flutter] Validation (0) | 2022.06.28 |
[Flutter] Date Picker & Time Picker (0) | 2022.06.23 |
[Flutter] 비만도 테스트(BMI Test) (0) | 2022.06.22 |