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) } } }