Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat] 번개 생성 개최 뷰 - 시간 / 날짜 뷰 구현 #43

Merged
merged 13 commits into from
Jan 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.sopt.pingle.presentation.type

import androidx.annotation.StringRes
import org.sopt.pingle.R

enum class MeridiemType(
@StringRes val meridiemStringRes: Int
) {
AM(R.string.plan_time_am), PM(R.string.plan_time_pm)
}
Comment on lines +6 to +10
Copy link
Collaborator

Choose a reason for hiding this comment

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

타입 관리 미쳤네염

Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package org.sopt.pingle.presentation.ui.main.plan

import android.os.Bundle
import android.view.View
import android.widget.NumberPicker
import org.sopt.pingle.R
import org.sopt.pingle.databinding.DialogDatePickerBinding
import org.sopt.pingle.util.base.BindingBottomSheetDialogFragment

class PlanDateDialogFragment(
private val onDialogClosed: (year: Int, month: Int, day: Int) -> Unit
) :
BindingBottomSheetDialogFragment<DialogDatePickerBinding>(R.layout.dialog_date_picker) {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
isCancelable = false
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

initLayout()
addListeners()
}

private fun initLayout() {
val yearPicker = binding.npDatePickerYear
yearPicker.apply {
wrapSelectorWheel = false // 순한 안되게 막기
descendantFocusability = NumberPicker.FOCUS_BLOCK_DESCENDANTS // editText 설정 해제
minValue = YEAR_MIN
maxValue = YEAR_MAX
}

val hoursPicker = binding.npDatePickerMonth
hoursPicker.apply {
wrapSelectorWheel = false
descendantFocusability = NumberPicker.FOCUS_BLOCK_DESCENDANTS
minValue = MONTH_MIN
maxValue = MONTH_MAX
}
val dayPicker = binding.npDatePickerDay
dayPicker.apply {
wrapSelectorWheel = false
descendantFocusability = NumberPicker.FOCUS_BLOCK_DESCENDANTS
minValue = DAY_MIN
maxValue = DAY_MAX
}
}

private fun addListeners() {
binding.tvDatePickerDone.setOnClickListener {
onDialogClosed(
binding.npDatePickerYear.value,
binding.npDatePickerMonth.value,
binding.npDatePickerDay.value
)
dismiss()
}
}

companion object {
const val YEAR_MIN = 2024
const val YEAR_MAX = 2050
const val MONTH_MIN = 1
const val MONTH_MAX = 12
const val DAY_MIN = 1
const val DAY_MAX = 31
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,89 @@ package org.sopt.pingle.presentation.ui.main.plan

import android.os.Bundle
import android.view.View
import androidx.fragment.app.activityViewModels
import java.text.SimpleDateFormat
import java.time.LocalDate
import org.sopt.pingle.R
import org.sopt.pingle.databinding.FragmentPlanDateTimeBinding
import org.sopt.pingle.util.base.BindingFragment
import timber.log.Timber

class PlanDateTimeFragment : BindingFragment<FragmentPlanDateTimeBinding>(R.layout.fragment_plan_date_time) {
class PlanDateTimeFragment :
BindingFragment<FragmentPlanDateTimeBinding>(R.layout.fragment_plan_date_time) {
private val planViewModel: PlanViewModel by activityViewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

addListeners()
}

private fun addListeners() {
binding.includePlanTextWithTitleDate.root.setOnClickListener {
val dialogDateFragment = PlanDateDialogFragment(::onDateDialogFragmentClosed)
dialogDateFragment.show(
parentFragmentManager,
dialogDateFragment.tag
)
}

binding.includePlanTextWithTitleStartTime.root.setOnClickListener {
val dialogStartTimeFragment = PlanTimeDialogFragment(::onTimeDialogFragmentClosed)
dialogStartTimeFragment.show(
parentFragmentManager,
dialogStartTimeFragment.tag
)
planViewModel.setSelectedTimeType(START_TIME)
}

binding.includePlanTextWithTitleEndTime.root.setOnClickListener {
val dialogEndTimeFragment = PlanTimeDialogFragment(::onTimeDialogFragmentClosed)
dialogEndTimeFragment.show(
parentFragmentManager,
dialogEndTimeFragment.tag
)
planViewModel.setSelectedTimeType(END_TIME)
}
}

// TODO format 관련 refactor
private fun onDateDialogFragmentClosed(year: Int, month: Int, day: Int) {
val dateFormat = SimpleDateFormat("yyyy-MM-dd")
val todayLocalDate = dateFormat.parse(LocalDate.now().toString())
val selectedFormatDate = String.format("%d-%02d-%02d", year, month, day)
val selectedLocalDate = dateFormat.parse(selectedFormatDate)

if (selectedLocalDate != null) {
if (selectedLocalDate.before(todayLocalDate)) {
// TODO 에러 스낵바 노출
} else {
binding.includePlanTextWithTitleDate.tvText.text = String.format(
"%d년 %d월 %d일",
year,
month,
day
)
planViewModel.setPlanDate(selectedFormatDate)
}
}
}

// TODO 시간 포맷 나오면 수정 예정
// TODO {} 수정 예정
private fun onTimeDialogFragmentClosed(time: String) {
when (planViewModel.selectedTimeType.value) {
START_TIME -> {
Timber.d(START_TIME)
}

END_TIME -> {
Timber.d(END_TIME)
}
}
}

companion object {
const val START_TIME = "startTime"
const val END_TIME = "endTime"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package org.sopt.pingle.presentation.ui.main.plan

import android.os.Bundle
import android.view.View
import android.widget.NumberPicker
import org.sopt.pingle.R
import org.sopt.pingle.databinding.DialogTimePickerBinding
import org.sopt.pingle.presentation.type.MeridiemType
import org.sopt.pingle.util.base.BindingBottomSheetDialogFragment

class PlanTimeDialogFragment(
private val onDialogClosed: (String) -> Unit
) :
BindingBottomSheetDialogFragment<DialogTimePickerBinding>(R.layout.dialog_time_picker) {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
isCancelable = false
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

initLayout()
addListeners()
}

private fun initLayout() {
val meridiemPicker = binding.npTimePickerMeridiem
meridiemPicker.apply {
wrapSelectorWheel = false // 순한 안되게 막기
descendantFocusability = NumberPicker.FOCUS_BLOCK_DESCENDANTS // editText 설정 해제
minValue = 0
maxValue = 1
displayedValues =
arrayOf(
getString(MeridiemType.AM.meridiemStringRes),
getString(MeridiemType.PM.meridiemStringRes)
)
}

val hoursPicker = binding.npTimePickerHour
hoursPicker.apply {
wrapSelectorWheel = false // 순한 안되게 막기
descendantFocusability = NumberPicker.FOCUS_BLOCK_DESCENDANTS // editText 설정 해제
minValue = HOUR_MIN
maxValue = HOUR_MAX
}
val minutesPicker = binding.npTimePickerMinute
minutesPicker.apply {
wrapSelectorWheel = false // 순한 안되게 막기
descendantFocusability = NumberPicker.FOCUS_BLOCK_DESCENDANTS // editText 설정 해제
minValue = MINUTE_MIN
maxValue = MINUTE_MAX
setFormatter { value -> String.format("%02d", value) }
}
}

private fun addListeners() {
binding.tvTimePickerDone.setOnClickListener {
onDialogClosed("aaa")
// 시간 설정 후 editText에 띄우기
// with(binding) {
// val timeFormat =
// String.format("%02d:%02d:00", npTimePickerHour.value, npTimePickerMinute.value)
// onDialogClosed(timeFormat)
// Log.d(
// "aaa",
// String.format("%02d:%02d:00", npTimePickerHour.value, npTimePickerMinute.value)
// )
// }
dismiss()
}
}

companion object {
const val HOUR_MIN = 1
const val HOUR_MAX = 12
const val MINUTE_MIN = 0
const val MINUTE_MAX = 59
}
Comment on lines +75 to +80
Copy link
Collaborator

Choose a reason for hiding this comment

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

잘했어욤 ~

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,23 @@ import kotlinx.coroutines.flow.asStateFlow
class PlanViewModel : ViewModel() {
private val _currentPage = MutableStateFlow(FIRST_PAGE_POSITION)
val currentPage get() = _currentPage.asStateFlow()
private val _planDate = MutableStateFlow<String?>(null)
val planDate get() = _planDate.asStateFlow()
private val _selectedTimeType = MutableStateFlow<String?>(null)
val selectedTimeType get() = _selectedTimeType.asStateFlow()

fun setCurrentPage(position: Int) {
_currentPage.value = position
}

fun setPlanDate(planDate: String) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

우하하 이런 식으루 뷰모델에 저장하는 것이로군 쇽샥!!!!!!!!!!!!!!!!!!!!!!!

_planDate.value = planDate
}

fun setSelectedTimeType(timeType: String) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

쩐당

_selectedTimeType.value = timeType
}

companion object {
const val FIRST_PAGE_POSITION = 0
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ import org.sopt.pingle.R
import org.sopt.pingle.databinding.EditTextPingleBinding

@SuppressLint("CustomViewStyleable")
class PingleEditText(
class PingleEditText @JvmOverloads constructor(
Copy link
Collaborator

Choose a reason for hiding this comment

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

오와 생성자 오버로딩을 자동으로 생성해주는 어노테이션이라니 나중에 이런 식으로 커스텀뷰 만들 때 참고할게요~!

context: Context,
attrs: AttributeSet
) : ConstraintLayout(context, attrs) {
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : ConstraintLayout(context, attrs, defStyleAttr) {
private lateinit var binding: EditTextPingleBinding
private var _etText: String? = null

init {
val typedArray = context.obtainStyledAttributes(attrs, R.styleable.pingleEditText)
Expand All @@ -33,6 +35,9 @@ class PingleEditText(

val hint = getString(R.styleable.pingleEditText_hint)
binding.etEditText.hint = hint

_etText = getString(R.styleable.pingleEditText_etText)
binding.etEditText.setText(_etText)
}
}
}
60 changes: 60 additions & 0 deletions app/src/main/res/layout/dialog_date_picker.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">

<data>

</data>

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/g_10">

<TextView
android:id="@+id/tv_date_picker_done"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@color/g_11"
android:paddingVertical="7dp"
android:paddingEnd="15dp"
android:text="Done"
Copy link
Collaborator

Choose a reason for hiding this comment

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

추출 부탁합니둥

android:textAlignment="textEnd"
android:textColor="@color/pingle_green"
android:textSize="18dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<NumberPicker
android:id="@+id/np_date_picker_year"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginVertical="20dp"
android:layout_marginStart="44dp"
android:theme="@style/AppTheme.NumberPicker"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_date_picker_done" />
Copy link
Collaborator

Choose a reason for hiding this comment

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

여기 제약에 @id 사용해주세욥


<NumberPicker
android:id="@+id/np_date_picker_month"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.NumberPicker"
app:layout_constraintBottom_toBottomOf="@+id/np_date_picker_year"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/np_date_picker_year" />
Copy link
Collaborator

Choose a reason for hiding this comment

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

전부!!


<NumberPicker
android:id="@+id/np_date_picker_day"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="44dp"
android:theme="@style/AppTheme.NumberPicker"
app:layout_constraintBottom_toBottomOf="@+id/np_date_picker_month"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/np_date_picker_month" />
Comment on lines +29 to +58
Copy link
Collaborator

Choose a reason for hiding this comment

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

이거 체인 거는 게 나을 것 같습니다요

</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
Loading
Loading