Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions .idea/.name

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/AndroidProjectSystem.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/compiler.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions .idea/deploymentTargetSelector.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/encodings.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 19 additions & 0 deletions .idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions .idea/migrations.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions .idea/runConfigurations.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

39 changes: 39 additions & 0 deletions app/src/main/java/com/example/bcsd_android_2025_1/LapAdapter.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.example.bcsd_android_2025_1

import android.view.LayoutInflater
import android.view.View
import android.widget.TextView
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView

class LapAdapter : RecyclerView.Adapter<LapAdapter.LapViewHolder>() {

private val lapList = mutableListOf<LapItem>()

class LapViewHolder(View: View) : RecyclerView.ViewHolder(View) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

네이밍 컨밴션 지켜주세요(View: View -> view: View)

val lapText: TextView = View.findViewById(R.id.text_lap)
}

fun addLap(time: String) {
lapList.add(0, LapItem(time))
notifyItemInserted(0)
}

fun clearLaps() {
lapList.clear()
notifyDataSetChanged()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

notifyItemRangeRemoved()를 사용하시면 좋습니다.

}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LapViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_lap, parent, false)
return LapViewHolder(view)
}

override fun onBindViewHolder(holder: LapViewHolder, position: Int) {
holder.lapText.text = lapList[position].time
}

override fun getItemCount(): Int {
return lapList.size
}
}
3 changes: 3 additions & 0 deletions app/src/main/java/com/example/bcsd_android_2025_1/LapItem.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package com.example.bcsd_android_2025_1

data class LapItem(val time : String)
105 changes: 102 additions & 3 deletions app/src/main/java/com/example/bcsd_android_2025_1/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -1,14 +1,113 @@
package com.example.bcsd_android_2025_1

import android.os.Bundle
import androidx.activity.enableEdgeToEdge
import android.os.SystemClock
import android.widget.Button
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch

class MainActivity : AppCompatActivity() {

private lateinit var timerTextView: TextView
private lateinit var startPauseButton: Button
private lateinit var stopButton: Button
private lateinit var lapButton: Button
private lateinit var lapRecyclerView: RecyclerView
private lateinit var lapAdapter: LapAdapter

private var startTime = 0L
private var elapsedTime = 0L
private var isRunning = false
private var timeJob: Job? = null

private var coroutineScope = CoroutineScope(Dispatchers.Main)

private fun nowTime(ms: Long): String {
val minutes = (ms / 60000).toInt()
val seconds = ((ms % 60000) / 1000).toInt()
val millseconds = ((ms % 1000) / 10).toInt()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

milliseconds 오타인듯 합니다.

val timeString = getString(R.string.now_time, minutes, seconds, millseconds)
return timeString
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

timerTextView = findViewById(R.id.textview_timer)
startPauseButton = findViewById(R.id.button_start_pause)
stopButton = findViewById(R.id.button_stop)
lapButton = findViewById(R.id.button_lap)
lapRecyclerView = findViewById(R.id.lap_recyclerview)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

view binding 사용하시면 간편하게 할 수 있습니다 👍

lapAdapter = LapAdapter()

lapRecyclerView.adapter = lapAdapter
lapRecyclerView.layoutManager = LinearLayoutManager(this)

startPauseButton.setOnClickListener {
if (isRunning) {
pauseTimer()
} else {
startTimer()
}
}
stopButton.setOnClickListener {
stopTimer()
}
lapButton.setOnClickListener {
if (isRunning) {
val currentTime = SystemClock.elapsedRealtime() - startTime
val lapTime = nowTime(currentTime)

lapAdapter.addLap(lapTime)
lapRecyclerView.scrollToPosition(0)
}
}
}

private fun startTimer() {
startTime = SystemClock.elapsedRealtime() - elapsedTime
isRunning = true
startPauseButton.text = getString(R.string.text_pause)

timeJob = coroutineScope.launch {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lifecycleScope도 확인해보시면 좋을 것 같습니다 👍

while (isActive) {
val elapsed = SystemClock.elapsedRealtime() - startTime
timerTextView.text = nowTime(elapsed)
delay(10L)
}
}
}

private fun pauseTimer() {
elapsedTime = SystemClock.elapsedRealtime() - startTime
timeJob?.cancel()
isRunning = false
startPauseButton.text = getString(R.string.text_start)
}

private fun stopTimer() {
timeJob?.cancel()
startTime = 0L
elapsedTime = 0L
isRunning = false
timerTextView.text = getString(R.string.start_time)
startPauseButton.text = getString(R.string.text_start)
lapAdapter.clearLaps()
}

override fun onDestroy() {
super.onDestroy()
timeJob?.cancel()
coroutineScope.cancel()
}
}
57 changes: 50 additions & 7 deletions app/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
@@ -1,19 +1,62 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
android:padding="16dp">

<TextView
android:layout_width="wrap_content"
android:id="@+id/textview_timer"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Hello Android!"
app:layout_constraintBottom_toBottomOf="parent"
android:text="@string/start_time"
android:textSize="36sp"
android:textStyle="bold"
android:gravity="center"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/button_start_pause"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="50dp"/>

<Button
android:id="@+id/button_start_pause"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/text_start"
app:layout_constraintTop_toBottomOf="@id/textview_timer"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/button_stop"
android:layout_marginEnd="8dp"
android:layout_marginTop="50dp"/>

<Button
android:id="@+id/button_stop"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/text_stop"
app:layout_constraintTop_toTopOf="@id/button_start_pause"
app:layout_constraintStart_toEndOf="@id/button_start_pause"
app:layout_constraintEnd_toStartOf="@id/button_lap"
android:layout_marginEnd="8dp"/>

<Button
android:id="@+id/button_lap"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/text_lap"
app:layout_constraintTop_toTopOf="@id/button_stop"
app:layout_constraintStart_toEndOf="@id/button_stop"
app:layout_constraintEnd_toEndOf="parent" />

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/lap_recyclerview"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="@id/button_lap"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="30dp"/>

</androidx.constraintlayout.widget.ConstraintLayout>
9 changes: 9 additions & 0 deletions app/src/main/res/layout/item_lap.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id = "@+id/text_lap"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="12dp"
android:textSize="18sp"
android:textColor="@color/green"
/>
1 change: 1 addition & 0 deletions app/src/main/res/values/colors.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
<resources>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
<color name="green">#00AA00</color>
</resources>
6 changes: 6 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
<resources>
<string name="app_name">BCSD_Android_2025-1</string>
<string name="start_time">00 : 00 : 00</string>
<string name="now_time">%02d : %02d :%02d</string>
<string name="text_pause">Pause</string>
<string name="text_start">Start</string>
<string name="text_stop">Stop</string>
<string name="text_lap">Lap</string>
</resources>