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
2 changes: 2 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,6 @@ dependencies {
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
val fragment_version = "1.8.9"
implementation("androidx.fragment:fragment-ktx:$fragment_version")
}
26 changes: 26 additions & 0 deletions app/src/main/java/com/example/android_25_2/LapAdapter.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.example.android_25_2

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

class LapAdapter (private val lapList: MutableList<String>): RecyclerView.Adapter<RecyclerView.ViewHolder>(){
class ViewHolder(view: View) : RecyclerView.ViewHolder(view){
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item, parent, false)
return ViewHolder(view)
}

override fun getItemCount(): Int {
return lapList.size
}

override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val lapTime = lapList[position]
val textViewRecord: TextView = holder.itemView.findViewById(R.id.textView_record)
textViewRecord.text = lapTime
}
}
78 changes: 78 additions & 0 deletions app/src/main/java/com/example/android_25_2/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -1,12 +1,31 @@
package com.example.android_25_2

import android.os.Bundle
import android.widget.Button
import android.widget.TextView
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.util.Locale
import java.util.Timer


class MainActivity : AppCompatActivity() {

var time = 0
var isRunning = false
var lapList = mutableListOf<String>()
var timerJob: Job? = null
var timerTask: Timer? = null
var lapAdapter = LapAdapter(lapList)
Comment on lines +22 to +27

Choose a reason for hiding this comment

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

private 처리를 해도 좋을 것 같아요


override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
Expand All @@ -16,5 +35,64 @@ class MainActivity : AppCompatActivity() {
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}
val textViewTime = findViewById<TextView>(R.id.textView_time)
val recyclerView = findViewById<RecyclerView>(R.id.recyclerView)
val buttonStartOrPause = findViewById<Button>(R.id.button_start_or_pause)
val buttonStop = findViewById<Button>(R.id.button_stop)
val buttonLap = findViewById<Button>(R.id.button_lap)

lapAdapter = LapAdapter(lapList)
recyclerView.layoutManager = LinearLayoutManager(this)
recyclerView.adapter = lapAdapter
textViewTime.text = "00:00:00"

fun formatTime(millis: Int): String {

Choose a reason for hiding this comment

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

확장함수를 사용헀다면 더 좋을 것 같아요

val minutes = ((millis % 3600000) / 60000)
val seconds = ((millis % 60000) / 1000)
val ms = ((millis % 1000) / 10)
return String.format(Locale.US, "%02d:%02d:%02d", minutes, seconds, ms)

Choose a reason for hiding this comment

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

Locale이 US인 이유가 있나요?

}

fun start() {
isRunning = true
timerJob = lifecycleScope.launch {
while (isRunning) {
delay(10)

Choose a reason for hiding this comment

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

Coroutine에서 delay를 10ms만큼 준다고 실제 10ms만큼만 delay가 생기지 않습니다.
예를 들어, delay(1000)에 대해 전후에 System.currentTimeMillis()를 로그로 찍어보면, 실제로 1000ms만큼 차이가 나는 것이 아니라 오차가 발생하는 것을 확인할 수 있습니다.
왜 이런 현상이 발생하는지도 알아보시면 좋을 것 같아요.

time += 10
textViewTime.text = formatTime(time)
}
}
}

fun pause() {
isRunning = false
timerJob?.cancel()
}

fun stopTimer() {
isRunning = false
timerJob?.cancel()
time = 0
textViewTime.text = "00:00:00"
}

buttonStartOrPause.setOnClickListener {
if (isRunning) pause()
else start()
}

buttonStop.setOnClickListener {
stopTimer()
lapList.clear()
lapAdapter.notifyDataSetChanged()
isRunning = false
}

buttonLap.setOnClickListener{
val currentTime = textViewTime.text.toString()
lapList.add(0, currentTime)

Choose a reason for hiding this comment

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

0번 인덱스에 추가하는 방법도 좋은 방법이지만, recyclerview 자체를 반대로 뒤집을 수도 있어요

lapAdapter.notifyItemInserted(0)
recyclerView.scrollToPosition(0)
}
}
}
54 changes: 54 additions & 0 deletions app/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,58 @@
android:layout_height="match_parent"
tools:context=".MainActivity">

<TextView
android:id="@+id/textView_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30sp"
android:textStyle="bold"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="180dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>

<Button
android:id="@+id/button_start_or_pause"
android:layout_width="100dp"
android:layout_height="60dp"
android:text="@string/button_text_start_or_pause"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/textView_time"
app:layout_constraintEnd_toStartOf="@id/button_stop"
android:layout_marginTop="80dp"
android:layout_marginStart="25dp"/>

<Button
android:id="@+id/button_stop"
android:layout_width="100dp"
android:layout_height="60dp"
android:text="@string/button_text_stop"
app:layout_constraintTop_toBottomOf="@id/textView_time"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginHorizontal="25dp"
android:layout_marginTop="80dp"/>

<Button
android:id="@+id/button_lap"
android:layout_width="100dp"
android:layout_height="60dp"
android:text="@string/button_text_lap"
app:layout_constraintTop_toBottomOf="@id/textView_time"
app:layout_constraintStart_toEndOf="@id/button_stop"
android:layout_marginTop="80dp"
android:layout_marginHorizontal="25dp"/>

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="@id/button_stop"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="30dp"
android:background="@color/gray" />

</androidx.constraintlayout.widget.ConstraintLayout>
21 changes: 21 additions & 0 deletions app/src/main/res/layout/item.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="50dp"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="@color/white">

<TextView
android:id="@+id/textView_record"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="13dp"
android:layout_marginHorizontal="15dp"/>


</androidx.constraintlayout.widget.ConstraintLayout>
8 changes: 4 additions & 4 deletions app/src/main/res/values-night/themes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
<!-- Base application theme. -->
<style name="Theme.Android_252" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_200</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
<item name="colorPrimary">@color/purple</item>
<item name="colorPrimaryVariant">@color/purple</item>
<item name="colorOnPrimary">@color/black</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_200</item>
<item name="colorSecondary">@color/gray</item>
<item name="colorSecondaryVariant">@color/gray</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
Expand Down
7 changes: 2 additions & 5 deletions app/src/main/res/values/colors.xml
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
<?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="purple">#FF6200EE</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
<color name="gray">#F1F3F5</color>
</resources>
3 changes: 3 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
<resources>
<string name="app_name">Android_25-2</string>
<string name="button_text_start_or_pause">Start/Pause</string>
<string name="button_text_stop">Stop</string>
<string name="button_text_lap">Lap</string>
</resources>
8 changes: 4 additions & 4 deletions app/src/main/res/values/themes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
<!-- Base application theme. -->
<style name="Theme.Android_252" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_500</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
<item name="colorPrimary">@color/purple</item>
<item name="colorPrimaryVariant">@color/purple</item>
<item name="colorOnPrimary">@color/white</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_700</item>
<item name="colorSecondary">@color/gray</item>
<item name="colorSecondaryVariant">@color/gray</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
Expand Down
1 change: 1 addition & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ appcompat = "1.7.1"
material = "1.12.0"
activity = "1.11.0"
constraintlayout = "2.2.1"
fragment_version = "1.8.9"

[libraries]
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
Expand Down