-
Notifications
You must be signed in to change notification settings - Fork 0
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 : 학사 일정 데이트 피커 #263
base: develop
Are you sure you want to change the base?
Feat : 학사 일정 데이트 피커 #263
Changes from all commits
4c20ac4
c07455b
0b1dd99
3df50b7
53cb663
3929280
7e4ab80
63ea740
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
package com.dongyang.android.youdongknowme.ui.view.schedule | ||
|
||
import android.app.Dialog | ||
import android.os.Bundle | ||
import android.view.LayoutInflater | ||
import android.view.View | ||
import android.view.ViewGroup | ||
import android.widget.NumberPicker | ||
import androidx.fragment.app.activityViewModels | ||
import com.dongyang.android.youdongknowme.R | ||
import com.dongyang.android.youdongknowme.databinding.DialogDatepickerBinding | ||
import com.google.android.material.bottomsheet.BottomSheetDialog | ||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment | ||
import com.prolificinteractive.materialcalendarview.CalendarDay | ||
import org.threeten.bp.LocalDate | ||
|
||
class DatePickerDialog( | ||
private val year: Int, | ||
private val month: Int, | ||
private val listener: ScheduleClickListener | ||
) : BottomSheetDialogFragment() { | ||
|
||
private var _binding: DialogDatepickerBinding? = null | ||
private val binding get() = _binding!! | ||
|
||
override fun onCreateView( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fragment의 생명주기에 대해서 알고 계신가요 ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이전에 타프로젝트에서 언급주셨던 부분이라 기억하고 있습니다. |
||
inflater: LayoutInflater, | ||
container: ViewGroup?, | ||
savedInstanceState: Bundle?, | ||
): View { | ||
|
||
_binding = DialogDatepickerBinding.inflate(inflater, container, false) | ||
val view = binding.root | ||
Comment on lines
+32
to
+33
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 뷰바인딩을 초기화하고 반환 이후에 binding 객체를 사용하는 게 더 안전해보입니다! |
||
|
||
// 현재 연도 | ||
val currentYear = LocalDate.now().year | ||
|
||
// 순환 막기 | ||
binding.numberpickerDialogDatepickerYear.wrapSelectorWheel = false | ||
binding.numberpickerDialogDatepickerMonth.wrapSelectorWheel = false | ||
|
||
// editText 설정 막기 | ||
binding.numberpickerDialogDatepickerYear.descendantFocusability = | ||
NumberPicker.FOCUS_BLOCK_DESCENDANTS | ||
binding.numberpickerDialogDatepickerMonth.descendantFocusability = | ||
NumberPicker.FOCUS_BLOCK_DESCENDANTS | ||
|
||
// 연도 최소/최대값 설정 및 출력 방식 설정 | ||
with(binding.numberpickerDialogDatepickerYear) { | ||
minValue = currentYear - 1 | ||
maxValue = currentYear + 1 | ||
displayedValues = | ||
((minValue..maxValue).map { "$it${getString(R.string.calendar_year)}" } | ||
.toTypedArray()) | ||
} | ||
|
||
// 월 최소/최대값 설정 및 출력 방식 설정 | ||
with(binding.numberpickerDialogDatepickerMonth) { | ||
minValue = 1 | ||
maxValue = if (year == currentYear + 1) 2 else 12 | ||
|
||
// 연도 선택에 따른 월의 최대값 동적 설정 | ||
huiwoo-jo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
binding.numberpickerDialogDatepickerYear.setOnValueChangedListener { _, _, newYear -> | ||
maxValue = if (newYear == currentYear + 1) 2 else 12 | ||
} | ||
|
||
displayedValues = | ||
((minValue..maxValue).map { "$it${getString(R.string.calendar_month)}" } | ||
.toTypedArray()) | ||
} | ||
|
||
// 초기 설정 | ||
binding.numberpickerDialogDatepickerYear.value = year | ||
binding.numberpickerDialogDatepickerMonth.value = month | ||
|
||
Comment on lines
+72
to
+75
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 초기값을 설정하는 건 onCreateView에서의 역할이 아닌 것 같습니다! 뷰바인딩이 세팅이 끝난 후인 onViewCreated로 옮겨보시죵 |
||
return view | ||
} | ||
|
||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { | ||
|
||
super.onViewCreated(view, savedInstanceState) | ||
|
||
binding.tvDialogPermissionComplete.setOnClickListener { | ||
val year = binding.numberpickerDialogDatepickerYear.value | ||
val month = binding.numberpickerDialogDatepickerMonth.value | ||
val date = CalendarDay.from(year, month, 1) | ||
|
||
listener.buttonClick(date = date) | ||
|
||
dismiss() | ||
Comment on lines
+83
to
+90
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 지금 방법은 MVVM 패턴이 아닌 것 같습니다! view 변경 시 ViewModel 내 메서드 호출 > fragment 에서 viewModel의 파라미터 observing > 학사일정 변경 |
||
} | ||
} | ||
|
||
|
||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { | ||
|
||
return BottomSheetDialog(requireContext(), R.style.CustomBottomSheetDialogTheme) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 친구는 onCreateView에서 작동을 안 하나요 ? setStyle(STYLE_NORMAL, R.style.WebsosoDialogTheme) 요 코드 넣어보시면 될 거예요 |
||
} | ||
|
||
override fun onDestroyView() { | ||
|
||
super.onDestroyView() | ||
_binding = null | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package com.dongyang.android.youdongknowme.ui.view.schedule | ||
|
||
import com.prolificinteractive.materialcalendarview.CalendarDay | ||
|
||
interface ScheduleClickListener { | ||
fun buttonClick(date: CalendarDay) | ||
} | ||
Comment on lines
+5
to
+7
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 인터페이스를 제거해보시죠! |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,7 @@ | ||
package com.dongyang.android.youdongknowme.ui.view.schedule | ||
|
||
import android.content.res.ColorStateList | ||
import android.graphics.Bitmap | ||
import android.graphics.Canvas | ||
import android.graphics.PorterDuff | ||
import android.graphics.drawable.BitmapDrawable | ||
import android.graphics.drawable.Drawable | ||
import androidx.core.content.ContextCompat | ||
import androidx.core.content.res.ResourcesCompat | ||
import androidx.core.graphics.drawable.DrawableCompat | ||
import androidx.recyclerview.widget.DividerItemDecoration | ||
import androidx.recyclerview.widget.LinearLayoutManager | ||
import com.dongyang.android.youdongknowme.R | ||
|
@@ -21,20 +14,65 @@ import org.koin.androidx.viewmodel.ext.android.viewModel | |
import org.threeten.bp.LocalDate | ||
|
||
/* 학사 일정 화면 */ | ||
class ScheduleFragment : BaseFragment<FragmentScheduleBinding, ScheduleViewModel>() { | ||
class ScheduleFragment : BaseFragment<FragmentScheduleBinding, ScheduleViewModel>(), | ||
ScheduleClickListener { | ||
|
||
override val layoutResourceId: Int = R.layout.fragment_schedule | ||
override val viewModel: ScheduleViewModel by viewModel() | ||
|
||
private lateinit var adapter: ScheduleAdapter | ||
|
||
private var _year = LocalDate.now().year.toString() | ||
private var year = _year | ||
|
||
private var _month = LocalDate.now().month.toString() | ||
private var month = _month | ||
Comment on lines
+25
to
+29
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 둘 다 접근제한자가 private인데 프래그먼트에서 배킹프로퍼티를 사용하는 이유가 있나요 ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 기존 코드들을 참고하여서 배킹 프로퍼티의 의미를 제대로 생각 못한거 같습니다🤔 |
||
|
||
override fun buttonClick(date: CalendarDay) { | ||
viewModel.setPickedDate(date) | ||
} | ||
Comment on lines
+31
to
+33
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 인터페이스를 만들지 않고, 다이얼로그에서 버튼을 클릭했을 때 viewModel.setPickedDate 를 사용하면 될 것 같아요 |
||
|
||
// 연/월 방식으로 타이틀 처리 | ||
fun setCalenderHeader() { | ||
binding.mvScheduleCalendar.setTitleFormatter { day -> | ||
val inputText: LocalDate = day.date | ||
val calendarHeaderElements = inputText.toString().split("-").toTypedArray() | ||
|
||
year = calendarHeaderElements[0] | ||
month = calendarHeaderElements[1] | ||
|
||
val calendarHeaderBuilder = StringBuilder() | ||
calendarHeaderBuilder.append(year) | ||
.append(getString(R.string.calendar_year)) | ||
.append(" ") | ||
.append(month) | ||
.append(getString(R.string.calendar_month)) | ||
calendarHeaderBuilder.toString() | ||
} | ||
} | ||
|
||
override fun initStartView() { | ||
|
||
binding.vm = viewModel | ||
|
||
viewModel.setPickedDate(binding.mvScheduleCalendar.currentDate) | ||
|
||
binding.mvScheduleCalendar.leftArrow.setTintList(ColorStateList.valueOf(ContextCompat.getColor(this.requireContext(), R.color.blue300))) | ||
binding.mvScheduleCalendar.rightArrow.setTintList(ColorStateList.valueOf(ContextCompat.getColor(this.requireContext(), R.color.blue300))) | ||
binding.mvScheduleCalendar.leftArrow.setTintList( | ||
ColorStateList.valueOf( | ||
ContextCompat.getColor( | ||
this.requireContext(), | ||
R.color.blue300 | ||
) | ||
) | ||
) | ||
binding.mvScheduleCalendar.rightArrow.setTintList( | ||
ColorStateList.valueOf( | ||
ContextCompat.getColor( | ||
this.requireContext(), | ||
R.color.blue300 | ||
) | ||
) | ||
) | ||
|
||
adapter = ScheduleAdapter() | ||
binding.rvScheduleList.apply { | ||
|
@@ -55,10 +93,18 @@ class ScheduleFragment : BaseFragment<FragmentScheduleBinding, ScheduleViewModel | |
else dismissLoading() | ||
} | ||
|
||
viewModel.pickYear.observe(viewLifecycleOwner) { | ||
viewModel.getSchedules() | ||
} | ||
|
||
viewModel.pickMonth.observe(viewLifecycleOwner) { | ||
viewModel.getSchedules() | ||
} | ||
|
||
viewModel.selectedDate.observe(viewLifecycleOwner) { date -> | ||
updateCalendarViewHeader(date) | ||
} | ||
|
||
viewModel.scheduleList.observe(viewLifecycleOwner) { | ||
adapter.submitList(it) | ||
} | ||
|
@@ -68,34 +114,35 @@ class ScheduleFragment : BaseFragment<FragmentScheduleBinding, ScheduleViewModel | |
} | ||
} | ||
|
||
private fun updateCalendarViewHeader(date: CalendarDay) { | ||
binding.mvScheduleCalendar.setCurrentDate(date) | ||
|
||
setCalenderHeader() | ||
} | ||
|
||
|
||
override fun initAfterBinding() { | ||
|
||
binding.mvScheduleCalendar.setOnMonthChangedListener { _, date -> | ||
viewModel.setPickedDate(date) | ||
} | ||
|
||
binding.mvScheduleCalendar.setOnTitleClickListener { | ||
val dialog = DatePickerDialog( | ||
year = year.toInt(), | ||
month = month.toInt(), | ||
listener = this@ScheduleFragment | ||
) | ||
dialog.show(requireActivity().supportFragmentManager, "CustomDialog") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Tag 값은 상수화해서 사용하는 게 좋을 것 같아요! 그리고 커스텀 다이얼로그 보다는 다른 네이밍을 사용하면 좋을 것 같습니당 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
} | ||
|
||
// 최소 날짜, 최대 날짜 지정 | ||
binding.mvScheduleCalendar.apply { | ||
this.state().edit().setMinimumDate(CalendarDay.from(2023, 1, 1)) | ||
.setMaximumDate(CalendarDay.from(2025, 2, 28)) | ||
.commit() | ||
} | ||
|
||
// 연/월 방식으로 타이틀 처리 | ||
binding.mvScheduleCalendar.setTitleFormatter { day -> | ||
val inputText: LocalDate = day.date | ||
val calendarHeaderElements = inputText.toString().split("-").toTypedArray() | ||
|
||
val year = calendarHeaderElements[0] | ||
val month = calendarHeaderElements[1] | ||
|
||
val calendarHeaderBuilder = StringBuilder() | ||
calendarHeaderBuilder.append(year) | ||
.append(getString(R.string.calendar_year)) | ||
.append(" ") | ||
.append(month) | ||
.append(getString(R.string.calendar_month)) | ||
calendarHeaderBuilder.toString() | ||
} | ||
setCalenderHeader() | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<shape xmlns:android="http://schemas.android.com/apk/res/android"> | ||
<corners android:radius="20dp" /> | ||
<solid android:color="@color/white" /> | ||
</shape> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<vector xmlns:android="http://schemas.android.com/apk/res/android" | ||
android:width="48dp" | ||
android:height="5dp" | ||
android:viewportWidth="48" | ||
android:viewportHeight="5"> | ||
<path | ||
android:pathData="M0,2.035C0,0.911 0.911,0 2.035,0H45.965C47.089,0 48,0.911 48,2.035V2.035C48,3.159 47.089,4.07 45.965,4.07H2.035C0.911,4.07 0,3.159 0,2.035V2.035Z" | ||
android:fillColor="#7F8295"/> | ||
</vector> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||
xmlns:app="http://schemas.android.com/apk/res-auto" | ||
xmlns:tools="http://schemas.android.com/tools" | ||
android:layout_width="match_parent" | ||
android:layout_height="wrap_content" | ||
android:layout_margin="20dp"> | ||
|
||
<ImageView | ||
android:layout_width="wrap_content" | ||
android:layout_height="wrap_content" | ||
android:src="@drawable/ic_dialog_handle" | ||
app:layout_constraintStart_toStartOf="parent" | ||
app:layout_constraintEnd_toEndOf="parent" | ||
app:layout_constraintTop_toTopOf="parent" | ||
android:layout_marginTop="10dp"/> | ||
|
||
<NumberPicker | ||
android:id="@+id/numberpicker_dialog_datepicker_year" | ||
style="@style/PretendardMedium24" | ||
android:layout_width="0dp" | ||
android:layout_height="wrap_content" | ||
android:layout_marginHorizontal="16dp" | ||
android:layout_marginVertical="36dp" | ||
android:theme="@style/Theme.YouDongKnowMe.NumberPicker" | ||
app:layout_constraintEnd_toStartOf="@id/numberpicker_dialog_datepicker_month" | ||
app:layout_constraintStart_toStartOf="parent" | ||
app:layout_constraintTop_toTopOf="parent" /> | ||
|
||
<NumberPicker | ||
android:id="@+id/numberpicker_dialog_datepicker_month" | ||
style="@style/PretendardMedium24" | ||
android:layout_width="0dp" | ||
android:layout_height="wrap_content" | ||
android:layout_marginHorizontal="16dp" | ||
android:layout_marginVertical="36dp" | ||
android:theme="@style/Theme.YouDongKnowMe.NumberPicker" | ||
app:layout_constraintEnd_toEndOf="parent" | ||
app:layout_constraintStart_toEndOf="@+id/numberpicker_dialog_datepicker_year" | ||
app:layout_constraintTop_toTopOf="parent" /> | ||
|
||
<androidx.appcompat.widget.AppCompatButton | ||
android:id="@+id/tv_dialog_permission_complete" | ||
style="@style/PretendardMedium24" | ||
android:layout_width="0dp" | ||
android:layout_height="56dp" | ||
android:layout_marginHorizontal="16dp" | ||
android:layout_marginVertical="20dp" | ||
android:background="@drawable/btn_gray_to_blue_10dp_enabled" | ||
android:text="@string/dialog_datepicker_comlete" | ||
android:textColor="@color/white" | ||
app:layout_constraintBottom_toBottomOf="parent" | ||
app:layout_constraintEnd_toEndOf="parent" | ||
app:layout_constraintStart_toStartOf="parent" | ||
app:layout_constraintTop_toBottomOf="@id/numberpicker_dialog_datepicker_year" /> | ||
</androidx.constraintlayout.widget.ConstraintLayout> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
생성자로 연도, 월, 클릭리스너를 받아야 할까요?