스톱워치 사전지식: 메인 스레드와 백그라운드 스레드
runOnUiThread() 메소드
public final void runOnUiThread(Runnable action) {
if (Thread.currentThread() != mUiThread) {
mHandler.post(action);
} else{
action.run();
}
}
runOnUiThread(object : Runnable{
override fun run() {
doSomethingWithUI() //여기에 원하는 로직을 구현한다.
}
})
runOnUiThread{
doSomethingWithUI() //여기에 원하는 로직을 구현한다.
}
프로젝트 생성
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="purple_200">#FFBB86FC</color>
<color name="purple_500">#FF6200EE</color>
<color name="purple_700">#FF3700B3</color>
<color name="teal_200">#FF03DAC5</color>
<color name="teal_700">#FF018786</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
<!-- 여기서부터 직접 추가한 색 -->
<color name="blue">#603cff</color>
<color name="red">#ff6767</color>
<color name="yellow">#e1bf5a</color>
</resources>
색상 선택기 사용하기
색상을 코드로만 지정할 수 있는 것은 아니다. 색상 선택기를 이용하는 방법도 있다. 색상을 지정하는 코드 왼쪽에서 코드가 나타내는 색을 미리 보여주는데, 이 사각형을 클릭하면 색상 선택기가 뜬다. 여기서 선택한 색상대로 자동으로 코드가 바뀐다. 실제로 코딩할 때 유용하게 쓰이니 기억해두자
다음은 strings.xml에 '시작', '일시정지', '초기화' 문자열을 추가해준다.
<resources>
<string name="app_name">StopWatch</string>
<!-- 여기서부터 추가한 문자열 -->
<string name="start">시작</string>
<string name="pause">일시정지</string>
<string name="refresh">초기화</string>
</resources>
버튼 추가
시작 버튼
<Button
android:id="@+id/btn_start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginBottom="80dp"
android:padding="20dp"
android:backgroundTint="@color/blue"
android:text="@string/start"
android:textColor="@color/white"
android:textSize="16sp"
android:textStyle="bold"/>
초기화 버튼
<Button
android:id="@+id/btn_refresh"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="@id/btn_start"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginBottom="50dp"
android:padding="20sp"
android:text="@string/refresh"
android:backgroundTint="@color/yellow"
android:textSize="16sp"
android:textColor="@color/white"
android:textStyle="bold"/>
텍스트뷰 추가: 체인 사용해보기
<TextView
android:id="@+id/tv_minute"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="00"
android:textSize="45sp"/>
<TextView
android:id="@+id/tv_second"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=":00"
android:textSize="45sp"/>
<TextView
android:id="@+id/tv_millisecond"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=".00"
android:textSize="30sp"/>
수직 방향 제약 추가하기
왜 텍스트뷰 정렬에 베이스라인을 사용할까?
수평 방향 제약 추가하기


버튼에 이벤트 연결하기
class MainActivity : AppCompatActivity(), View.OnClickListener {//클릭 이벤트 처리 인터페이스
var isRunning = false//실행 여부 확인용 변수
private lateinit var btn_start: Button
private lateinit var btn_refresh: Button
private lateinit var tv_millisecond: TextView
private lateinit var tv_second: TextView
private lateinit var tv_minute: TextView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//뷰 가져오기
btn_start = findViewById(R.id.btn_start)
btn_refresh = findViewById(R.id.btn_refresh)
tv_millisecond = findViewById(R.id.tv_millisecond)
tv_second = findViewById(R.id.tv_second)
tv_minute = findViewById(R.id.tv_minute)
//버튼별 OnClickListener 등록
btn_start.setOnClickListener(this)
btn_refresh.setOnClickListener(this)
}
//클릭 이벤트 처리
override fun onClick(v: View?) {
when(v?.id) {
R.id.btn_start -> {
if(isRunning) {
pause()
} else {
start()
}
}
R.id.btn_refresh -> {
refresh()
}
}
}
private fun start() {
}
private fun pause() {
}
private fun refresh() {
}
}
스톱워치 시작 기능 구현하기
var timer : Timer? = null//timer 변수 추가
var time = 0//time 변수 추가
private fun start() {
btn_start.text = "일시정지"
btn_start.setBackgroundColor(getColor(R.color.red))
isRunning = true
timer = timer(period = 10) {
time++//10밀리초 단위 타이머
val milli_second = time % 100
val second = (time % 6000) / 100
val minute = time / 6000
tv_millisecond.text = if (milli_second < 10) ".0${milli_second}" else ".${milli_second}"//밀리초
tv_second.text = if(second < 10) ":0${second}" else ":${second}"//초
tv_minute.text = "${minute}"
}
}
runOnUiThread {
if(isRunning) {
tv_millisecond.text = if (milli_second < 10) ".0${milli_second}" else ".${milli_second}"//밀리초
tv_second.text = if(second < 10) ":0${second}" else ":${second}"//초
tv_minute.text = "${minute}"
}
}
일시정지 기능 구현하기
private fun pause() {
btn_start.text = "시작"
btn_start.setBackgroundColor(getColor(R.color.blue))
isRunning = false
timer?.cancel()//타이머 멈추기
}
초기화 기능 구현하기
private fun refresh() {
timer?.cancel()
btn_start.text="시작"
btn_start.setBackgroundColor(getColor(R.color.blue))
isRunning = false
time = 0
tv_millisecond.text = ".00"
tv_second.text = ":00"
tv_minute.text = "00"
}