From d2b97df0378b720b77a5689096f4c1fd8aee68c2 Mon Sep 17 00:00:00 2001 From: unam98 Date: Thu, 6 Aug 2026 18:04:13 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EB=9F=AC=EB=8B=9D=20=ED=99=94=EB=A9=B4?= =?UTF-8?q?=EC=97=90=20=EC=9D=BC=EC=8B=9C=EC=A0=95=EC=A7=80/=EC=9E=AC?= =?UTF-8?q?=EA=B0=9C=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 기존엔 러닝 종료 버튼 하나만 있어 중간에 멈출 수 없었음. 기존 "러닝 종료" 풀와이드 버튼을 원형 일시정지(주) 버튼으로 교체하고, 일시정지 시에만 종료(정지)/재개 버튼 두 개가 나타나도록 했다. 지도는 NRC처럼 별도 화면으로 바꾸지 않고 그대로 유지하되, 옅은 틴트와 "일시정지 중" 배지로 상태를 표시해 코스 경로를 계속 보여준다. TimerService에 pauseTimer/resumeTimer를 추가했는데, 기존 time 값을 초기화하지 않는 startTimer/stopTimer 구조를 그대로 재사용해 일시정지 후 재개하면 멈췄던 지점부터 이어서 카운트된다. --- .../runnect/presentation/run/RunActivity.kt | 27 +++++++- .../runnect/presentation/run/RunViewModel.kt | 1 + .../runnect/presentation/run/TimerService.kt | 13 ++++ app/src/main/res/drawable/bg_paused_pill.xml | 6 ++ .../main/res/drawable/circle_ghost_button.xml | 8 +++ .../main/res/drawable/circle_m1_button.xml | 5 ++ app/src/main/res/drawable/ic_run_pause.xml | 13 ++++ app/src/main/res/drawable/ic_run_resume.xml | 10 +++ app/src/main/res/drawable/ic_run_stop.xml | 10 +++ app/src/main/res/layout/activity_run.xml | 63 +++++++++++++++---- app/src/main/res/values/strings.xml | 4 ++ 11 files changed, 146 insertions(+), 14 deletions(-) create mode 100644 app/src/main/res/drawable/bg_paused_pill.xml create mode 100644 app/src/main/res/drawable/circle_ghost_button.xml create mode 100644 app/src/main/res/drawable/circle_m1_button.xml create mode 100644 app/src/main/res/drawable/ic_run_pause.xml create mode 100644 app/src/main/res/drawable/ic_run_resume.xml create mode 100644 app/src/main/res/drawable/ic_run_stop.xml diff --git a/app/src/main/java/com/runnect/runnect/presentation/run/RunActivity.kt b/app/src/main/java/com/runnect/runnect/presentation/run/RunActivity.kt index fe9e4257b..59019f351 100644 --- a/app/src/main/java/com/runnect/runnect/presentation/run/RunActivity.kt +++ b/app/src/main/java/com/runnect/runnect/presentation/run/RunActivity.kt @@ -97,6 +97,7 @@ class RunActivity : BindingActivity(R.layout.activity_run), getCurrentLocation() showRecord() backButton() + setUpPauseResume() val runCourseData: CourseData? = intent.getParcelableExtra(EXTRA_COUNTDOWN_TO_RUN) val targetDistanceM = runCourseData?.distance?.let { (it * 1000f).roundToInt() } @@ -133,6 +134,30 @@ class RunActivity : BindingActivity(R.layout.activity_run), stopService(serviceIntent) //서비스 객체 제거 } + private fun setUpPauseResume() { + binding.btnRunPauseResume.setOnClickListener { + val isPaused = viewModel.isPaused.value ?: false + if (isPaused) { + timerService?.resumeTimer() + } else { + timerService?.pauseTimer() + } + viewModel.isPaused.value = !isPaused + updatePauseResumeUI(!isPaused) + } + } + + private fun updatePauseResumeUI(isPaused: Boolean) { + binding.btnRunPauseResume.apply { + setImageResource(if (isPaused) R.drawable.ic_run_resume else R.drawable.ic_run_pause) + contentDescription = getString( + if (isPaused) R.string.run_description_resume else R.string.run_description_pause + ) + } + binding.btnRunStop.visibility = if (isPaused) View.VISIBLE else View.GONE + binding.tvPausedLabel.visibility = if (isPaused) View.VISIBLE else View.GONE + } + override fun onStart() { super.onStart() // Timer 결과값을 받기 위해 브로드캐스트 리시버 등록 @@ -336,7 +361,7 @@ class RunActivity : BindingActivity(R.layout.activity_run), } private fun showRecord() { - binding.btnRunFinish.setOnClickListener { + binding.btnRunStop.setOnClickListener { stopTimer() val totalTimeSec = ((timerData.hour ?: 0) * 3600) + ((timerData.minute ?: 0) * 60) + (timerData.second ?: 0) Analytics.logEvent( diff --git a/app/src/main/java/com/runnect/runnect/presentation/run/RunViewModel.kt b/app/src/main/java/com/runnect/runnect/presentation/run/RunViewModel.kt index d15f35ada..4c7bf98d8 100644 --- a/app/src/main/java/com/runnect/runnect/presentation/run/RunViewModel.kt +++ b/app/src/main/java/com/runnect/runnect/presentation/run/RunViewModel.kt @@ -9,4 +9,5 @@ class RunViewModel : ViewModel() { val dataFrom = MutableLiveData() var courseId = MutableLiveData() var publicCourseId = MutableLiveData() + val isPaused = MutableLiveData(false) } \ No newline at end of file diff --git a/app/src/main/java/com/runnect/runnect/presentation/run/TimerService.kt b/app/src/main/java/com/runnect/runnect/presentation/run/TimerService.kt index b8afbc7dd..b526c0079 100644 --- a/app/src/main/java/com/runnect/runnect/presentation/run/TimerService.kt +++ b/app/src/main/java/com/runnect/runnect/presentation/run/TimerService.kt @@ -90,6 +90,19 @@ class TimerService : Service() { timer?.cancel() } + // 일시정지: 타이머만 멈추고 누적된 time은 유지한다 (resumeTimer에서 이어서 증가) + fun pauseTimer() { + timer?.cancel() + notificationBuilder.setContentText("일시정지 중") + val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager + notificationManager.notify(NOTI_ID, notificationBuilder.build()) + } + + // 재개: 기존 time 값에 이어서 타이머를 다시 시작한다 + fun resumeTimer() { + startTimer() + } + override fun onBind(intent: Intent?): IBinder { return binder } diff --git a/app/src/main/res/drawable/bg_paused_pill.xml b/app/src/main/res/drawable/bg_paused_pill.xml new file mode 100644 index 000000000..419c2fb0d --- /dev/null +++ b/app/src/main/res/drawable/bg_paused_pill.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/app/src/main/res/drawable/circle_ghost_button.xml b/app/src/main/res/drawable/circle_ghost_button.xml new file mode 100644 index 000000000..a18252dd6 --- /dev/null +++ b/app/src/main/res/drawable/circle_ghost_button.xml @@ -0,0 +1,8 @@ + + + + + diff --git a/app/src/main/res/drawable/circle_m1_button.xml b/app/src/main/res/drawable/circle_m1_button.xml new file mode 100644 index 000000000..e9f960dd9 --- /dev/null +++ b/app/src/main/res/drawable/circle_m1_button.xml @@ -0,0 +1,5 @@ + + + + diff --git a/app/src/main/res/drawable/ic_run_pause.xml b/app/src/main/res/drawable/ic_run_pause.xml new file mode 100644 index 000000000..9eb5838b0 --- /dev/null +++ b/app/src/main/res/drawable/ic_run_pause.xml @@ -0,0 +1,13 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_run_resume.xml b/app/src/main/res/drawable/ic_run_resume.xml new file mode 100644 index 000000000..3da04e6a0 --- /dev/null +++ b/app/src/main/res/drawable/ic_run_resume.xml @@ -0,0 +1,10 @@ + + + + diff --git a/app/src/main/res/drawable/ic_run_stop.xml b/app/src/main/res/drawable/ic_run_stop.xml new file mode 100644 index 000000000..7a1d144fb --- /dev/null +++ b/app/src/main/res/drawable/ic_run_stop.xml @@ -0,0 +1,10 @@ + + + + diff --git a/app/src/main/res/layout/activity_run.xml b/app/src/main/res/layout/activity_run.xml index 39fbf25f4..54f9bcf7b 100644 --- a/app/src/main/res/layout/activity_run.xml +++ b/app/src/main/res/layout/activity_run.xml @@ -154,22 +154,59 @@ tools:layout_editor_absoluteX="0dp" tools:layout_editor_absoluteY="0dp" /> - + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/view_run_top_frame" + tools:visibility="visible" /> + + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7fbacbf8f..552ca7062 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -74,6 +74,10 @@ 시간 러닝 종료 current_location + 일시정지 + 재개 + 러닝 종료 + 일시정지 중 선택 업로드