From f3f69f8fabc13ebe5d7676614fbc46eb9bce691a Mon Sep 17 00:00:00 2001 From: ootr47 Date: Thu, 28 Dec 2023 16:35:50 +0900 Subject: [PATCH 01/70] =?UTF-8?q?feat:=20=ED=9A=8C=EC=9B=90=20=ED=83=88?= =?UTF-8?q?=ED=87=B4=20api=20=EC=B4=88=EA=B8=B0=20=EC=84=B8=ED=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/deleteaccount/DeleteAccountResponse.kt | 9 +++++++++ .../java/app/priceguard/data/network/UserAPI.kt | 5 +++++ .../data/repository/auth/AuthRepository.kt | 2 ++ .../data/repository/auth/AuthRepositoryImpl.kt | 16 ++++++++++++++++ .../priceguard/ui/home/mypage/MyPageViewModel.kt | 10 ++++++++++ 5 files changed, 42 insertions(+) create mode 100644 android/app/src/main/java/app/priceguard/data/dto/deleteaccount/DeleteAccountResponse.kt diff --git a/android/app/src/main/java/app/priceguard/data/dto/deleteaccount/DeleteAccountResponse.kt b/android/app/src/main/java/app/priceguard/data/dto/deleteaccount/DeleteAccountResponse.kt new file mode 100644 index 0000000..f4545da --- /dev/null +++ b/android/app/src/main/java/app/priceguard/data/dto/deleteaccount/DeleteAccountResponse.kt @@ -0,0 +1,9 @@ +package app.priceguard.data.dto.deleteaccount + +import kotlinx.serialization.Serializable + +@Serializable +data class DeleteAccountResponse( + val statusCode: Int, + val message: String +) diff --git a/android/app/src/main/java/app/priceguard/data/network/UserAPI.kt b/android/app/src/main/java/app/priceguard/data/network/UserAPI.kt index 270b0a4..b539e85 100644 --- a/android/app/src/main/java/app/priceguard/data/network/UserAPI.kt +++ b/android/app/src/main/java/app/priceguard/data/network/UserAPI.kt @@ -1,5 +1,6 @@ package app.priceguard.data.network +import app.priceguard.data.dto.deleteaccount.DeleteAccountResponse import app.priceguard.data.dto.firebase.FirebaseTokenUpdateRequest import app.priceguard.data.dto.firebase.FirebaseTokenUpdateResponse import app.priceguard.data.dto.login.LoginRequest @@ -8,6 +9,7 @@ import app.priceguard.data.dto.signup.SignupRequest import app.priceguard.data.dto.signup.SignupResponse import retrofit2.Response import retrofit2.http.Body +import retrofit2.http.DELETE import retrofit2.http.Header import retrofit2.http.POST import retrofit2.http.PUT @@ -24,6 +26,9 @@ interface UserAPI { @Body request: SignupRequest ): Response + @DELETE("") + suspend fun deleteAccount(): Response + @PUT("firebase/token") suspend fun updateFirebaseToken( @Header("Authorization") authToken: String, diff --git a/android/app/src/main/java/app/priceguard/data/repository/auth/AuthRepository.kt b/android/app/src/main/java/app/priceguard/data/repository/auth/AuthRepository.kt index f75b37b..07fb157 100644 --- a/android/app/src/main/java/app/priceguard/data/repository/auth/AuthRepository.kt +++ b/android/app/src/main/java/app/priceguard/data/repository/auth/AuthRepository.kt @@ -9,4 +9,6 @@ interface AuthRepository { suspend fun signUp(email: String, userName: String, password: String): RepositoryResult suspend fun login(email: String, password: String): RepositoryResult + + suspend fun deleteAccount(): RepositoryResult } diff --git a/android/app/src/main/java/app/priceguard/data/repository/auth/AuthRepositoryImpl.kt b/android/app/src/main/java/app/priceguard/data/repository/auth/AuthRepositoryImpl.kt index d007435..b1acaef 100644 --- a/android/app/src/main/java/app/priceguard/data/repository/auth/AuthRepositoryImpl.kt +++ b/android/app/src/main/java/app/priceguard/data/repository/auth/AuthRepositoryImpl.kt @@ -73,4 +73,20 @@ class AuthRepositoryImpl @Inject constructor(private val userAPI: UserAPI) : Aut } } } + + override suspend fun deleteAccount(): RepositoryResult { + val response = getApiResult { + userAPI.deleteAccount() + } + + return when (response) { + is APIResult.Success -> { + RepositoryResult.Success(true) + } + + is APIResult.Error -> { + handleError(response.code) + } + } + } } diff --git a/android/app/src/main/java/app/priceguard/ui/home/mypage/MyPageViewModel.kt b/android/app/src/main/java/app/priceguard/ui/home/mypage/MyPageViewModel.kt index 12e49dc..193018a 100644 --- a/android/app/src/main/java/app/priceguard/ui/home/mypage/MyPageViewModel.kt +++ b/android/app/src/main/java/app/priceguard/ui/home/mypage/MyPageViewModel.kt @@ -2,6 +2,7 @@ package app.priceguard.ui.home.mypage import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import app.priceguard.data.repository.auth.AuthRepository import app.priceguard.data.repository.token.TokenRepository import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject @@ -13,6 +14,7 @@ import kotlinx.coroutines.launch @HiltViewModel class MyPageViewModel @Inject constructor( + val authRepository: AuthRepository, val tokenRepository: TokenRepository ) : ViewModel() { @@ -55,6 +57,14 @@ class MyPageViewModel @Inject constructor( } } + fun deleteAccount() { + viewModelScope.launch { + authRepository.deleteAccount() + tokenRepository.clearTokens() + _event.emit(MyPageEvent.StartIntroAndExitHome) + } + } + private fun getFirstName(name: String): String { name.forEach { if (it.isSurrogate().not() && it.toString().isNotBlank()) { From 6c3ff86dcb99e623b4667c9c3fc4f28b55e3e0e4 Mon Sep 17 00:00:00 2001 From: ootr47 Date: Thu, 28 Dec 2023 16:36:11 +0900 Subject: [PATCH 02/70] =?UTF-8?q?feat:=20=ED=9A=8C=EC=9B=90=20=ED=83=88?= =?UTF-8?q?=ED=87=B4=20=EC=95=84=EC=9D=B4=EC=BD=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- android/app/src/main/res/drawable/ic_close_red.xml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 android/app/src/main/res/drawable/ic_close_red.xml diff --git a/android/app/src/main/res/drawable/ic_close_red.xml b/android/app/src/main/res/drawable/ic_close_red.xml new file mode 100644 index 0000000..ea5e3a4 --- /dev/null +++ b/android/app/src/main/res/drawable/ic_close_red.xml @@ -0,0 +1,10 @@ + + + From f9735a6a8daf563359544f7423a676d94ae80b17 Mon Sep 17 00:00:00 2001 From: ootr47 Date: Thu, 28 Dec 2023 16:37:44 +0900 Subject: [PATCH 03/70] =?UTF-8?q?feat:=20=ED=9A=8C=EC=9B=90=20=ED=83=88?= =?UTF-8?q?=ED=87=B4=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80=20=EB=B0=8F?= =?UTF-8?q?=20=EB=8B=A4=EC=9D=B4=EC=96=BC=EB=A1=9C=EA=B7=B8=20requestCode?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../priceguard/ui/detail/DetailActivity.kt | 2 +- .../ui/home/mypage/MyPageFragment.kt | 26 ++++++++++++++----- .../ui/home/mypage/SettingItemInfo.kt | 3 ++- .../ui/util/ConfirmDialogFragment.kt | 8 ++++-- 4 files changed, 28 insertions(+), 11 deletions(-) diff --git a/android/app/src/main/java/app/priceguard/ui/detail/DetailActivity.kt b/android/app/src/main/java/app/priceguard/ui/detail/DetailActivity.kt index 7fe0a3e..2c75d62 100644 --- a/android/app/src/main/java/app/priceguard/ui/detail/DetailActivity.kt +++ b/android/app/src/main/java/app/priceguard/ui/detail/DetailActivity.kt @@ -298,7 +298,7 @@ class DetailActivity : AppCompatActivity(), ConfirmDialogFragment.OnDialogResult Toast.makeText(this, message, Toast.LENGTH_LONG).show() } - override fun onDialogResult(result: Boolean) { + override fun onDialogResult(requestCode: Int, result: Boolean) { if (result) { productDetailViewModel.deleteProductTracking() } diff --git a/android/app/src/main/java/app/priceguard/ui/home/mypage/MyPageFragment.kt b/android/app/src/main/java/app/priceguard/ui/home/mypage/MyPageFragment.kt index 77c0c7b..141a782 100644 --- a/android/app/src/main/java/app/priceguard/ui/home/mypage/MyPageFragment.kt +++ b/android/app/src/main/java/app/priceguard/ui/home/mypage/MyPageFragment.kt @@ -5,6 +5,7 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.annotation.StringRes import androidx.core.content.ContextCompat import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels @@ -78,7 +79,11 @@ class MyPageFragment : Fragment(), ConfirmDialogFragment.OnDialogResultListener } Setting.LOGOUT -> { - showConfirmationDialogForResult() + showConfirmationDialogForResult(R.string.logout_confirm_title, R.string.logout_confirm_message, Setting.LOGOUT.ordinal) + } + + Setting.DELETE_ACCOUNT -> { + showConfirmationDialogForResult(R.string.delete_account_confirm_title, R.string.delete_account_confirm_message, Setting.DELETE_ACCOUNT.ordinal) } } } @@ -107,19 +112,25 @@ class MyPageFragment : Fragment(), ConfirmDialogFragment.OnDialogResultListener Setting.LOGOUT, ContextCompat.getDrawable(requireActivity(), R.drawable.ic_logout), getString(R.string.logout) + ), + SettingItemInfo( + Setting.DELETE_ACCOUNT, + ContextCompat.getDrawable(requireActivity(), R.drawable.ic_close_red), + getString(R.string.delete_account) ) ) } - private fun showConfirmationDialogForResult() { + private fun showConfirmationDialogForResult(@StringRes title: Int, @StringRes message: Int, requestCode: Int) { val tag = "confirm_dialog_fragment_from_activity" if (requireActivity().supportFragmentManager.findFragmentByTag(tag) != null) return val dialogFragment = ConfirmDialogFragment() val bundle = Bundle() - bundle.putString("title", getString(R.string.logout_confirm_title)) - bundle.putString("message", getString(R.string.logout_confirm_message)) + bundle.putString("title", getString(title)) + bundle.putString("message", getString(message)) bundle.putString("actionString", DialogConfirmAction.CUSTOM.name) + bundle.putInt("requestCode", requestCode) dialogFragment.arguments = bundle dialogFragment.setOnDialogResultListener(this) dialogFragment.show(requireActivity().supportFragmentManager, tag) @@ -131,9 +142,10 @@ class MyPageFragment : Fragment(), ConfirmDialogFragment.OnDialogResultListener requireActivity().finish() } - override fun onDialogResult(result: Boolean) { - if (result) { - myPageViewModel.logout() + override fun onDialogResult(requestCode: Int, result: Boolean) { + when (requestCode) { + Setting.LOGOUT.ordinal -> myPageViewModel.logout() + Setting.DELETE_ACCOUNT.ordinal -> myPageViewModel.deleteAccount() } } diff --git a/android/app/src/main/java/app/priceguard/ui/home/mypage/SettingItemInfo.kt b/android/app/src/main/java/app/priceguard/ui/home/mypage/SettingItemInfo.kt index 3b53bb6..6462bc3 100644 --- a/android/app/src/main/java/app/priceguard/ui/home/mypage/SettingItemInfo.kt +++ b/android/app/src/main/java/app/priceguard/ui/home/mypage/SettingItemInfo.kt @@ -12,5 +12,6 @@ enum class Setting { NOTIFICATION, THEME, LICENSE, - LOGOUT + LOGOUT, + DELETE_ACCOUNT } diff --git a/android/app/src/main/java/app/priceguard/ui/util/ConfirmDialogFragment.kt b/android/app/src/main/java/app/priceguard/ui/util/ConfirmDialogFragment.kt index f68a051..dad9da5 100644 --- a/android/app/src/main/java/app/priceguard/ui/util/ConfirmDialogFragment.kt +++ b/android/app/src/main/java/app/priceguard/ui/util/ConfirmDialogFragment.kt @@ -35,7 +35,7 @@ class ConfirmDialogFragment : DialogFragment() { } DialogConfirmAction.CUSTOM -> { - resultListener?.onDialogResult(true) + resultListener?.onDialogResult(getRequestCode(), true) } DialogConfirmAction.HOME -> { @@ -77,6 +77,10 @@ class ConfirmDialogFragment : DialogFragment() { requireActivity().finish() } + private fun getRequestCode(): Int { + return arguments?.getInt("requestCode") ?: 0 + } + override fun onStart() { super.onStart() @@ -92,6 +96,6 @@ class ConfirmDialogFragment : DialogFragment() { } interface OnDialogResultListener { - fun onDialogResult(result: Boolean) + fun onDialogResult(requestCode: Int, result: Boolean) } } From 70d671bdc6e3c215ed2ea5703b908fd06150b69d Mon Sep 17 00:00:00 2001 From: ootr47 Date: Thu, 28 Dec 2023 16:38:29 +0900 Subject: [PATCH 04/70] =?UTF-8?q?feat:=20=ED=9A=8C=EC=9B=90=ED=83=88?= =?UTF-8?q?=ED=87=B4=20=ED=85=8D=EC=8A=A4=ED=8A=B8=20=EC=83=89=EC=83=81=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/priceguard/ui/home/mypage/MyPageSettingAdapter.kt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/android/app/src/main/java/app/priceguard/ui/home/mypage/MyPageSettingAdapter.kt b/android/app/src/main/java/app/priceguard/ui/home/mypage/MyPageSettingAdapter.kt index a182807..21467e3 100644 --- a/android/app/src/main/java/app/priceguard/ui/home/mypage/MyPageSettingAdapter.kt +++ b/android/app/src/main/java/app/priceguard/ui/home/mypage/MyPageSettingAdapter.kt @@ -1,5 +1,7 @@ package app.priceguard.ui.home.mypage +import android.R +import android.util.TypedValue import android.view.LayoutInflater import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView @@ -32,6 +34,12 @@ class MyPageSettingAdapter( with(binding) { settingItemInfo = item listener = clickListener + + if (item.id == Setting.DELETE_ACCOUNT) { + val typedValue = TypedValue() + binding.root.context.theme.resolveAttribute(R.attr.colorError, typedValue, true) + tvMyPageItemTitle.setTextColor(typedValue.data) + } } } } From acb2a7e59eee2cc94465eb8f4de537474a78fc09 Mon Sep 17 00:00:00 2001 From: ootr47 Date: Thu, 28 Dec 2023 16:38:41 +0900 Subject: [PATCH 05/70] =?UTF-8?q?feat:=20=EB=AC=B8=EC=9E=90=EC=97=B4=20?= =?UTF-8?q?=EB=A6=AC=EC=86=8C=EC=8A=A4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- android/app/src/main/res/values/strings.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml index 148d8e3..741445b 100644 --- a/android/app/src/main/res/values/strings.xml +++ b/android/app/src/main/res/values/strings.xml @@ -133,4 +133,7 @@ 0 999999999 Product Price Notification + 회원 탈퇴 + 회원 탈퇴 확인 + 정말로 회원 탈퇴 하시겠습니까? \ No newline at end of file From 1a9ee8e2f68c3ab4ab6caec9aaa5d1bdbd0a7036 Mon Sep 17 00:00:00 2001 From: ootr47 Date: Tue, 2 Jan 2024 21:31:44 +0900 Subject: [PATCH 06/70] =?UTF-8?q?refactor:=20=EB=A6=AC=ED=8F=AC=EB=A7=B7,?= =?UTF-8?q?=20private=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/home/mypage/MyPageFragment.kt | 18 +++++++++++++++--- .../ui/home/mypage/MyPageViewModel.kt | 4 ++-- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/android/app/src/main/java/app/priceguard/ui/home/mypage/MyPageFragment.kt b/android/app/src/main/java/app/priceguard/ui/home/mypage/MyPageFragment.kt index 141a782..3c32e60 100644 --- a/android/app/src/main/java/app/priceguard/ui/home/mypage/MyPageFragment.kt +++ b/android/app/src/main/java/app/priceguard/ui/home/mypage/MyPageFragment.kt @@ -79,11 +79,19 @@ class MyPageFragment : Fragment(), ConfirmDialogFragment.OnDialogResultListener } Setting.LOGOUT -> { - showConfirmationDialogForResult(R.string.logout_confirm_title, R.string.logout_confirm_message, Setting.LOGOUT.ordinal) + showConfirmationDialogForResult( + R.string.logout_confirm_title, + R.string.logout_confirm_message, + Setting.LOGOUT.ordinal + ) } Setting.DELETE_ACCOUNT -> { - showConfirmationDialogForResult(R.string.delete_account_confirm_title, R.string.delete_account_confirm_message, Setting.DELETE_ACCOUNT.ordinal) + showConfirmationDialogForResult( + R.string.delete_account_confirm_title, + R.string.delete_account_confirm_message, + Setting.DELETE_ACCOUNT.ordinal + ) } } } @@ -121,7 +129,11 @@ class MyPageFragment : Fragment(), ConfirmDialogFragment.OnDialogResultListener ) } - private fun showConfirmationDialogForResult(@StringRes title: Int, @StringRes message: Int, requestCode: Int) { + private fun showConfirmationDialogForResult( + @StringRes title: Int, + @StringRes message: Int, + requestCode: Int + ) { val tag = "confirm_dialog_fragment_from_activity" if (requireActivity().supportFragmentManager.findFragmentByTag(tag) != null) return diff --git a/android/app/src/main/java/app/priceguard/ui/home/mypage/MyPageViewModel.kt b/android/app/src/main/java/app/priceguard/ui/home/mypage/MyPageViewModel.kt index 193018a..3a371a4 100644 --- a/android/app/src/main/java/app/priceguard/ui/home/mypage/MyPageViewModel.kt +++ b/android/app/src/main/java/app/priceguard/ui/home/mypage/MyPageViewModel.kt @@ -14,8 +14,8 @@ import kotlinx.coroutines.launch @HiltViewModel class MyPageViewModel @Inject constructor( - val authRepository: AuthRepository, - val tokenRepository: TokenRepository + private val authRepository: AuthRepository, + private val tokenRepository: TokenRepository ) : ViewModel() { sealed class MyPageEvent { From 9d9f08dbffb72723839f56a7ea5ac33b8a01c1ca Mon Sep 17 00:00:00 2001 From: ootr47 Date: Fri, 5 Jan 2024 16:34:02 +0900 Subject: [PATCH 07/70] =?UTF-8?q?feat:=20Custom=20Slider=20View=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- android/app/src/main/AndroidManifest.xml | 14 +- .../ui/slider/CustomSliderEventListener.kt | 3 + .../app/priceguard/ui/slider/RoundSlider.kt | 210 ++++++++++++++++++ .../ui/slider/RoundSliderActivity.kt | 24 ++ .../main/res/layout/activity_round_slider.xml | 25 +++ 5 files changed, 271 insertions(+), 5 deletions(-) create mode 100644 android/app/src/main/java/app/priceguard/ui/slider/CustomSliderEventListener.kt create mode 100644 android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt create mode 100644 android/app/src/main/java/app/priceguard/ui/slider/RoundSliderActivity.kt create mode 100644 android/app/src/main/res/layout/activity_round_slider.xml diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index fd71dcf..d3c8499 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -14,6 +14,15 @@ android:supportsRtl="true" android:theme="@style/Theme.PriceGuard" tools:targetApi="34"> + + + + + + + - - - - - \ No newline at end of file diff --git a/android/app/src/main/java/app/priceguard/ui/slider/CustomSliderEventListener.kt b/android/app/src/main/java/app/priceguard/ui/slider/CustomSliderEventListener.kt new file mode 100644 index 0000000..065e70d --- /dev/null +++ b/android/app/src/main/java/app/priceguard/ui/slider/CustomSliderEventListener.kt @@ -0,0 +1,3 @@ +package app.priceguard.ui.slider + +typealias sliderValueChangeListener = (value: Int) -> Unit diff --git a/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt b/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt new file mode 100644 index 0000000..cb151fe --- /dev/null +++ b/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt @@ -0,0 +1,210 @@ +package app.priceguard.ui.slider + +import android.content.Context +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.Paint +import android.graphics.RectF +import android.util.AttributeSet +import android.util.Log +import android.view.MotionEvent +import android.view.View +import kotlin.math.atan +import kotlin.math.cos +import kotlin.math.sin + +class RoundSlider @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0, + defStyleRes: Int = 0 +) : View(context, attrs, defStyleAttr, defStyleRes) { + + private var width = 0f + private var height = 0f + + private val slideBarPaint = Paint() + private val controllerPaint = Paint() + private val sliderValuePaint = Paint() + + private var controllerPointX = 0f + private var controllerPointY = 0f + + private var slideBarPointX = 0f + private var slideBarPointY = 0f + + private var customViewClickListener: sliderValueChangeListener? = null + + private var state = false + + private val pi = Math.PI.toFloat() + + private var sliderValue = 50 + set(value) { + if(field != value){ + field = value + handleValueChangeEvent(value) + } + } + + // TODO : width와 height로 적정 크기 계산하기 마진도 추가!! + var slideBarRadius = 400f + var controllerRadius = 40f + + var slideBarStrokeWidth = 20f + + var maxPecentValue = 100F + + var margin = 30f + + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec) + Log.d("CustomSlider", "onMeasure") + + // 뷰 크기 모드 체크 + val viewWidthMode = MeasureSpec.getMode(widthMeasureSpec) + val viewHeightMode = MeasureSpec.getMode(heightMeasureSpec) + + // 뷰 크기 값 체크 + val viewWidthSize = MeasureSpec.getSize(widthMeasureSpec) + val viewHeightSize = MeasureSpec.getSize(heightMeasureSpec) + + + // 크기 모드에 따라 setMeasuredDimension() 메서드로 뷰의 영역 크기를 설정한다. + if(viewWidthMode == MeasureSpec.EXACTLY && viewHeightMode == MeasureSpec.EXACTLY){ + // XML에서 뷰의 크기가 특정 값으로 설정된 경우, 그대로 사용한다. + setMeasuredDimension(viewWidthSize, viewHeightSize) + }else{ + // wrap_content이거나, 지정되지 않은 경우, 뷰의 크기를 내부에서 지정해주어야 한다 + setMeasuredDimension(1000, 550) + } + } + + override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) { + super.onSizeChanged(w, h, oldw, oldh) + Log.d("CustomSlider", "onSizeChanged") + + width = getWidth().toFloat() + height = getHeight().toFloat() - controllerRadius - margin + + slideBarPointX = width / 2 + slideBarPointY = height + + val rad = 1.8F*(maxPecentValue-sliderValue).toRadian() + controllerPointX = width / 2 + cos(rad) * slideBarRadius + controllerPointY = height + sin(-rad) * slideBarRadius + } + + override fun onDraw(canvas: Canvas) { + super.onDraw(canvas) + Log.d("CustomSlider", "onDraw") + + drawSlideBar(canvas) + drawController(canvas) + drawSlideValueText(canvas) + } + + private fun drawController(canvas: Canvas) { + controllerPaint.style = Paint.Style.FILL + controllerPaint.color = Color.BLUE + + canvas.drawCircle(controllerPointX, controllerPointY, controllerRadius, controllerPaint) + } + + private fun drawSlideBar(canvas: Canvas) { + slideBarPaint.style = Paint.Style.STROKE + slideBarPaint.strokeWidth = slideBarStrokeWidth + + val oval = RectF() + oval.set( + slideBarPointX - slideBarRadius, + slideBarPointY - slideBarRadius, + slideBarPointX + slideBarRadius, + slideBarPointY + slideBarRadius + ) + + canvas.drawArc(oval, 180F, 180F, false, slideBarPaint) + } + + private fun drawSlideValueText(canvas: Canvas) { + sliderValuePaint.textSize = 48f + canvas.drawText(sliderValue.toString(), slideBarPointX, slideBarPointY, sliderValuePaint) + } + + override fun onTouchEvent(event: MotionEvent?): Boolean { + if (event != null) { + when (event.action) { + MotionEvent.ACTION_MOVE -> { + // 터치 좌표 x에 맞게 컨트롤러의 y좌표 설정 (y좌표만 움직이면 controller 이동하지 않음) + + if (event.y > slideBarPointY) { + if(state) { + if(event.x >= slideBarPointX){ + controllerPointX = width / 2 + slideBarRadius + controllerPointY = height + sliderValue = degreeToValue(0F) + } else { + controllerPointX = width / 2 - slideBarRadius + controllerPointY = height + sliderValue = degreeToValue(180F) + } + invalidate() + state = false + } + return true + } + + state = true + val rad = calculateRadToPoint(event.x, event.y) + + controllerPointX = width / 2 + cos(rad) * slideBarRadius + controllerPointY = height + sin(-rad) * slideBarRadius + + sliderValue = degreeToValue(rad.toDegree()) + + invalidate() + } + + MotionEvent.ACTION_UP -> { + state = false + } + } + } + return true + } + + private fun Float.toRadian(): Float { + return this * pi / 180F + } + + private fun Float.toDegree(): Float { + return this * 180F / pi + } + + private fun calculateRadToPoint(x: Float, y: Float): Float { + val arcTan = atan((x - slideBarPointX) / (y - slideBarPointY)) + return (pi / 2) + arcTan + } + + private fun degreeToValue(degree: Float): Int { + return ((180F - degree) / (180F / maxPecentValue)).toInt() + } + + fun setValue(value: Int) { + Log.d("CustomSlider", "setValue") + controllerPointX = width / 2 + cos(value * pi / maxPecentValue) * slideBarRadius + controllerPointY = height + sin(-value * pi / maxPecentValue) * slideBarRadius + sliderValue = value + invalidate() + } + + + + private fun handleValueChangeEvent(value: Int) { + customViewClickListener?.invoke(value) + } + + fun setSliderValueChangeListener(listener: sliderValueChangeListener) { + customViewClickListener = listener + } +} diff --git a/android/app/src/main/java/app/priceguard/ui/slider/RoundSliderActivity.kt b/android/app/src/main/java/app/priceguard/ui/slider/RoundSliderActivity.kt new file mode 100644 index 0000000..855b700 --- /dev/null +++ b/android/app/src/main/java/app/priceguard/ui/slider/RoundSliderActivity.kt @@ -0,0 +1,24 @@ +package app.priceguard.ui.slider + +import androidx.appcompat.app.AppCompatActivity +import android.os.Bundle +import android.util.Log +import app.priceguard.R +import app.priceguard.databinding.ActivityRoundSliderBinding + +class RoundSliderActivity : AppCompatActivity() { + + private lateinit var binding: ActivityRoundSliderBinding + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + binding = ActivityRoundSliderBinding.inflate(layoutInflater) + setContentView(binding.root) + + binding.roundSlider.setValue(30) + binding.roundSlider.setSliderValueChangeListener { value -> + Log.d("slideValueChange", value.toString()) + } + } +} diff --git a/android/app/src/main/res/layout/activity_round_slider.xml b/android/app/src/main/res/layout/activity_round_slider.xml new file mode 100644 index 0000000..b54ee14 --- /dev/null +++ b/android/app/src/main/res/layout/activity_round_slider.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + \ No newline at end of file From 92fdadfdfbcbe871a8cfbd817f9c060f56d12040 Mon Sep 17 00:00:00 2001 From: ootr47 Date: Fri, 5 Jan 2024 17:07:20 +0900 Subject: [PATCH 08/70] =?UTF-8?q?feat=20:=20Dp,=20Px=20=EC=B6=94=EA=B0=80,?= =?UTF-8?q?=20=EC=8A=AC=EB=9D=BC=EC=9D=B4=EB=8D=94=20=ED=8A=B9=EC=A0=95=20?= =?UTF-8?q?=EB=B6=80=EB=B6=84=20=EC=83=89=EC=83=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/priceguard/ui/slider/RoundSlider.kt | 54 +++++++++++++----- .../java/app/priceguard/ui/slider/util.kt | 57 +++++++++++++++++++ 2 files changed, 98 insertions(+), 13 deletions(-) create mode 100644 android/app/src/main/java/app/priceguard/ui/slider/util.kt diff --git a/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt b/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt index cb151fe..e8d464c 100644 --- a/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt +++ b/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt @@ -4,6 +4,7 @@ import android.content.Context import android.graphics.Canvas import android.graphics.Color import android.graphics.Paint +import android.graphics.Rect import android.graphics.RectF import android.util.AttributeSet import android.util.Log @@ -41,7 +42,7 @@ class RoundSlider @JvmOverloads constructor( private var sliderValue = 50 set(value) { - if(field != value){ + if (field != value) { field = value handleValueChangeEvent(value) } @@ -51,11 +52,11 @@ class RoundSlider @JvmOverloads constructor( var slideBarRadius = 400f var controllerRadius = 40f - var slideBarStrokeWidth = 20f + var slideBarStrokeWidth = Dp(8F).toPx(context).value var maxPecentValue = 100F - var margin = 30f + var margin = Dp(8F).toPx(context).value override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { super.onMeasure(widthMeasureSpec, heightMeasureSpec) @@ -71,10 +72,10 @@ class RoundSlider @JvmOverloads constructor( // 크기 모드에 따라 setMeasuredDimension() 메서드로 뷰의 영역 크기를 설정한다. - if(viewWidthMode == MeasureSpec.EXACTLY && viewHeightMode == MeasureSpec.EXACTLY){ + if (viewWidthMode == MeasureSpec.EXACTLY && viewHeightMode == MeasureSpec.EXACTLY) { // XML에서 뷰의 크기가 특정 값으로 설정된 경우, 그대로 사용한다. setMeasuredDimension(viewWidthSize, viewHeightSize) - }else{ + } else { // wrap_content이거나, 지정되지 않은 경우, 뷰의 크기를 내부에서 지정해주어야 한다 setMeasuredDimension(1000, 550) } @@ -83,23 +84,24 @@ class RoundSlider @JvmOverloads constructor( override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) { super.onSizeChanged(w, h, oldw, oldh) Log.d("CustomSlider", "onSizeChanged") - + width = getWidth().toFloat() height = getHeight().toFloat() - controllerRadius - margin slideBarPointX = width / 2 slideBarPointY = height - val rad = 1.8F*(maxPecentValue-sliderValue).toRadian() + val rad = 1.8F * (maxPecentValue - sliderValue).toRadian() controllerPointX = width / 2 + cos(rad) * slideBarRadius controllerPointY = height + sin(-rad) * slideBarRadius } - + override fun onDraw(canvas: Canvas) { super.onDraw(canvas) Log.d("CustomSlider", "onDraw") drawSlideBar(canvas) + drawPointSlideBar(canvas) drawController(canvas) drawSlideValueText(canvas) } @@ -114,6 +116,7 @@ class RoundSlider @JvmOverloads constructor( private fun drawSlideBar(canvas: Canvas) { slideBarPaint.style = Paint.Style.STROKE slideBarPaint.strokeWidth = slideBarStrokeWidth + slideBarPaint.color = Color.GRAY val oval = RectF() oval.set( @@ -126,9 +129,35 @@ class RoundSlider @JvmOverloads constructor( canvas.drawArc(oval, 180F, 180F, false, slideBarPaint) } + private fun drawPointSlideBar(canvas: Canvas) { + slideBarPaint.color = Color.RED + + val oval = RectF() + oval.set( + slideBarPointX - slideBarRadius, + slideBarPointY - slideBarRadius, + slideBarPointX + slideBarRadius, + slideBarPointY + slideBarRadius + ) + + canvas.drawArc(oval, 270F, 30F, false, slideBarPaint) + } + private fun drawSlideValueText(canvas: Canvas) { - sliderValuePaint.textSize = 48f - canvas.drawText(sliderValue.toString(), slideBarPointX, slideBarPointY, sliderValuePaint) + sliderValuePaint.textSize = 88f + val bounds = Rect() + + val textString = sliderValue.toString() + sliderValuePaint.getTextBounds(textString, 0, textString.length, bounds) + + val textWidth = bounds.width() + val textHeight = bounds.height() + canvas.drawText( + textString, + slideBarPointX - textWidth / 2, + slideBarPointY, + sliderValuePaint + ) } override fun onTouchEvent(event: MotionEvent?): Boolean { @@ -138,8 +167,8 @@ class RoundSlider @JvmOverloads constructor( // 터치 좌표 x에 맞게 컨트롤러의 y좌표 설정 (y좌표만 움직이면 controller 이동하지 않음) if (event.y > slideBarPointY) { - if(state) { - if(event.x >= slideBarPointX){ + if (state) { + if (event.x >= slideBarPointX) { controllerPointX = width / 2 + slideBarRadius controllerPointY = height sliderValue = degreeToValue(0F) @@ -199,7 +228,6 @@ class RoundSlider @JvmOverloads constructor( } - private fun handleValueChangeEvent(value: Int) { customViewClickListener?.invoke(value) } diff --git a/android/app/src/main/java/app/priceguard/ui/slider/util.kt b/android/app/src/main/java/app/priceguard/ui/slider/util.kt new file mode 100644 index 0000000..12734c6 --- /dev/null +++ b/android/app/src/main/java/app/priceguard/ui/slider/util.kt @@ -0,0 +1,57 @@ +package app.priceguard.ui.slider + +import android.content.Context + +data class Px(val value: Float) + +data class Dp(val value: Float) + +fun Px.toDp(context: Context): Dp { + val density = context.resources.displayMetrics.density + return Dp(value / density) +} + +operator fun Px.plus(other: Px): Px { + return Px(value + other.value) +} + +operator fun Px.minus(other: Px): Px { + return Px(value - other.value) +} + +operator fun Px.times(other: Px): Px { + return Px(value * other.value) +} + +operator fun Px.div(other: Px): Px { + return Px(value / other.value) +} + +operator fun Px.rem(other: Px): Px { + return Px(value % other.value) +} + +fun Dp.toPx(context: Context): Px { + val density = context.resources.displayMetrics.density + return Px(value * density) +} + +operator fun Dp.plus(other: Dp): Dp { + return Dp(value + other.value) +} + +operator fun Dp.minus(other: Dp): Dp { + return Dp(value - other.value) +} + +operator fun Dp.times(other: Dp): Dp { + return Dp(value * other.value) +} + +operator fun Dp.div(other: Dp): Dp { + return Dp(value / other.value) +} + +operator fun Dp.rem(other: Dp): Dp { + return Dp(value % other.value) +} From 914dba95731d20a4b00c3c8bde1c594f9270e065 Mon Sep 17 00:00:00 2001 From: ootr47 Date: Fri, 5 Jan 2024 17:33:16 +0900 Subject: [PATCH 09/70] =?UTF-8?q?feat:=20=ED=81=AC=EA=B8=B0=20=EB=8F=99?= =?UTF-8?q?=EC=A0=81=20=EB=B3=80=EA=B2=BD,=20=EB=B7=B0=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=ED=81=AC=EA=B8=B0=20=EC=A1=B0?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/priceguard/ui/slider/RoundSlider.kt | 43 ++++++++++--------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt b/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt index e8d464c..8c1dd14 100644 --- a/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt +++ b/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt @@ -49,14 +49,14 @@ class RoundSlider @JvmOverloads constructor( } // TODO : width와 height로 적정 크기 계산하기 마진도 추가!! - var slideBarRadius = 400f - var controllerRadius = 40f - var slideBarStrokeWidth = Dp(8F).toPx(context).value var maxPecentValue = 100F - var margin = Dp(8F).toPx(context).value + var margin = Dp(24F).toPx(context).value + + var slideBarRadius = 0F + var controllerRadius = Dp(8F).toPx(context).value override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { super.onMeasure(widthMeasureSpec, heightMeasureSpec) @@ -75,9 +75,13 @@ class RoundSlider @JvmOverloads constructor( if (viewWidthMode == MeasureSpec.EXACTLY && viewHeightMode == MeasureSpec.EXACTLY) { // XML에서 뷰의 크기가 특정 값으로 설정된 경우, 그대로 사용한다. setMeasuredDimension(viewWidthSize, viewHeightSize) + width = viewWidthSize.toFloat() + height = viewHeightSize.toFloat() } else { // wrap_content이거나, 지정되지 않은 경우, 뷰의 크기를 내부에서 지정해주어야 한다 - setMeasuredDimension(1000, 550) + width = 1000F + height = width / 2 + margin * 2 + controllerRadius + setMeasuredDimension(width.toInt(), height.toInt()) } } @@ -85,15 +89,14 @@ class RoundSlider @JvmOverloads constructor( super.onSizeChanged(w, h, oldw, oldh) Log.d("CustomSlider", "onSizeChanged") - width = getWidth().toFloat() - height = getHeight().toFloat() - controllerRadius - margin - slideBarPointX = width / 2 - slideBarPointY = height + slideBarPointY = height - margin - controllerRadius + + slideBarRadius = width / 2 - margin val rad = 1.8F * (maxPecentValue - sliderValue).toRadian() - controllerPointX = width / 2 + cos(rad) * slideBarRadius - controllerPointY = height + sin(-rad) * slideBarRadius + controllerPointX = slideBarPointX + cos(rad) * slideBarRadius + controllerPointY = slideBarPointY + sin(-rad) * slideBarRadius } override fun onDraw(canvas: Canvas) { @@ -155,7 +158,7 @@ class RoundSlider @JvmOverloads constructor( canvas.drawText( textString, slideBarPointX - textWidth / 2, - slideBarPointY, + slideBarPointY - slideBarRadius / 2 + textHeight, sliderValuePaint ) } @@ -169,12 +172,12 @@ class RoundSlider @JvmOverloads constructor( if (event.y > slideBarPointY) { if (state) { if (event.x >= slideBarPointX) { - controllerPointX = width / 2 + slideBarRadius - controllerPointY = height + controllerPointX = slideBarPointX + slideBarRadius + controllerPointY = slideBarPointY sliderValue = degreeToValue(0F) } else { - controllerPointX = width / 2 - slideBarRadius - controllerPointY = height + controllerPointX = slideBarPointX - slideBarRadius + controllerPointY = slideBarPointY sliderValue = degreeToValue(180F) } invalidate() @@ -186,8 +189,8 @@ class RoundSlider @JvmOverloads constructor( state = true val rad = calculateRadToPoint(event.x, event.y) - controllerPointX = width / 2 + cos(rad) * slideBarRadius - controllerPointY = height + sin(-rad) * slideBarRadius + controllerPointX = slideBarPointX + cos(rad) * slideBarRadius + controllerPointY = slideBarPointY + sin(-rad) * slideBarRadius sliderValue = degreeToValue(rad.toDegree()) @@ -221,8 +224,8 @@ class RoundSlider @JvmOverloads constructor( fun setValue(value: Int) { Log.d("CustomSlider", "setValue") - controllerPointX = width / 2 + cos(value * pi / maxPecentValue) * slideBarRadius - controllerPointY = height + sin(-value * pi / maxPecentValue) * slideBarRadius + controllerPointX = slideBarPointX + cos(value * pi / maxPecentValue) * slideBarRadius + controllerPointY = slideBarPointY + sin(-value * pi / maxPecentValue) * slideBarRadius sliderValue = value invalidate() } From 26e21a96a2615a46c8f2a733fcda498823109631 Mon Sep 17 00:00:00 2001 From: ootr47 Date: Fri, 5 Jan 2024 18:01:52 +0900 Subject: [PATCH 10/70] =?UTF-8?q?refactor:=20=EB=AF=B8=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=20=ED=95=A8=EC=88=98=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/app/priceguard/ui/slider/util.kt | 40 ------------------- 1 file changed, 40 deletions(-) diff --git a/android/app/src/main/java/app/priceguard/ui/slider/util.kt b/android/app/src/main/java/app/priceguard/ui/slider/util.kt index 12734c6..854524f 100644 --- a/android/app/src/main/java/app/priceguard/ui/slider/util.kt +++ b/android/app/src/main/java/app/priceguard/ui/slider/util.kt @@ -11,47 +11,7 @@ fun Px.toDp(context: Context): Dp { return Dp(value / density) } -operator fun Px.plus(other: Px): Px { - return Px(value + other.value) -} - -operator fun Px.minus(other: Px): Px { - return Px(value - other.value) -} - -operator fun Px.times(other: Px): Px { - return Px(value * other.value) -} - -operator fun Px.div(other: Px): Px { - return Px(value / other.value) -} - -operator fun Px.rem(other: Px): Px { - return Px(value % other.value) -} - fun Dp.toPx(context: Context): Px { val density = context.resources.displayMetrics.density return Px(value * density) } - -operator fun Dp.plus(other: Dp): Dp { - return Dp(value + other.value) -} - -operator fun Dp.minus(other: Dp): Dp { - return Dp(value - other.value) -} - -operator fun Dp.times(other: Dp): Dp { - return Dp(value * other.value) -} - -operator fun Dp.div(other: Dp): Dp { - return Dp(value / other.value) -} - -operator fun Dp.rem(other: Dp): Dp { - return Dp(value % other.value) -} From fda03d779dfc048891045d8fd13fceb80028cca6 Mon Sep 17 00:00:00 2001 From: ootr47 Date: Fri, 5 Jan 2024 18:02:39 +0900 Subject: [PATCH 11/70] =?UTF-8?q?feat:=20stroke,=20maxValue=20=EC=86=8D?= =?UTF-8?q?=EC=84=B1=20=EB=B3=80=EA=B2=BD=20=ED=95=A8=EC=88=98=20=EC=A0=9C?= =?UTF-8?q?=EA=B3=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/priceguard/ui/slider/RoundSlider.kt | 23 +++++++++++++------ .../ui/slider/RoundSliderActivity.kt | 5 +++- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt b/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt index 8c1dd14..40377a3 100644 --- a/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt +++ b/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt @@ -48,15 +48,14 @@ class RoundSlider @JvmOverloads constructor( } } - // TODO : width와 height로 적정 크기 계산하기 마진도 추가!! - var slideBarStrokeWidth = Dp(8F).toPx(context).value + private var slideBarStrokeWidth = Dp(8F).toPx(context).value - var maxPecentValue = 100F + private var slideBarRadius = 0F + private var controllerRadius = Dp(12F).toPx(context).value - var margin = Dp(24F).toPx(context).value + private var margin = Dp(24F).toPx(context).value - var slideBarRadius = 0F - var controllerRadius = Dp(8F).toPx(context).value + private var maxPecentValue = 100F override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { super.onMeasure(widthMeasureSpec, heightMeasureSpec) @@ -87,7 +86,7 @@ class RoundSlider @JvmOverloads constructor( override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) { super.onSizeChanged(w, h, oldw, oldh) - Log.d("CustomSlider", "onSizeChanged") + slideBarPointX = width / 2 slideBarPointY = height - margin - controllerRadius @@ -230,6 +229,16 @@ class RoundSlider @JvmOverloads constructor( invalidate() } + fun setSliderStrokeWidth(value: Int) { + slideBarStrokeWidth = Dp(value.toFloat()).toPx(context).value + invalidate() + } + + fun setMaxPercentValue(value: Int) { + maxPecentValue = value.toFloat() + invalidate() + } + private fun handleValueChangeEvent(value: Int) { customViewClickListener?.invoke(value) diff --git a/android/app/src/main/java/app/priceguard/ui/slider/RoundSliderActivity.kt b/android/app/src/main/java/app/priceguard/ui/slider/RoundSliderActivity.kt index 855b700..872dca4 100644 --- a/android/app/src/main/java/app/priceguard/ui/slider/RoundSliderActivity.kt +++ b/android/app/src/main/java/app/priceguard/ui/slider/RoundSliderActivity.kt @@ -16,7 +16,10 @@ class RoundSliderActivity : AppCompatActivity() { binding = ActivityRoundSliderBinding.inflate(layoutInflater) setContentView(binding.root) - binding.roundSlider.setValue(30) + binding.roundSlider.setMaxPercentValue(180) + binding.roundSlider.setValue(10) + binding.roundSlider.setSliderStrokeWidth(4) + binding.roundSlider.setSliderValueChangeListener { value -> Log.d("slideValueChange", value.toString()) } From 21e1d24047df7a1c41cdc1f91f037abb4966d96d Mon Sep 17 00:00:00 2001 From: ootr47 Date: Fri, 5 Jan 2024 18:02:57 +0900 Subject: [PATCH 12/70] =?UTF-8?q?fix:=20=EB=9D=BC=EB=94=94=EC=95=88=20?= =?UTF-8?q?=EA=B3=84=EC=82=B0=EC=8B=9D=20=EC=98=A4=EB=A5=98=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt b/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt index 40377a3..2152ca5 100644 --- a/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt +++ b/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt @@ -93,7 +93,7 @@ class RoundSlider @JvmOverloads constructor( slideBarRadius = width / 2 - margin - val rad = 1.8F * (maxPecentValue - sliderValue).toRadian() + val rad = (180 / maxPecentValue * (maxPecentValue - sliderValue)).toRadian() controllerPointX = slideBarPointX + cos(rad) * slideBarRadius controllerPointY = slideBarPointY + sin(-rad) * slideBarRadius } From faac70ec5bc36e014d2ba0cd1afd2fa5c3fee05f Mon Sep 17 00:00:00 2001 From: ootr47 Date: Fri, 5 Jan 2024 18:18:00 +0900 Subject: [PATCH 13/70] =?UTF-8?q?feat:=20=EC=8A=AC=EB=9D=BC=EC=9D=B4?= =?UTF-8?q?=EB=8D=94=20=ED=8F=AC=EC=9D=B8=ED=84=B0=20=EB=B2=94=EC=9C=84=20?= =?UTF-8?q?=EC=A7=80=EC=A0=95=20=ED=95=A8=EC=88=98=20=EC=A0=9C=EA=B3=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/app/priceguard/ui/slider/RoundSlider.kt | 12 ++++++++++-- .../app/priceguard/ui/slider/RoundSliderActivity.kt | 1 + 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt b/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt index 2152ca5..77d1a67 100644 --- a/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt +++ b/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt @@ -57,6 +57,9 @@ class RoundSlider @JvmOverloads constructor( private var maxPecentValue = 100F + private var startDegree = 270F + private var endDegree = 300F + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { super.onMeasure(widthMeasureSpec, heightMeasureSpec) Log.d("CustomSlider", "onMeasure") @@ -141,8 +144,7 @@ class RoundSlider @JvmOverloads constructor( slideBarPointX + slideBarRadius, slideBarPointY + slideBarRadius ) - - canvas.drawArc(oval, 270F, 30F, false, slideBarPaint) + canvas.drawArc(oval, startDegree, endDegree - startDegree, false, slideBarPaint) } private fun drawSlideValueText(canvas: Canvas) { @@ -239,6 +241,12 @@ class RoundSlider @JvmOverloads constructor( invalidate() } + fun setPointRange(startValue: Int, endValue: Int) { + startDegree = (180 / maxPecentValue * startValue) + 180 + endDegree = (180 / maxPecentValue * endValue) + 180 + invalidate() + } + private fun handleValueChangeEvent(value: Int) { customViewClickListener?.invoke(value) diff --git a/android/app/src/main/java/app/priceguard/ui/slider/RoundSliderActivity.kt b/android/app/src/main/java/app/priceguard/ui/slider/RoundSliderActivity.kt index 872dca4..893c12c 100644 --- a/android/app/src/main/java/app/priceguard/ui/slider/RoundSliderActivity.kt +++ b/android/app/src/main/java/app/priceguard/ui/slider/RoundSliderActivity.kt @@ -19,6 +19,7 @@ class RoundSliderActivity : AppCompatActivity() { binding.roundSlider.setMaxPercentValue(180) binding.roundSlider.setValue(10) binding.roundSlider.setSliderStrokeWidth(4) + binding.roundSlider.setPointRange(100, 120) binding.roundSlider.setSliderValueChangeListener { value -> Log.d("slideValueChange", value.toString()) From f5536caad8f1a946f25334e53cb605922a7e9946 Mon Sep 17 00:00:00 2001 From: ootr47 Date: Fri, 5 Jan 2024 18:26:10 +0900 Subject: [PATCH 14/70] =?UTF-8?q?feat:=20Sp=20=ED=81=B4=EB=9E=98=EC=8A=A4?= =?UTF-8?q?=20=EB=B0=8F=20=EB=B3=80=ED=99=98=20=ED=95=A8=EC=88=98=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/app/priceguard/ui/slider/RoundSlider.kt | 4 +++- .../src/main/java/app/priceguard/ui/slider/util.kt | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt b/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt index 77d1a67..fb1fdf0 100644 --- a/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt +++ b/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt @@ -60,6 +60,8 @@ class RoundSlider @JvmOverloads constructor( private var startDegree = 270F private var endDegree = 300F + private var textValueSize = Sp(32F) + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { super.onMeasure(widthMeasureSpec, heightMeasureSpec) Log.d("CustomSlider", "onMeasure") @@ -148,7 +150,7 @@ class RoundSlider @JvmOverloads constructor( } private fun drawSlideValueText(canvas: Canvas) { - sliderValuePaint.textSize = 88f + sliderValuePaint.textSize = textValueSize.toPx(context).value val bounds = Rect() val textString = sliderValue.toString() diff --git a/android/app/src/main/java/app/priceguard/ui/slider/util.kt b/android/app/src/main/java/app/priceguard/ui/slider/util.kt index 854524f..6e8a7cc 100644 --- a/android/app/src/main/java/app/priceguard/ui/slider/util.kt +++ b/android/app/src/main/java/app/priceguard/ui/slider/util.kt @@ -1,11 +1,14 @@ package app.priceguard.ui.slider import android.content.Context +import android.util.TypedValue data class Px(val value: Float) data class Dp(val value: Float) +data class Sp(val value: Float) + fun Px.toDp(context: Context): Dp { val density = context.resources.displayMetrics.density return Dp(value / density) @@ -15,3 +18,14 @@ fun Dp.toPx(context: Context): Px { val density = context.resources.displayMetrics.density return Px(value * density) } + +fun Sp.toPx(context: Context): Px { + return Px( + TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_SP, + value, + context.resources.displayMetrics + ) + ) +} + From 4f90163e2ef97c574bb56fd56e4fecd1fa94e1ef Mon Sep 17 00:00:00 2001 From: ootr47 Date: Fri, 5 Jan 2024 18:27:46 +0900 Subject: [PATCH 15/70] =?UTF-8?q?refactor:=20=EB=A6=AC=ED=8F=AC=EB=A7=B7?= =?UTF-8?q?=20=EB=B0=8F=20=ED=95=A8=EC=88=98=20=EC=9C=84=EC=B9=98=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/priceguard/ui/slider/RoundSlider.kt | 20 +++---------------- .../ui/slider/RoundSliderActivity.kt | 3 +-- .../java/app/priceguard/ui/slider/util.kt | 7 +++++++ 3 files changed, 11 insertions(+), 19 deletions(-) diff --git a/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt b/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt index fb1fdf0..773e072 100644 --- a/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt +++ b/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt @@ -64,7 +64,6 @@ class RoundSlider @JvmOverloads constructor( override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { super.onMeasure(widthMeasureSpec, heightMeasureSpec) - Log.d("CustomSlider", "onMeasure") // 뷰 크기 모드 체크 val viewWidthMode = MeasureSpec.getMode(widthMeasureSpec) @@ -74,7 +73,6 @@ class RoundSlider @JvmOverloads constructor( val viewWidthSize = MeasureSpec.getSize(widthMeasureSpec) val viewHeightSize = MeasureSpec.getSize(heightMeasureSpec) - // 크기 모드에 따라 setMeasuredDimension() 메서드로 뷰의 영역 크기를 설정한다. if (viewWidthMode == MeasureSpec.EXACTLY && viewHeightMode == MeasureSpec.EXACTLY) { // XML에서 뷰의 크기가 특정 값으로 설정된 경우, 그대로 사용한다. @@ -92,7 +90,6 @@ class RoundSlider @JvmOverloads constructor( override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) { super.onSizeChanged(w, h, oldw, oldh) - slideBarPointX = width / 2 slideBarPointY = height - margin - controllerRadius @@ -105,7 +102,6 @@ class RoundSlider @JvmOverloads constructor( override fun onDraw(canvas: Canvas) { super.onDraw(canvas) - Log.d("CustomSlider", "onDraw") drawSlideBar(canvas) drawPointSlideBar(canvas) @@ -208,14 +204,6 @@ class RoundSlider @JvmOverloads constructor( return true } - private fun Float.toRadian(): Float { - return this * pi / 180F - } - - private fun Float.toDegree(): Float { - return this * 180F / pi - } - private fun calculateRadToPoint(x: Float, y: Float): Float { val arcTan = atan((x - slideBarPointX) / (y - slideBarPointY)) return (pi / 2) + arcTan @@ -226,7 +214,6 @@ class RoundSlider @JvmOverloads constructor( } fun setValue(value: Int) { - Log.d("CustomSlider", "setValue") controllerPointX = slideBarPointX + cos(value * pi / maxPecentValue) * slideBarRadius controllerPointY = slideBarPointY + sin(-value * pi / maxPecentValue) * slideBarRadius sliderValue = value @@ -249,12 +236,11 @@ class RoundSlider @JvmOverloads constructor( invalidate() } + fun setSliderValueChangeListener(listener: sliderValueChangeListener) { + customViewClickListener = listener + } private fun handleValueChangeEvent(value: Int) { customViewClickListener?.invoke(value) } - - fun setSliderValueChangeListener(listener: sliderValueChangeListener) { - customViewClickListener = listener - } } diff --git a/android/app/src/main/java/app/priceguard/ui/slider/RoundSliderActivity.kt b/android/app/src/main/java/app/priceguard/ui/slider/RoundSliderActivity.kt index 893c12c..515c0fa 100644 --- a/android/app/src/main/java/app/priceguard/ui/slider/RoundSliderActivity.kt +++ b/android/app/src/main/java/app/priceguard/ui/slider/RoundSliderActivity.kt @@ -1,9 +1,8 @@ package app.priceguard.ui.slider -import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.util.Log -import app.priceguard.R +import androidx.appcompat.app.AppCompatActivity import app.priceguard.databinding.ActivityRoundSliderBinding class RoundSliderActivity : AppCompatActivity() { diff --git a/android/app/src/main/java/app/priceguard/ui/slider/util.kt b/android/app/src/main/java/app/priceguard/ui/slider/util.kt index 6e8a7cc..f6b837f 100644 --- a/android/app/src/main/java/app/priceguard/ui/slider/util.kt +++ b/android/app/src/main/java/app/priceguard/ui/slider/util.kt @@ -29,3 +29,10 @@ fun Sp.toPx(context: Context): Px { ) } +fun Float.toRadian(): Float { + return this * Math.PI.toFloat() / 180F +} + +fun Float.toDegree(): Float { + return this * 180F / Math.PI.toFloat() +} From b0d9960dd0d4bc7f12ee7af97ecc9f0a4a306450 Mon Sep 17 00:00:00 2001 From: ootr47 Date: Fri, 5 Jan 2024 18:29:43 +0900 Subject: [PATCH 16/70] =?UTF-8?q?refactor:=20=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD=20util=20->=20ConvertUt?= =?UTF-8?q?il?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/app/priceguard/ui/slider/{util.kt => ConvertUtil.kt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename android/app/src/main/java/app/priceguard/ui/slider/{util.kt => ConvertUtil.kt} (100%) diff --git a/android/app/src/main/java/app/priceguard/ui/slider/util.kt b/android/app/src/main/java/app/priceguard/ui/slider/ConvertUtil.kt similarity index 100% rename from android/app/src/main/java/app/priceguard/ui/slider/util.kt rename to android/app/src/main/java/app/priceguard/ui/slider/ConvertUtil.kt From f61c29e0237f96f046d42e999020bc1a5b131648 Mon Sep 17 00:00:00 2001 From: ootr47 Date: Mon, 8 Jan 2024 18:37:35 +0900 Subject: [PATCH 17/70] =?UTF-8?q?feat:=20=EC=8A=AC=EB=9D=BC=EC=9D=B4?= =?UTF-8?q?=EB=8D=94=20=EB=B7=B0=20=ED=81=AC=EA=B8=B0=20=EB=8F=99=EC=A0=81?= =?UTF-8?q?=20=EC=84=A4=EC=A0=95=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/priceguard/ui/slider/RoundSlider.kt | 68 +++++++++++++------ 1 file changed, 46 insertions(+), 22 deletions(-) diff --git a/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt b/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt index 773e072..c563c6e 100644 --- a/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt +++ b/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt @@ -7,11 +7,11 @@ import android.graphics.Paint import android.graphics.Rect import android.graphics.RectF import android.util.AttributeSet -import android.util.Log import android.view.MotionEvent import android.view.View import kotlin.math.atan import kotlin.math.cos +import kotlin.math.min import kotlin.math.sin class RoundSlider @JvmOverloads constructor( @@ -34,6 +34,10 @@ class RoundSlider @JvmOverloads constructor( private var slideBarPointX = 0f private var slideBarPointY = 0f + private var btnRadius = Dp(20F).toPx(context).value + private var btnMarginTop = Dp(24F).toPx(context).value + private var btnMarginBottom = Dp(12F).toPx(context).value + private var customViewClickListener: sliderValueChangeListener? = null private var state = false @@ -53,7 +57,7 @@ class RoundSlider @JvmOverloads constructor( private var slideBarRadius = 0F private var controllerRadius = Dp(12F).toPx(context).value - private var margin = Dp(24F).toPx(context).value + private var slideBarMargin = Dp(12F).toPx(context).value + controllerRadius private var maxPecentValue = 100F @@ -73,17 +77,30 @@ class RoundSlider @JvmOverloads constructor( val viewWidthSize = MeasureSpec.getSize(widthMeasureSpec) val viewHeightSize = MeasureSpec.getSize(heightMeasureSpec) - // 크기 모드에 따라 setMeasuredDimension() 메서드로 뷰의 영역 크기를 설정한다. - if (viewWidthMode == MeasureSpec.EXACTLY && viewHeightMode == MeasureSpec.EXACTLY) { - // XML에서 뷰의 크기가 특정 값으로 설정된 경우, 그대로 사용한다. - setMeasuredDimension(viewWidthSize, viewHeightSize) - width = viewWidthSize.toFloat() - height = viewHeightSize.toFloat() + width = if (viewWidthMode == MeasureSpec.EXACTLY) { + viewWidthSize.toFloat() + } else if (viewHeightMode == MeasureSpec.EXACTLY) { + (viewHeightSize.toFloat() - controllerRadius - btnRadius * 2 - btnMarginTop) * 2 + } else { + 700F + } + width = min(width, viewWidthSize.toFloat()) + + height = if (viewHeightMode == MeasureSpec.EXACTLY) { + viewHeightSize.toFloat() } else { - // wrap_content이거나, 지정되지 않은 경우, 뷰의 크기를 내부에서 지정해주어야 한다 - width = 1000F - height = width / 2 + margin * 2 + controllerRadius - setMeasuredDimension(width.toInt(), height.toInt()) + width / 2 + btnRadius * 2 + btnMarginTop + btnMarginBottom + } + height = min(height, viewHeightSize.toFloat()) + + setMeasuredDimension(width.toInt(), height.toInt()) + + // 높이가 필요한 크기보다 클 경우 크기 줄이기 (중앙 정렬을 위함) + if (viewHeightMode == MeasureSpec.EXACTLY) { + val temp = width / 2 + btnRadius * 2 + btnMarginTop + btnMarginBottom + if (height > temp) { + height -= (height - temp) / 2 + } } } @@ -91,9 +108,13 @@ class RoundSlider @JvmOverloads constructor( super.onSizeChanged(w, h, oldw, oldh) slideBarPointX = width / 2 - slideBarPointY = height - margin - controllerRadius + slideBarPointY = height - btnRadius * 2 - btnMarginTop - btnMarginBottom - slideBarRadius = width / 2 - margin + slideBarRadius = if (isHeightEnough()) { + width / 2 - slideBarMargin + } else { + height - btnRadius * 2 - btnMarginTop - slideBarMargin - btnMarginBottom + } val rad = (180 / maxPecentValue * (maxPecentValue - sliderValue)).toRadian() controllerPointX = slideBarPointX + cos(rad) * slideBarRadius @@ -109,13 +130,6 @@ class RoundSlider @JvmOverloads constructor( drawSlideValueText(canvas) } - private fun drawController(canvas: Canvas) { - controllerPaint.style = Paint.Style.FILL - controllerPaint.color = Color.BLUE - - canvas.drawCircle(controllerPointX, controllerPointY, controllerRadius, controllerPaint) - } - private fun drawSlideBar(canvas: Canvas) { slideBarPaint.style = Paint.Style.STROKE slideBarPaint.strokeWidth = slideBarStrokeWidth @@ -128,7 +142,6 @@ class RoundSlider @JvmOverloads constructor( slideBarPointX + slideBarRadius, slideBarPointY + slideBarRadius ) - canvas.drawArc(oval, 180F, 180F, false, slideBarPaint) } @@ -145,6 +158,13 @@ class RoundSlider @JvmOverloads constructor( canvas.drawArc(oval, startDegree, endDegree - startDegree, false, slideBarPaint) } + private fun drawController(canvas: Canvas) { + controllerPaint.style = Paint.Style.FILL + controllerPaint.color = Color.BLUE + + canvas.drawCircle(controllerPointX, controllerPointY, controllerRadius, controllerPaint) + } + private fun drawSlideValueText(canvas: Canvas) { sliderValuePaint.textSize = textValueSize.toPx(context).value val bounds = Rect() @@ -204,6 +224,10 @@ class RoundSlider @JvmOverloads constructor( return true } + private fun isHeightEnough(): Boolean { + return height >= width / 2 + btnMarginBottom + btnRadius * 2 + btnMarginTop + } + private fun calculateRadToPoint(x: Float, y: Float): Float { val arcTan = atan((x - slideBarPointX) / (y - slideBarPointY)) return (pi / 2) + arcTan From d0e5b357199cef20af697e67f79100773d28d814 Mon Sep 17 00:00:00 2001 From: ootr47 Date: Mon, 8 Jan 2024 19:09:21 +0900 Subject: [PATCH 18/70] =?UTF-8?q?feat:=20=EB=B2=84=ED=8A=BC=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20=EB=B3=80=EC=88=98=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/priceguard/ui/slider/RoundSlider.kt | 32 ++++++++----------- 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt b/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt index c563c6e..ccac02f 100644 --- a/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt +++ b/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt @@ -34,10 +34,6 @@ class RoundSlider @JvmOverloads constructor( private var slideBarPointX = 0f private var slideBarPointY = 0f - private var btnRadius = Dp(20F).toPx(context).value - private var btnMarginTop = Dp(24F).toPx(context).value - private var btnMarginBottom = Dp(12F).toPx(context).value - private var customViewClickListener: sliderValueChangeListener? = null private var state = false @@ -59,7 +55,7 @@ class RoundSlider @JvmOverloads constructor( private var slideBarMargin = Dp(12F).toPx(context).value + controllerRadius - private var maxPecentValue = 100F + private var maxPercentValue = 100F private var startDegree = 270F private var endDegree = 300F @@ -80,7 +76,7 @@ class RoundSlider @JvmOverloads constructor( width = if (viewWidthMode == MeasureSpec.EXACTLY) { viewWidthSize.toFloat() } else if (viewHeightMode == MeasureSpec.EXACTLY) { - (viewHeightSize.toFloat() - controllerRadius - btnRadius * 2 - btnMarginTop) * 2 + (viewHeightSize.toFloat() - controllerRadius - slideBarMargin) * 2 } else { 700F } @@ -89,7 +85,7 @@ class RoundSlider @JvmOverloads constructor( height = if (viewHeightMode == MeasureSpec.EXACTLY) { viewHeightSize.toFloat() } else { - width / 2 + btnRadius * 2 + btnMarginTop + btnMarginBottom + width / 2 + slideBarMargin } height = min(height, viewHeightSize.toFloat()) @@ -97,7 +93,7 @@ class RoundSlider @JvmOverloads constructor( // 높이가 필요한 크기보다 클 경우 크기 줄이기 (중앙 정렬을 위함) if (viewHeightMode == MeasureSpec.EXACTLY) { - val temp = width / 2 + btnRadius * 2 + btnMarginTop + btnMarginBottom + val temp = width / 2 + slideBarMargin if (height > temp) { height -= (height - temp) / 2 } @@ -108,15 +104,15 @@ class RoundSlider @JvmOverloads constructor( super.onSizeChanged(w, h, oldw, oldh) slideBarPointX = width / 2 - slideBarPointY = height - btnRadius * 2 - btnMarginTop - btnMarginBottom + slideBarPointY = height - slideBarMargin slideBarRadius = if (isHeightEnough()) { width / 2 - slideBarMargin } else { - height - btnRadius * 2 - btnMarginTop - slideBarMargin - btnMarginBottom + height - slideBarMargin * 2 } - val rad = (180 / maxPecentValue * (maxPecentValue - sliderValue)).toRadian() + val rad = (180 / maxPercentValue * (maxPercentValue - sliderValue)).toRadian() controllerPointX = slideBarPointX + cos(rad) * slideBarRadius controllerPointY = slideBarPointY + sin(-rad) * slideBarRadius } @@ -225,7 +221,7 @@ class RoundSlider @JvmOverloads constructor( } private fun isHeightEnough(): Boolean { - return height >= width / 2 + btnMarginBottom + btnRadius * 2 + btnMarginTop + return height >= width / 2 + slideBarMargin } private fun calculateRadToPoint(x: Float, y: Float): Float { @@ -234,12 +230,12 @@ class RoundSlider @JvmOverloads constructor( } private fun degreeToValue(degree: Float): Int { - return ((180F - degree) / (180F / maxPecentValue)).toInt() + return ((180F - degree) / (180F / maxPercentValue)).toInt() } fun setValue(value: Int) { - controllerPointX = slideBarPointX + cos(value * pi / maxPecentValue) * slideBarRadius - controllerPointY = slideBarPointY + sin(-value * pi / maxPecentValue) * slideBarRadius + controllerPointX = slideBarPointX + cos(value * pi / maxPercentValue) * slideBarRadius + controllerPointY = slideBarPointY + sin(-value * pi / maxPercentValue) * slideBarRadius sliderValue = value invalidate() } @@ -250,13 +246,13 @@ class RoundSlider @JvmOverloads constructor( } fun setMaxPercentValue(value: Int) { - maxPecentValue = value.toFloat() + maxPercentValue = value.toFloat() invalidate() } fun setPointRange(startValue: Int, endValue: Int) { - startDegree = (180 / maxPecentValue * startValue) + 180 - endDegree = (180 / maxPecentValue * endValue) + 180 + startDegree = (180 / maxPercentValue * startValue) + 180 + endDegree = (180 / maxPercentValue * endValue) + 180 invalidate() } From de48b2c5f2b26f31d35bf698c7a0097b2fe32fd0 Mon Sep 17 00:00:00 2001 From: ootr47 Date: Mon, 8 Jan 2024 19:25:23 +0900 Subject: [PATCH 19/70] =?UTF-8?q?feat:=20=ED=95=98=EC=9D=B4=EB=9D=BC?= =?UTF-8?q?=EC=9D=B4=ED=8A=B8=20=EC=8A=AC=EB=9D=BC=EC=9D=B4=EB=8D=94=20?= =?UTF-8?q?=EA=B8=B0=EB=B3=B8=20=EA=B0=92=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/app/priceguard/ui/slider/RoundSlider.kt | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt b/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt index ccac02f..6091b97 100644 --- a/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt +++ b/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt @@ -57,19 +57,17 @@ class RoundSlider @JvmOverloads constructor( private var maxPercentValue = 100F - private var startDegree = 270F - private var endDegree = 300F + private var startDegree = 0F + private var endDegree = 0F private var textValueSize = Sp(32F) override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { super.onMeasure(widthMeasureSpec, heightMeasureSpec) - // 뷰 크기 모드 체크 val viewWidthMode = MeasureSpec.getMode(widthMeasureSpec) val viewHeightMode = MeasureSpec.getMode(heightMeasureSpec) - // 뷰 크기 값 체크 val viewWidthSize = MeasureSpec.getSize(widthMeasureSpec) val viewHeightSize = MeasureSpec.getSize(heightMeasureSpec) @@ -121,7 +119,7 @@ class RoundSlider @JvmOverloads constructor( super.onDraw(canvas) drawSlideBar(canvas) - drawPointSlideBar(canvas) + drawHighlightSlider(canvas) drawController(canvas) drawSlideValueText(canvas) } @@ -141,7 +139,7 @@ class RoundSlider @JvmOverloads constructor( canvas.drawArc(oval, 180F, 180F, false, slideBarPaint) } - private fun drawPointSlideBar(canvas: Canvas) { + private fun drawHighlightSlider(canvas: Canvas) { slideBarPaint.color = Color.RED val oval = RectF() @@ -182,8 +180,6 @@ class RoundSlider @JvmOverloads constructor( if (event != null) { when (event.action) { MotionEvent.ACTION_MOVE -> { - // 터치 좌표 x에 맞게 컨트롤러의 y좌표 설정 (y좌표만 움직이면 controller 이동하지 않음) - if (event.y > slideBarPointY) { if (state) { if (event.x >= slideBarPointX) { @@ -200,7 +196,6 @@ class RoundSlider @JvmOverloads constructor( } return true } - state = true val rad = calculateRadToPoint(event.x, event.y) From f241446f5e084c78d551aac5e335bc14c24b1850 Mon Sep 17 00:00:00 2001 From: ootr47 Date: Mon, 8 Jan 2024 19:36:46 +0900 Subject: [PATCH 20/70] =?UTF-8?q?feat:=20active=20=EC=8A=AC=EB=9D=BC?= =?UTF-8?q?=EC=9D=B4=EB=8D=94=20=EA=B5=AC=EA=B0=84=20=EB=82=98=ED=83=80?= =?UTF-8?q?=EB=82=B4=EB=8A=94=20ui=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/app/priceguard/ui/slider/RoundSlider.kt | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt b/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt index 6091b97..ede1da0 100644 --- a/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt +++ b/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt @@ -7,6 +7,7 @@ import android.graphics.Paint import android.graphics.Rect import android.graphics.RectF import android.util.AttributeSet +import android.util.Log import android.view.MotionEvent import android.view.View import kotlin.math.atan @@ -25,6 +26,7 @@ class RoundSlider @JvmOverloads constructor( private var height = 0f private val slideBarPaint = Paint() + private val activeSlideBarPaint = Paint() private val controllerPaint = Paint() private val sliderValuePaint = Paint() @@ -62,6 +64,8 @@ class RoundSlider @JvmOverloads constructor( private var textValueSize = Sp(32F) + private var rad = pi + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { super.onMeasure(widthMeasureSpec, heightMeasureSpec) @@ -110,7 +114,7 @@ class RoundSlider @JvmOverloads constructor( height - slideBarMargin * 2 } - val rad = (180 / maxPercentValue * (maxPercentValue - sliderValue)).toRadian() + rad = (180 / maxPercentValue * (maxPercentValue - sliderValue)).toRadian() controllerPointX = slideBarPointX + cos(rad) * slideBarRadius controllerPointY = slideBarPointY + sin(-rad) * slideBarRadius } @@ -129,6 +133,10 @@ class RoundSlider @JvmOverloads constructor( slideBarPaint.strokeWidth = slideBarStrokeWidth slideBarPaint.color = Color.GRAY + activeSlideBarPaint.style = Paint.Style.STROKE + activeSlideBarPaint.strokeWidth = slideBarStrokeWidth + activeSlideBarPaint.color = Color.BLUE + val oval = RectF() oval.set( slideBarPointX - slideBarRadius, @@ -136,7 +144,9 @@ class RoundSlider @JvmOverloads constructor( slideBarPointX + slideBarRadius, slideBarPointY + slideBarRadius ) + canvas.drawArc(oval, 180F, 180F, false, slideBarPaint) + canvas.drawArc(oval, 180F, 180 - rad.toDegree(), false, activeSlideBarPaint) } private fun drawHighlightSlider(canvas: Canvas) { @@ -197,7 +207,7 @@ class RoundSlider @JvmOverloads constructor( return true } state = true - val rad = calculateRadToPoint(event.x, event.y) + rad = calculateRadToPoint(event.x, event.y) controllerPointX = slideBarPointX + cos(rad) * slideBarRadius controllerPointY = slideBarPointY + sin(-rad) * slideBarRadius From f2929fbda6bff7b91d047c12f1683824d0039d59 Mon Sep 17 00:00:00 2001 From: ootr47 Date: Mon, 8 Jan 2024 20:43:57 +0900 Subject: [PATCH 21/70] =?UTF-8?q?feat:=20=EC=83=89=EC=83=81=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20=EB=B0=8F=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/priceguard/ui/slider/RoundSlider.kt | 46 ++++++++++++++++--- android/app/src/main/res/values/attrs.xml | 8 ++++ 2 files changed, 47 insertions(+), 7 deletions(-) create mode 100644 android/app/src/main/res/values/attrs.xml diff --git a/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt b/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt index ede1da0..3180f28 100644 --- a/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt +++ b/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt @@ -7,9 +7,9 @@ import android.graphics.Paint import android.graphics.Rect import android.graphics.RectF import android.util.AttributeSet -import android.util.Log import android.view.MotionEvent import android.view.View +import app.priceguard.R import kotlin.math.atan import kotlin.math.cos import kotlin.math.min @@ -42,7 +42,7 @@ class RoundSlider @JvmOverloads constructor( private val pi = Math.PI.toFloat() - private var sliderValue = 50 + private var sliderValue = 0 set(value) { if (field != value) { field = value @@ -66,6 +66,36 @@ class RoundSlider @JvmOverloads constructor( private var rad = pi + private var colorPrimary: Int + private var colorOnPrimaryContainer: Int + private var colorSurfaceVariant: Int + + init { + val typedArray = context.obtainStyledAttributes( + attrs, + R.styleable.RoundSlider, + defStyleAttr, + 0 + ) + + colorPrimary = typedArray.getColor( + R.styleable.RoundSlider_colorPrimary, + Color.BLUE + ) + + colorOnPrimaryContainer = typedArray.getColor( + R.styleable.RoundSlider_colorOnPrimaryContainer, + Color.BLACK + ) + + colorSurfaceVariant = typedArray.getColor( + R.styleable.RoundSlider_colorSurfaceVariant, + Color.GRAY + ) + + typedArray.recycle() + } + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { super.onMeasure(widthMeasureSpec, heightMeasureSpec) @@ -131,11 +161,11 @@ class RoundSlider @JvmOverloads constructor( private fun drawSlideBar(canvas: Canvas) { slideBarPaint.style = Paint.Style.STROKE slideBarPaint.strokeWidth = slideBarStrokeWidth - slideBarPaint.color = Color.GRAY + slideBarPaint.color = colorSurfaceVariant activeSlideBarPaint.style = Paint.Style.STROKE activeSlideBarPaint.strokeWidth = slideBarStrokeWidth - activeSlideBarPaint.color = Color.BLUE + activeSlideBarPaint.color = colorPrimary val oval = RectF() oval.set( @@ -150,7 +180,8 @@ class RoundSlider @JvmOverloads constructor( } private fun drawHighlightSlider(canvas: Canvas) { - slideBarPaint.color = Color.RED + slideBarPaint.color = Color.parseColor("#FFD7F3") //#FFE3E3 + slideBarPaint.alpha val oval = RectF() oval.set( @@ -164,16 +195,17 @@ class RoundSlider @JvmOverloads constructor( private fun drawController(canvas: Canvas) { controllerPaint.style = Paint.Style.FILL - controllerPaint.color = Color.BLUE + controllerPaint.color = colorPrimary canvas.drawCircle(controllerPointX, controllerPointY, controllerRadius, controllerPaint) } private fun drawSlideValueText(canvas: Canvas) { sliderValuePaint.textSize = textValueSize.toPx(context).value + sliderValuePaint.color = colorOnPrimaryContainer val bounds = Rect() - val textString = sliderValue.toString() + val textString = "$sliderValue%" sliderValuePaint.getTextBounds(textString, 0, textString.length, bounds) val textWidth = bounds.width() diff --git a/android/app/src/main/res/values/attrs.xml b/android/app/src/main/res/values/attrs.xml new file mode 100644 index 0000000..bcf44b5 --- /dev/null +++ b/android/app/src/main/res/values/attrs.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file From bd6ac374bdedd7cefd1d3dd8042b6ada203b6c5d Mon Sep 17 00:00:00 2001 From: ootr47 Date: Mon, 8 Jan 2024 20:46:28 +0900 Subject: [PATCH 22/70] =?UTF-8?q?fix:=20=ED=95=98=EC=9D=B4=EB=9D=BC?= =?UTF-8?q?=EC=9D=B4=ED=8A=B8=20=EB=B6=80=EB=B6=84=EC=9D=B4=20=ED=99=9C?= =?UTF-8?q?=EC=84=B1=ED=99=94=EB=90=9C=20=EB=B6=80=EB=B6=84=20=EC=9C=84?= =?UTF-8?q?=EC=97=90=20=EA=B7=B8=EB=A0=A4=EC=A7=80=EB=8A=94=20=ED=98=84?= =?UTF-8?q?=EC=83=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt b/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt index 3180f28..eaf646e 100644 --- a/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt +++ b/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt @@ -153,7 +153,6 @@ class RoundSlider @JvmOverloads constructor( super.onDraw(canvas) drawSlideBar(canvas) - drawHighlightSlider(canvas) drawController(canvas) drawSlideValueText(canvas) } @@ -176,6 +175,7 @@ class RoundSlider @JvmOverloads constructor( ) canvas.drawArc(oval, 180F, 180F, false, slideBarPaint) + drawHighlightSlider(canvas) canvas.drawArc(oval, 180F, 180 - rad.toDegree(), false, activeSlideBarPaint) } From 9366d387ca42ce1f751a74afbd6d290781294637 Mon Sep 17 00:00:00 2001 From: ootr47 Date: Mon, 8 Jan 2024 20:47:17 +0900 Subject: [PATCH 23/70] =?UTF-8?q?refactor:=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20=ED=95=A8=EC=88=98=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/app/priceguard/ui/slider/RoundSliderActivity.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/android/app/src/main/java/app/priceguard/ui/slider/RoundSliderActivity.kt b/android/app/src/main/java/app/priceguard/ui/slider/RoundSliderActivity.kt index 515c0fa..aa11759 100644 --- a/android/app/src/main/java/app/priceguard/ui/slider/RoundSliderActivity.kt +++ b/android/app/src/main/java/app/priceguard/ui/slider/RoundSliderActivity.kt @@ -17,7 +17,6 @@ class RoundSliderActivity : AppCompatActivity() { binding.roundSlider.setMaxPercentValue(180) binding.roundSlider.setValue(10) - binding.roundSlider.setSliderStrokeWidth(4) binding.roundSlider.setPointRange(100, 120) binding.roundSlider.setSliderValueChangeListener { value -> From 23c251494048bfecac70dd1a013a8ca1b71a66e4 Mon Sep 17 00:00:00 2001 From: ootr47 Date: Mon, 8 Jan 2024 20:52:25 +0900 Subject: [PATCH 24/70] =?UTF-8?q?docs:=20=ED=95=84=EC=9A=94=EC=97=86?= =?UTF-8?q?=EB=8A=94=20=EC=A3=BC=EC=84=9D=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt b/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt index eaf646e..61a4bb2 100644 --- a/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt +++ b/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt @@ -180,7 +180,7 @@ class RoundSlider @JvmOverloads constructor( } private fun drawHighlightSlider(canvas: Canvas) { - slideBarPaint.color = Color.parseColor("#FFD7F3") //#FFE3E3 + slideBarPaint.color = Color.parseColor("#FFD7F3") slideBarPaint.alpha val oval = RectF() From d0cf59f7f34e81dc72bc0e1801dea5293506fc80 Mon Sep 17 00:00:00 2001 From: ootr47 Date: Mon, 8 Jan 2024 20:57:13 +0900 Subject: [PATCH 25/70] =?UTF-8?q?refactor:=20=ED=95=A8=EC=88=98=EB=AA=85?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt | 2 +- .../main/java/app/priceguard/ui/slider/RoundSliderActivity.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt b/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt index 61a4bb2..0a1ff46 100644 --- a/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt +++ b/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt @@ -287,7 +287,7 @@ class RoundSlider @JvmOverloads constructor( invalidate() } - fun setPointRange(startValue: Int, endValue: Int) { + fun setHighlightRange(startValue: Int, endValue: Int) { startDegree = (180 / maxPercentValue * startValue) + 180 endDegree = (180 / maxPercentValue * endValue) + 180 invalidate() diff --git a/android/app/src/main/java/app/priceguard/ui/slider/RoundSliderActivity.kt b/android/app/src/main/java/app/priceguard/ui/slider/RoundSliderActivity.kt index aa11759..6cd9a86 100644 --- a/android/app/src/main/java/app/priceguard/ui/slider/RoundSliderActivity.kt +++ b/android/app/src/main/java/app/priceguard/ui/slider/RoundSliderActivity.kt @@ -17,7 +17,7 @@ class RoundSliderActivity : AppCompatActivity() { binding.roundSlider.setMaxPercentValue(180) binding.roundSlider.setValue(10) - binding.roundSlider.setPointRange(100, 120) + binding.roundSlider.setHighlightRange(100, 120) binding.roundSlider.setSliderValueChangeListener { value -> Log.d("slideValueChange", value.toString()) From 6ac679fe2f5a5c1ed0a2f1f7a70db59861711642 Mon Sep 17 00:00:00 2001 From: ootr47 Date: Mon, 8 Jan 2024 21:02:46 +0900 Subject: [PATCH 26/70] =?UTF-8?q?refactor:=20=ED=8C=8C=EC=9D=BC=EB=AA=85?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD,=20=EC=82=AC=EC=9A=A9=ED=95=98=EC=A7=80?= =?UTF-8?q?=20=EC=95=8A=EB=8A=94=20=ED=95=A8=EC=88=98=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/app/priceguard/ui/slider/ConvertUtil.kt | 5 ----- ...omSliderEventListener.kt => SliderValueChangeListener.kt} | 0 2 files changed, 5 deletions(-) rename android/app/src/main/java/app/priceguard/ui/slider/{CustomSliderEventListener.kt => SliderValueChangeListener.kt} (100%) diff --git a/android/app/src/main/java/app/priceguard/ui/slider/ConvertUtil.kt b/android/app/src/main/java/app/priceguard/ui/slider/ConvertUtil.kt index f6b837f..dff3c27 100644 --- a/android/app/src/main/java/app/priceguard/ui/slider/ConvertUtil.kt +++ b/android/app/src/main/java/app/priceguard/ui/slider/ConvertUtil.kt @@ -9,11 +9,6 @@ data class Dp(val value: Float) data class Sp(val value: Float) -fun Px.toDp(context: Context): Dp { - val density = context.resources.displayMetrics.density - return Dp(value / density) -} - fun Dp.toPx(context: Context): Px { val density = context.resources.displayMetrics.density return Px(value * density) diff --git a/android/app/src/main/java/app/priceguard/ui/slider/CustomSliderEventListener.kt b/android/app/src/main/java/app/priceguard/ui/slider/SliderValueChangeListener.kt similarity index 100% rename from android/app/src/main/java/app/priceguard/ui/slider/CustomSliderEventListener.kt rename to android/app/src/main/java/app/priceguard/ui/slider/SliderValueChangeListener.kt From 3604ffafd847bd680e5b0d29e0a8ccffffae2f36 Mon Sep 17 00:00:00 2001 From: ootr47 Date: Thu, 11 Jan 2024 21:53:20 +0900 Subject: [PATCH 27/70] =?UTF-8?q?feat:=20=EB=AC=B8=EC=9E=90=EC=97=B4=20?= =?UTF-8?q?=EB=A6=AC=EC=86=8C=EC=8A=A4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- android/app/src/main/res/values/strings.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml index 148d8e3..aa2258c 100644 --- a/android/app/src/main/res/values/strings.xml +++ b/android/app/src/main/res/values/strings.xml @@ -133,4 +133,6 @@ 0 999999999 Product Price Notification + %s원 에 알림을 받고 싶습니다. + 목표 가격을 입력해 주세요 \ No newline at end of file From c8457b66cb32b907ce671fcbb4c610ba3bdba054 Mon Sep 17 00:00:00 2001 From: ootr47 Date: Thu, 11 Jan 2024 21:53:55 +0900 Subject: [PATCH 28/70] =?UTF-8?q?feat:=20=EC=BB=A4=EC=8A=A4=ED=85=80=20?= =?UTF-8?q?=EB=B7=B0=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=95=A1=ED=8B=B0?= =?UTF-8?q?=EB=B9=84=ED=8B=B0=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- android/app/src/main/AndroidManifest.xml | 14 +++------- .../ui/slider/RoundSliderActivity.kt | 26 ------------------- .../main/res/layout/activity_round_slider.xml | 25 ------------------ 3 files changed, 4 insertions(+), 61 deletions(-) delete mode 100644 android/app/src/main/java/app/priceguard/ui/slider/RoundSliderActivity.kt delete mode 100644 android/app/src/main/res/layout/activity_round_slider.xml diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index d3c8499..2ac5be4 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -14,15 +14,6 @@ android:supportsRtl="true" android:theme="@style/Theme.PriceGuard" tools:targetApi="34"> - - - - - - - - + + + + - Log.d("slideValueChange", value.toString()) - } - } -} diff --git a/android/app/src/main/res/layout/activity_round_slider.xml b/android/app/src/main/res/layout/activity_round_slider.xml deleted file mode 100644 index b54ee14..0000000 --- a/android/app/src/main/res/layout/activity_round_slider.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file From aa361a67bf375a10e32fa448e9ae66129b303bc4 Mon Sep 17 00:00:00 2001 From: ootr47 Date: Sat, 13 Jan 2024 14:51:27 +0900 Subject: [PATCH 29/70] =?UTF-8?q?feat:=20=EB=AA=A9=ED=91=9C=20=EA=B0=80?= =?UTF-8?q?=EA=B2=A9=20=EC=88=98=EC=A0=95=20=EB=8B=A4=EC=9D=B4=EC=96=BC?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../setprice/SetTargetPriceDialogFragment.kt | 104 ++++++++++++++++++ .../setprice/SetTargetPriceDialogViewModel.kt | 29 +++++ .../layout/fragment_target_price_dialog.xml | 48 ++++++++ android/app/src/main/res/values/strings.xml | 1 + 4 files changed, 182 insertions(+) create mode 100644 android/app/src/main/java/app/priceguard/ui/additem/setprice/SetTargetPriceDialogFragment.kt create mode 100644 android/app/src/main/java/app/priceguard/ui/additem/setprice/SetTargetPriceDialogViewModel.kt create mode 100644 android/app/src/main/res/layout/fragment_target_price_dialog.xml diff --git a/android/app/src/main/java/app/priceguard/ui/additem/setprice/SetTargetPriceDialogFragment.kt b/android/app/src/main/java/app/priceguard/ui/additem/setprice/SetTargetPriceDialogFragment.kt new file mode 100644 index 0000000..556e7c2 --- /dev/null +++ b/android/app/src/main/java/app/priceguard/ui/additem/setprice/SetTargetPriceDialogFragment.kt @@ -0,0 +1,104 @@ +package app.priceguard.ui.additem.setprice + +import android.app.Dialog +import android.os.Bundle +import androidx.core.widget.addTextChangedListener +import androidx.fragment.app.DialogFragment +import androidx.fragment.app.viewModels +import app.priceguard.R +import app.priceguard.databinding.FragmentTargetPriceDialogBinding +import app.priceguard.ui.util.lifecycle.repeatOnStarted +import com.google.android.material.dialog.MaterialAlertDialogBuilder + +class SetTargetPriceDialogFragment : DialogFragment() { + + private var _binding: FragmentTargetPriceDialogBinding? = null + private val binding get() = _binding!! + + private val viewModel: SetTargetPriceDialogViewModel by viewModels() + + private var resultListener: OnDialogResultListener? = null + + override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { + _binding = FragmentTargetPriceDialogBinding.inflate(requireActivity().layoutInflater) + val view = binding.root + + binding.viewModel = viewModel + binding.lifecycleOwner = this + + initListener() + + val title = arguments?.getString("title") ?: "" + val price = arguments?.getInt("price") ?: 0 + + viewModel.updateTargetPrice(price) + + val dialogBuilder = MaterialAlertDialogBuilder( + requireActivity(), + R.style.ThemeOverlay_App_MaterialAlertDialog + ).apply { + setTitle(title) + setView(view) + setNegativeButton(R.string.cancel) { _, _ -> dismiss() } + setPositiveButton(R.string.confirm) { _, _ -> + resultListener?.onDialogResult(viewModel.state.value.targetPrice) + dismiss() + } + } + val dialog = dialogBuilder.create() + + repeatOnStarted { + viewModel.state.collect { state -> + viewModel.updateTextChangedEnabled(false) + binding.etTargetPriceDialog.setText( + getString(R.string.won, getString(R.string.comma_number, state.targetPrice)) + ) + dialog.getButton(Dialog.BUTTON_POSITIVE).isEnabled = !state.isErrorMessageVisible + viewModel.updateTextChangedEnabled(true) + } + } + + return dialog + } + + override fun onDestroyView() { + super.onDestroyView() + _binding = null + } + + private fun initListener() { + binding.etTargetPriceDialog.addTextChangedListener { + binding.etTargetPriceDialog.setSelection(it.toString().length - 1) + + val price = extractAndConvertToInteger(it.toString()) + + if (viewModel.state.value.isTextChanged) { + if (price > 100000000) { + viewModel.updateErrorMessageVisible(true) + } else { + viewModel.updateErrorMessageVisible(false) + } + viewModel.updateTargetPrice(price) + } + } + + binding.etTargetPriceDialog.setOnClickListener { + binding.etTargetPriceDialog.setSelection(binding.etTargetPriceDialog.text.toString().length - 1) + } + } + + private fun extractAndConvertToInteger(text: String): Int { + val digits = text.filter { it.isDigit() } + var num = digits.toLongOrNull() ?: 0 + if (num > 999999999) num = 999999999 + return num.toInt() + } + + fun setOnDialogResultListener(listener: OnDialogResultListener) { + resultListener = listener + } + + interface OnDialogResultListener { + fun onDialogResult(result: Int) + } +} diff --git a/android/app/src/main/java/app/priceguard/ui/additem/setprice/SetTargetPriceDialogViewModel.kt b/android/app/src/main/java/app/priceguard/ui/additem/setprice/SetTargetPriceDialogViewModel.kt new file mode 100644 index 0000000..87cf41e --- /dev/null +++ b/android/app/src/main/java/app/priceguard/ui/additem/setprice/SetTargetPriceDialogViewModel.kt @@ -0,0 +1,29 @@ +package app.priceguard.ui.additem.setprice + +import androidx.lifecycle.ViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow + +class SetTargetPriceDialogViewModel : ViewModel() { + + data class SetTargetPriceDialogState( + val targetPrice: Int = 0, + val isTextChanged: Boolean = false, + val isErrorMessageVisible: Boolean = false + ) + + private val _state = MutableStateFlow(SetTargetPriceDialogState()) + val state = _state.asStateFlow() + + fun updateTargetPrice(price: Int) { + _state.value = _state.value.copy(targetPrice = price) + } + + fun updateTextChangedEnabled(isEnabled: Boolean) { + _state.value = _state.value.copy(isTextChanged = isEnabled) + } + + fun updateErrorMessageVisible(isEnabled: Boolean) { + _state.value = _state.value.copy(isErrorMessageVisible = isEnabled) + } +} diff --git a/android/app/src/main/res/layout/fragment_target_price_dialog.xml b/android/app/src/main/res/layout/fragment_target_price_dialog.xml new file mode 100644 index 0000000..60e8cb2 --- /dev/null +++ b/android/app/src/main/res/layout/fragment_target_price_dialog.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml index aa2258c..3b4cdef 100644 --- a/android/app/src/main/res/values/strings.xml +++ b/android/app/src/main/res/values/strings.xml @@ -135,4 +135,5 @@ Product Price Notification %s원 에 알림을 받고 싶습니다. 목표 가격을 입력해 주세요 + 목표 가격은 1억을 초과할 수 없습니다. \ No newline at end of file From 4d3b4f7e378cfb4ed89b529335a527aec7e27057 Mon Sep 17 00:00:00 2001 From: ootr47 Date: Sat, 13 Jan 2024 14:51:48 +0900 Subject: [PATCH 30/70] =?UTF-8?q?refactor:=20=EB=8B=A4=EC=9D=B4=EC=96=BC?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=20tag=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- android/app/src/main/java/app/priceguard/ui/util/Dialog.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/android/app/src/main/java/app/priceguard/ui/util/Dialog.kt b/android/app/src/main/java/app/priceguard/ui/util/Dialog.kt index b1f3e18..7b3de7e 100644 --- a/android/app/src/main/java/app/priceguard/ui/util/Dialog.kt +++ b/android/app/src/main/java/app/priceguard/ui/util/Dialog.kt @@ -27,7 +27,7 @@ fun Fragment.showDialogWithAction( message: String, action: DialogConfirmAction = DialogConfirmAction.NOTHING ) { - val tag = "confirm_dialog_fragment_from_activity" + val tag = "confirm_dialog_fragment_from_fragment" if (requireActivity().supportFragmentManager.findFragmentByTag(tag) != null) return val dialogFragment = ConfirmDialogFragment() @@ -40,11 +40,11 @@ fun Fragment.showDialogWithAction( } fun AppCompatActivity.showDialogWithLogout() { - val tag = "error_dialog_fragment_from_fragment" + val tag = "error_dialog_fragment_from_activity" if (supportFragmentManager.findFragmentByTag(tag) != null) return val dialogFragment = ErrorDialogFragment() - dialogFragment.show(supportFragmentManager, "error_dialog_fragment_from_activity") + dialogFragment.show(supportFragmentManager, tag) } fun Fragment.showDialogWithLogout() { From 751dd2b91088484a67669ae116fd9d7c4497c468 Mon Sep 17 00:00:00 2001 From: ootr47 Date: Sat, 13 Jan 2024 14:54:36 +0900 Subject: [PATCH 31/70] =?UTF-8?q?fix:=20=EC=8A=AC=EB=9D=BC=EC=9D=B4?= =?UTF-8?q?=EB=8D=94=20=EC=BB=A8=ED=8A=B8=EB=A1=A4=EB=9F=AC=20=EC=9C=84?= =?UTF-8?q?=EC=B9=98=20=EC=95=88=EB=A7=9E=EB=8A=94=20=ED=98=84=EC=83=81=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt b/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt index 0a1ff46..41e7c1b 100644 --- a/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt +++ b/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt @@ -271,7 +271,9 @@ class RoundSlider @JvmOverloads constructor( } fun setValue(value: Int) { - controllerPointX = slideBarPointX + cos(value * pi / maxPercentValue) * slideBarRadius + rad = (180 / maxPercentValue * (maxPercentValue - value)).toRadian() + // cos(rad) = -cos(value * pi / maxPercentValue) + controllerPointX = slideBarPointX + cos(rad) * slideBarRadius controllerPointY = slideBarPointY + sin(-value * pi / maxPercentValue) * slideBarRadius sliderValue = value invalidate() From 50340d7b23ce13899d3ee46d01928c81d5d1ce71 Mon Sep 17 00:00:00 2001 From: ootr47 Date: Sat, 13 Jan 2024 14:55:44 +0900 Subject: [PATCH 32/70] =?UTF-8?q?feat:=20=EC=8A=AC=EB=9D=BC=EC=9D=B4?= =?UTF-8?q?=EB=8D=94=20=EC=A1=B0=EC=9E=91=20=EC=A4=91=EC=97=90=EB=8A=94=20?= =?UTF-8?q?=EB=B6=80=EB=AA=A8=20=ED=84=B0=EC=B9=98=20=EC=9D=B4=EB=B2=A4?= =?UTF-8?q?=ED=8A=B8=20=EB=B9=84=ED=99=9C=EC=84=B1=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/app/priceguard/ui/slider/RoundSlider.kt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt b/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt index 41e7c1b..3fcfb1b 100644 --- a/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt +++ b/android/app/src/main/java/app/priceguard/ui/slider/RoundSlider.kt @@ -221,6 +221,10 @@ class RoundSlider @JvmOverloads constructor( override fun onTouchEvent(event: MotionEvent?): Boolean { if (event != null) { when (event.action) { + MotionEvent.ACTION_DOWN -> { + parent.requestDisallowInterceptTouchEvent(true) + } + MotionEvent.ACTION_MOVE -> { if (event.y > slideBarPointY) { if (state) { @@ -250,6 +254,7 @@ class RoundSlider @JvmOverloads constructor( } MotionEvent.ACTION_UP -> { + parent.requestDisallowInterceptTouchEvent(false) state = false } } From 8f5ff5524d089532d1bea21001b210626b6b92c5 Mon Sep 17 00:00:00 2001 From: ootr47 Date: Sat, 13 Jan 2024 14:57:48 +0900 Subject: [PATCH 33/70] =?UTF-8?q?feat:=20=EA=B0=80=EA=B2=A9=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20=ED=99=94=EB=A9=B4=20=EC=BB=A4=EC=8A=A4=ED=85=80=20?= =?UTF-8?q?=EC=8A=AC=EB=9D=BC=EC=9D=B4=EB=8D=94=20=EB=B7=B0=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../setprice/SetTargetPriceFragment.kt | 101 ++++++------------ .../setprice/SetTargetPriceViewModel.kt | 14 ++- .../res/layout/fragment_set_target_price.xml | 46 +++----- 3 files changed, 57 insertions(+), 104 deletions(-) diff --git a/android/app/src/main/java/app/priceguard/ui/additem/setprice/SetTargetPriceFragment.kt b/android/app/src/main/java/app/priceguard/ui/additem/setprice/SetTargetPriceFragment.kt index 6e76c08..bb4d8a1 100644 --- a/android/app/src/main/java/app/priceguard/ui/additem/setprice/SetTargetPriceFragment.kt +++ b/android/app/src/main/java/app/priceguard/ui/additem/setprice/SetTargetPriceFragment.kt @@ -1,12 +1,10 @@ package app.priceguard.ui.additem.setprice import android.os.Bundle -import android.text.Editable import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.activity.addCallback -import androidx.core.widget.addTextChangedListener import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels import androidx.navigation.fragment.findNavController @@ -19,14 +17,12 @@ import app.priceguard.ui.data.DialogConfirmAction import app.priceguard.ui.util.lifecycle.repeatOnStarted import app.priceguard.ui.util.showDialogWithAction import app.priceguard.ui.util.showDialogWithLogout -import com.google.android.material.slider.Slider -import com.google.android.material.slider.Slider.OnSliderTouchListener import dagger.hilt.android.AndroidEntryPoint import java.text.NumberFormat import javax.inject.Inject @AndroidEntryPoint -class SetTargetPriceFragment : Fragment() { +class SetTargetPriceFragment : Fragment(), SetTargetPriceDialogFragment.OnDialogResultListener { @Inject lateinit var tokenRepository: TokenRepository @@ -53,6 +49,7 @@ class SetTargetPriceFragment : Fragment() { setBackPressedCallback() binding.initView() binding.initListener() + initCollector() handleEvent() } @@ -72,9 +69,9 @@ class SetTargetPriceFragment : Fragment() { val productCode = arguments.getString("productCode") ?: "" val title = arguments.getString("productTitle") ?: "" val price = arguments.getInt("productPrice") - var targetPrice = arguments.getInt("productTargetPrice") + val targetPrice = arguments.getInt("productTargetPrice") - setTargetPriceViewModel.updateTargetPrice(targetPrice) + setTargetPriceViewModel.setProductInfo(productCode, title, price, targetPrice) tvSetPriceCurrentPrice.text = String.format( @@ -83,11 +80,6 @@ class SetTargetPriceFragment : Fragment() { ) tvSetPriceCurrentPrice.contentDescription = getString(R.string.current_price_info, tvSetPriceCurrentPrice.text) - - setTargetPriceViewModel.setProductInfo(productCode, title, price) - etTargetPrice.setText(targetPrice.toString()) - - updateSlideValueWithPrice(targetPrice.toFloat()) } private fun FragmentSetTargetPriceBinding.initListener() { @@ -98,58 +90,35 @@ class SetTargetPriceFragment : Fragment() { findNavController().navigateUp() } } + btnConfirmItemNext.setOnClickListener { val isAdding = requireArguments().getBoolean("isAdding") if (isAdding) setTargetPriceViewModel.addProduct() else setTargetPriceViewModel.patchProduct() } - slTargetPrice.addOnChangeListener { _, value, _ -> - if (!etTargetPrice.isFocused) { - setTargetPriceAndPercent(value) + + rsTargetPrice.setSliderValueChangeListener { value -> + if (setTargetPriceViewModel.state.value.isEnabledSliderListener) { + setTargetPriceViewModel.updateTargetPriceFromPercent(value) } } - slTargetPrice.addOnSliderTouchListener(object : OnSliderTouchListener { - override fun onStartTrackingTouch(slider: Slider) { - etTargetPrice.clearFocus() - setTargetPriceAndPercent(slider.value) - } - override fun onStopTrackingTouch(slider: Slider) { - } - }) - etTargetPrice.addTextChangedListener { - updateTargetPriceUI(it) + tvTargetPriceContent.setOnClickListener { + showConfirmationDialogForResult() } } - private fun updateTargetPriceUI(it: Editable?) { - if (binding.etTargetPrice.isFocused) { - val targetPrice = if (it.toString().matches("^\\d{1,9}$".toRegex())) { - it.toString().toInt() - } else if (it.toString().isEmpty()) { - binding.etTargetPrice.setText(getString(R.string.min_price)) - 0 - } else { - binding.etTargetPrice.setText(getString(R.string.max_price)) - 999999999 + private fun initCollector() { + repeatOnStarted { + setTargetPriceViewModel.state.collect { state -> + setTargetPriceViewModel.setSliderChangeListenerEnabled(false) + setTargetPricePercent(state.productPrice, state.targetPrice) + setTargetPriceViewModel.setSliderChangeListenerEnabled(true) } - - setTargetPriceViewModel.updateTargetPrice(targetPrice) - binding.updateSlideValueWithPrice(targetPrice.toFloat()) } } - private fun Int.roundAtFirstDigit(): Int { - return ((this + 5) / 10) * 10 - } - - private fun FragmentSetTargetPriceBinding.setTargetPriceAndPercent(value: Float) { - val targetPrice = ((setTargetPriceViewModel.state.value.productPrice) * value.toInt() / 100) - tvTargetPricePercent.text = - String.format(getString(R.string.current_price_percent), value.toInt()) - etTargetPrice.setText( - targetPrice.toString() - ) - setTargetPriceViewModel.updateTargetPrice(targetPrice) + private fun setTargetPricePercent(productPrice: Int, targetPrice: Int) { + binding.rsTargetPrice.setValue(targetPrice * 100 / productPrice) } private fun handleEvent() { @@ -214,22 +183,17 @@ class SetTargetPriceFragment : Fragment() { } } - private fun FragmentSetTargetPriceBinding.updateSlideValueWithPrice(targetPrice: Float) { - val percent = - ((targetPrice / setTargetPriceViewModel.state.value.productPrice) * MAX_PERCENT).toInt() - val pricePercent = percent.coerceIn(MIN_PERCENT, MAX_PERCENT).roundAtFirstDigit() - if (targetPrice > setTargetPriceViewModel.state.value.productPrice) { - tvTargetPricePercent.text = getString(R.string.over_current_price) - } else { - tvTargetPricePercent.text = - String.format(getString(R.string.current_price_percent), percent) - } - binding.tvTargetPricePercent.contentDescription = getString( - R.string.target_price_percent_and_price, - binding.tvTargetPricePercent.text, - binding.tvSetPriceCurrentPrice.text - ) - slTargetPrice.value = pricePercent.toFloat() + private fun showConfirmationDialogForResult() { + val tag = "set_target_price_dialog_fragment_from_fragment" + if (requireActivity().supportFragmentManager.findFragmentByTag(tag) != null) return + + val dialogFragment = SetTargetPriceDialogFragment() + val bundle = Bundle() + bundle.putString("title", getString(R.string.set_target_price_dialog_title)) + bundle.putInt("price", setTargetPriceViewModel.state.value.targetPrice) + dialogFragment.setOnDialogResultListener(this) + dialogFragment.arguments = bundle + dialogFragment.show(requireActivity().supportFragmentManager, tag) } override fun onDestroyView() { @@ -237,8 +201,7 @@ class SetTargetPriceFragment : Fragment() { _binding = null } - companion object { - const val MIN_PERCENT = 0 - const val MAX_PERCENT = 100 + override fun onDialogResult(result: Int) { + setTargetPriceViewModel.updateTargetPrice(result) } } diff --git a/android/app/src/main/java/app/priceguard/ui/additem/setprice/SetTargetPriceViewModel.kt b/android/app/src/main/java/app/priceguard/ui/additem/setprice/SetTargetPriceViewModel.kt index c40b3d0..a413915 100644 --- a/android/app/src/main/java/app/priceguard/ui/additem/setprice/SetTargetPriceViewModel.kt +++ b/android/app/src/main/java/app/priceguard/ui/additem/setprice/SetTargetPriceViewModel.kt @@ -22,6 +22,7 @@ class SetTargetPriceViewModel @Inject constructor(private val productRepository: val targetPrice: Int = 0, val productName: String = "", val productPrice: Int = 0, + val isEnabledSliderListener: Boolean = true, val isReady: Boolean = true ) @@ -80,12 +81,21 @@ class SetTargetPriceViewModel @Inject constructor(private val productRepository: _state.value = state.value.copy(targetPrice = price) } - fun setProductInfo(productCode: String, name: String, price: Int) { + fun updateTargetPriceFromPercent(percent: Int) { + _state.value = state.value.copy(targetPrice = _state.value.productPrice * percent / 100) + } + + fun setProductInfo(productCode: String, name: String, price: Int, targetPrice: Int) { _state.value = state.value.copy( productCode = productCode, productName = name, - productPrice = price + productPrice = price, + targetPrice = targetPrice ) } + + fun setSliderChangeListenerEnabled(isEnabled: Boolean) { + _state.value = state.value.copy(isEnabledSliderListener = isEnabled) + } } diff --git a/android/app/src/main/res/layout/fragment_set_target_price.xml b/android/app/src/main/res/layout/fragment_set_target_price.xml index af211be..476ae82 100644 --- a/android/app/src/main/res/layout/fragment_set_target_price.xml +++ b/android/app/src/main/res/layout/fragment_set_target_price.xml @@ -67,47 +67,27 @@ app:layout_constraintEnd_toStartOf="@id/gl_vertical_end" app:layout_constraintTop_toTopOf="@id/tv_set_price_name" /> - - - + app:layout_constraintTop_toBottomOf="@id/tv_set_price_name" /> + app:layout_constraintTop_toBottomOf="@id/rs_target_price" />