StopWatch 에 들어간 클래스/위젯
class, component on the StopWatch
- Timer
- TextView. Button
- ScrollView



activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" android:id="@+id/secTextView" android:textSize="100sp"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
app:layout_constraintVertical_bias="0.100000024"/>
<TextView
android:text="00"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/milliTextView"
android:textAppearance="@style/TextAppearance.AppCompat.Large" app:fontFamily="sans-serif-black"
app:layout_constraintStart_toEndOf="@+id/secTextView" android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
app:layout_constraintBaseline_toBaselineOf="@+id/secTextView"/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true" app:srcCompat="@drawable/ic_play_arrow_black_24dp"
android:id="@+id/fab" app:backgroundTint="@color/colorPrimary"
app:layout_constraintBottom_toBottomOf="parent" android:layout_marginBottom="16dp"
android:tint="@android:color/white" tools:srcCompat="@drawable/ic_play_arrow_black_24dp"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent"/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true" app:srcCompat="@drawable/ic_refresh_black_24dp"
android:id="@+id/resetFab" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent" android:layout_marginBottom="16dp"
android:layout_marginLeft="16dp" android:layout_marginStart="16dp" app:backgroundTint="#E91E63"
android:tint="@android:color/white"/>
<Button
android:text="랩 타임 "
android:layout_width="93dp"
android:layout_height="55dp"
android:id="@+id/lapButton"
app:layout_constraintBottom_toBottomOf="parent" android:layout_marginBottom="16dp"
app:layout_constraintEnd_toEndOf="parent" android:layout_marginEnd="16dp"
android:layout_marginRight="16dp" android:textAppearance="@style/TextAppearance.AppCompat.Medium"/>
<ScrollView
android:layout_width="wrap_content"
android:layout_height="0dp" android:layout_marginTop="8dp"
app:layout_constraintTop_toBottomOf="@+id/secTextView" android:layout_marginBottom="8dp"
app:layout_constraintBottom_toTopOf="@+id/fab" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:id="@+id/scrollView2">
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content"
android:orientation="vertical" android:id="@+id/lapLayout"/>
</ScrollView>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true" app:srcCompat="@drawable/ic_clear_black_24dp"
android:id="@+id/clear"
android:tint="@android:color/white" app:backgroundTint="@color/design_default_color_primary"
android:visibility="invisible" android:layout_marginBottom="8dp"
app:layout_constraintBottom_toTopOf="@+id/resetFab" app:layout_constraintStart_toStartOf="parent"
android:layout_marginLeft="16dp" android:layout_marginStart="16dp"/>
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.kt
package com.example.stop_watch
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.TextView
import android.widget.Toast
import androidx.core.view.isVisible
import kotlinx.android.synthetic.main.activity_main.*
import java.util.*
import kotlin.concurrent.timer
class MainActivity : AppCompatActivity() {
private var time=0 // 0.01초마다 1씩 오르는 변수
private var isRunning=false // 스톱워치 실행이 되면 true가 됨
private var timerTask: Timer?=null // Timer객체를 가리키는 참조변수
private var lap=1 // 저장이 몇 개 됐는지 알리는 변수
private var lastTimeBackPressed:Long=-1500 // 이전에 버튼을 눌렀을 때 시간
private fun start(){
clear.isVisible=false // 외관상 좋게 보이기 위해 x버튼 감추기
fab.setImageResource(R.drawable.ic_pause_black_24dp)
// timer고차함수에 period인자와 블록{} 내 함수를 보냄 -> Timer객체를 반환
// timer에서는 전달받은 함수를 0.01초에 한 번씩 호출
timerTask=timer(period=10){
time++
val sec=time/100 // 1초가 지나면 time은 100이되는데 이 때 sec은 1이 됨
val milli=time%100 // milli는 1~99까지만 출력되어야 하니 100으로 나눈 나머지임
// runonuithread메소드 호출 (ui관련 객체를 전달) <sam변환>
// 힘든 작업을 할 때는 워커 스레드에서 작용하는데 timer함수가 그렇다.
// 워커 스레드 작업 중에는 ui변경이 불가능하다. 하지만 runonuithread에 전달되는 클래스는 워커 스레드에서 벗어난다.
runOnUiThread{
secTextView.text="$sec"
milliTextView.text="$milli"
}
}
}
private fun pause(){
fab.setImageResource(R.drawable.ic_play_arrow_black_24dp)
clear.isVisible=true
// Timer객체의 cancel메소드로 타이머 중지 가능
timerTask?.cancel()
}
private fun reset(num:Int){
timerTask?.cancel() // 멈춤
clear.isVisible=true // x 버튼 보이게 함
// reset됐는데 isRunning이 true인 상태면 false로 만듬
if(isRunning)
isRunning=false
// time초기화 및 시작 버튼 바꿈
time=0
fab.setImageResource(R.drawable.ic_play_arrow_black_24dp)
if(num==1){ // clear버튼 눌렀을 때는 리니어 레이아웃 모든 위젯 제거/ 텍스트,lap초기화
lapLayout.removeAllViews()
secTextView.text="0"
milliTextView.text="00"
lap=1
clear.isVisible=false // x 버튼 감춤
}
}
private fun recordLapTime(){
// start메소드에서 계속 오르는 time변수를 가져옴
val lapTime=this.time
// 위젯을 동적 생성
val textView= TextView(this)
val string="$lap LAP:${lapTime/100}.${lapTime%100}"
textView.text=string
// 스크롤뷰 맨 위(인덱스:0)에 위젯을 추가
lapLayout.addView(textView,0)
lap++
}
// 이전 버튼 두 번 눌러서 종료하기
override fun onBackPressed() {
// (현재 버튼 누른 시간-이전에 버튼 누른 시간) <=1.5초일 때 동작
if(System.currentTimeMillis()-lastTimeBackPressed<=1500)
finish()
lastTimeBackPressed=System.currentTimeMillis()
Toast.makeText(this,"이전 버튼을 한 번 더 누르면 종료됩니다",Toast.LENGTH_SHORT).show()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
fab.setOnClickListener{
// fab이 클릭되면 isRunning을 반전
when(isRunning){
false->start() // false: 현재 실행되지 않는 상태이니 start가능, start시 변수 반전
else->pause() // true: 현재 실행되는 상태이니 pause가능, pause시 변수 반전
}
isRunning=!isRunning
}
lapButton.setOnClickListener{
recordLapTime()
}
resetFab.setOnClickListener{
reset(0)
}
clear.setOnClickListener{
reset(1)
}
}
}