본문 바로가기

책/오준석의 안드로이드 생존코딩 코틀린편

6. 스톱워치

프로젝트명 StopWatch
기능
  • 타이머를 시작, 일시정지하고 초기화 할 수 있다.
  • 타이머 실행 중에 랩타임을 측정하여 표시한다.
핵심 구성요소
  • timer : 일정 시간 간격으로 백그라운드 스레드에서 실행한다.
  • runOnUiThread : 메인 스레드에서 UI를 갱신한다.
  • ScrollView : 랩타임을 표시할 때 상하로 스크롤되는 뷰를 사용한다.
  • FloatingActionButton : 머티리얼 디자인의 둥근 모양의 버튼이다.
라이브러리 설정
  • 백터드로어블 하위 호환 설정 : 안드로이드 5.0 미만에서 벡터 드러어블을 지원하는 라이브러리
  • design 라이브러리 : FloatingActionButton 등 머티리얼 디자인을 제공하는 라이브러리
  1. 준비하기 : 프로젝트 생성 및 안드로이드 설정
  2. 스텝1 : 화면 작성
  3. 스텝2 : 타이머 구현하기
  4. 스텝3 : 랩 타임 기록하기

준비하기

./build.gradle 파일에 백터드로어블 하위 호환설정 추가

android {
....
    defaultConfig {
....
        vectorDrawables.useSupportLibrary = true
    }
....
}

스텝1 화면 작성

  1. 시간을 표시하는 TextView 배치
  2. TextView 정렬
  3. 벡터 이미지 준비
  4. FloatingActionButton 소개
  5. 타이머 시작 용 FloatingActionButton 작성
  6. 타이머 초기화 용 FloatingActionButton 작성
  7. 랩 타임 기록을 위한 버튼 배치
  8. 랩 타임 표시하는 ScrollView 배치

시간을 표시하는 TextView 배치

초를 표시할 텍스트 뷰의 설정

배치 Autoconnect 모드로 TextView를 레이아웃의 정중앙에 배치
ID secTextView
text 0
textSize 100sp
textAppearence AppCompact.Large
뷰의 위치를 10%로 지정

 

밀리초를 표시할 텍스트 뷰의 설정

배치 초를 표시하는 뷰의 오른쪽 지점에 적당히 배치
ID millTextView
text 00
textSize 22sp
textAppearence AppCompact.Large
두 텍스트의 정렬
좌측 여백 제약 추가

벡터 이미지 준비

프로젝트 창에서 res 폴더에서 마우스 우클릭 -> New -> Vector Asset 을 클릭하여 다음 이미지를 준비한다.

타이머 시작용 FloatingActionButton 작성

./app/build.gradle 에 design 라이브러리가 추가 되었는지 확인

dependencies {
....
    implementation 'com.google.android.material:material:1.1.0'
....
}
배치 Autoconnect 모드로 FloatingActionButton을 레이아웃의 아래 가로중앙에 배치
버튼 이미지
srcCompat
ic_baseline_play_arrow_24
backgroundTint colorPrimary 로 변경
tint Coror -> android -> white 선택
ID fab
하단 여백 16
좌우 여백 0

타이머 초기화용 FloatingActionButton 작성

배치 Autoconnect 모드로 FloatingActionButton을 레이아웃의 아래 좌측에 배치
버튼 이미지
srcCompat
ic_baseline_refresh_24
tint Coror -> android -> white 선택
ID resetFab
왼쪽, 아래 여백 16

랩 타임을 기록하는 버튼 배치

배치 Button을 레이아웃의 아래 우측에 배치
ID lapButton
오른쪽, 아래 여백 16
text 랩타임

랩 타임을 표시하는 ScrollView 배치

배치 secTextView 와 fab 사이에 배치
내부 LinearLayout(vertical) 의 ID 

lapLayourt
layout_width wrap_content
layout_height match_constraint ( 0dp )
위,아래 여백 8

스텝2 타이머 구현하기

timer 사용방법

안드로이드 워크 스레드에서는 UI를 조작할 수 없고 메인 스레드에서만 조작이 가능하다 따라서 워커 스레드 내에서 runOnUiThread 메서드를 사용하여 UI조작을 하여야 한다.

timer(period = 1000) {
    //오래 걸리는 작업
    runOnUiThread {
        // UI 조작
    }
}

타이머 시작, 멈춤, 이벤트 연결

package abstractask.example.stopwatch

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*
import java.util.*
import kotlin.concurrent.timer

class MainActivity : AppCompatActivity() {

    private var time = 0
    private var isRunning = false
    private var timerTask: Timer? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        fab.setOnClickListener{
            isRunning = !isRunning

            if(isRunning) {
                start()
            } else {
                pause()
            }

        }
    }
    private fun start() {
        fab.setImageResource(R.drawable.ic_baseline_pause_24)

        timerTask = timer(period = 10) {
            time++
            val sec = time / 100
            val milli = time % 100
            runOnUiThread {
                secTextView.text = "$sec"
                millTextView.text = "$milli"
            }
        }
    }
    private fun pause() {
        fab.setImageResource(R.drawable.ic_baseline_play_arrow_24)
        timerTask?.cancel()
    }
}

스텝3 랩 타임 기록 하기

랩 타임을 표시하기

class MainActivity : AppCompatActivity() {

    private var time = 0
    private var isRunning = false
    private var timerTask: Timer? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        //....
        
        lapButton.setOnClickListener {
            recordLapTime()
        }
    }
    
    //....
    
    private var lap = 1
    private fun recordLapTime() {
        var lapTime = this.time
        val textView = TextView(this)
        textView.text = "$lap LAB : ${lapTime / 100}.${lapTime % 100}"

        // 맨 위에 랩타임 추가
        lapLayout.addView(textView, 0)
        lap++
    }
}

타이머 초기화 구현

class MainActivity : AppCompatActivity() {

    private var time = 0
    private var isRunning = false
    private var timerTask: Timer? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        //....
        
        resetFab.setOnClickListener {
            reset()
        }
    }
    
    //....
    
    private fun reset() {
        timerTask?.cancel()

        //모든 변수 초기화
        time = 0
        isRunning = false
        fab.setImageResource(R.drawable.ic_baseline_play_arrow_24)
        secTextView.text = "0"
        millTextView.text = "00"

        // 모든 랩타임 제거
        lapLayout.removeAllViews()
        lap = 1
    }
}

결과화면 

' > 오준석의 안드로이드 생존코딩 코틀린편' 카테고리의 다른 글

8. 수평 측정기  (0) 2020.06.16
7. 나만의 웹 브라우저  (0) 2020.06.15
5. 비만도 계산기  (0) 2020.06.09
4. 코틀린  (0) 2020.06.08
3. 첫 번째 앱 만들기  (0) 2020.06.07