-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #481 from woowacourse-teams/AN/feature/449-studyde…
…tail-inflate [스터디 상세보기 뷰] 스터디 시작 시 보여질 요일 선택 뷰를 구현합니다.
- Loading branch information
Showing
14 changed files
with
560 additions
and
3 deletions.
There are no files selected for viewing
22 changes: 22 additions & 0 deletions
22
...c/main/java/com/created/team201/presentation/common/customview/dayofselector/DayOfWeek.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package com.created.team201.presentation.common.customview.dayofselector | ||
|
||
import androidx.annotation.StringRes | ||
import com.created.team201.R | ||
|
||
enum class DayOfWeek(@StringRes val stringRes: Int) { | ||
MONDAY(R.string.monday), | ||
TUESDAY(R.string.tuesday), | ||
WEDNESDAY(R.string.wednesday), | ||
THURSDAY(R.string.thursday), | ||
FRIDAY(R.string.friday), | ||
SATURDAY(R.string.saturday), | ||
SUNDAY(R.string.sunday), | ||
; | ||
|
||
companion object { | ||
fun getValuesWithStartDay(startDay: DayOfWeek = MONDAY): List<DayOfWeek> { | ||
val values = DayOfWeek.values() | ||
return values.slice(startDay.ordinal until values.size) + values.slice(0 until startDay.ordinal) | ||
} | ||
} | ||
} |
169 changes: 169 additions & 0 deletions
169
...ava/com/created/team201/presentation/common/customview/dayofselector/DayOfWeekSelector.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
package com.created.team201.presentation.common.customview.dayofselector | ||
|
||
import android.content.Context | ||
import android.content.res.TypedArray | ||
import android.graphics.drawable.Drawable | ||
import android.util.AttributeSet | ||
import android.view.LayoutInflater | ||
import android.widget.TextView | ||
import androidx.annotation.DrawableRes | ||
import androidx.constraintlayout.widget.ConstraintLayout | ||
import androidx.core.content.res.ResourcesCompat | ||
import androidx.core.view.children | ||
import androidx.databinding.BindingAdapter | ||
import com.created.team201.R | ||
import com.created.team201.databinding.ViewDayOfWeekSelectorBinding | ||
|
||
class DayOfWeekSelector @JvmOverloads constructor( | ||
context: Context, | ||
attrs: AttributeSet? = null, | ||
) : ConstraintLayout(context, attrs) { | ||
|
||
private val binding: ViewDayOfWeekSelectorBinding by lazy { | ||
ViewDayOfWeekSelectorBinding.inflate(LayoutInflater.from(context), this, true) | ||
} | ||
|
||
private val dayTextViews: Map<DayOfWeek, TextView> by lazy { initDayTextViews() } | ||
|
||
private val textViewDays: Map<TextView, DayOfWeek> by lazy { initTextViewDays() } | ||
|
||
private var canMultiSelect: Boolean = false | ||
|
||
private var dayOnClick: DayOnClickListener? = null | ||
|
||
fun interface DayOnClickListener { | ||
fun onClick(day: DayOfWeek) | ||
} | ||
|
||
init { | ||
attrs?.let { setTypedArray(getAttrs(it)) } | ||
setupDayTexts() | ||
setupDayClickListeners() | ||
} | ||
|
||
private fun initDayTextViews(): Map<DayOfWeek, TextView> = | ||
DayOfWeek.getValuesWithStartDay() | ||
.zip(binding.clDayOfWeekBackground.children.filterIsInstance<TextView>().toList()) | ||
.toMap() | ||
|
||
private fun initTextViewDays(): Map<TextView, DayOfWeek> = | ||
dayTextViews.entries.associateBy({ it.value }, { it.key }) | ||
|
||
private fun getAttrs(attrs: AttributeSet): TypedArray { | ||
return context.obtainStyledAttributes(attrs, R.styleable.DayOfWeekSelector) | ||
} | ||
|
||
private fun setTypedArray(typedArray: TypedArray) { | ||
canMultiSelect = | ||
typedArray.getBoolean(R.styleable.DayOfWeekSelector_canMultipleSelect, false) | ||
|
||
if (canMultiSelect) { | ||
dayTextViews.values.forEach { | ||
it.background = getBackground(R.drawable.bg_day_of_week_selector_multi_select) | ||
} | ||
} else { | ||
dayTextViews.values.forEach { | ||
it.background = getBackground(R.drawable.bg_day_of_week_selector_single_select) | ||
} | ||
} | ||
|
||
typedArray.recycle() | ||
} | ||
|
||
private fun getBackground(@DrawableRes id: Int): Drawable? = ResourcesCompat.getDrawable( | ||
resources, | ||
id, | ||
null, | ||
) | ||
|
||
private fun setupDayClickListeners() { | ||
dayTextViews.values.forEach { dayTextView -> | ||
dayTextView.setOnClickListener { it -> | ||
val clickedDay: DayOfWeek = | ||
requireNotNull(textViewDays[it]) { "$it 에 해당하는 요일이 존재하지 않습니다." } | ||
if (canMultiSelect) { | ||
selectDayTextView(dayTextView) | ||
dayOnClick?.onClick(clickedDay) | ||
return@setOnClickListener | ||
} | ||
|
||
if (it.isSelected) return@setOnClickListener | ||
|
||
selectDayTextView(dayTextView) | ||
|
||
dayTextViews.values | ||
.filterNot { it == dayTextView } | ||
.forEach { it.isSelected = false } | ||
dayOnClick?.onClick(clickedDay) | ||
} | ||
} | ||
} | ||
|
||
private fun setupDayTexts() { | ||
val days: List<DayOfWeek> = DayOfWeek.getValuesWithStartDay() | ||
dayTextViews.values.forEachIndexed { index, textView -> | ||
textView.text = resources.getString(days[index].stringRes) | ||
} | ||
} | ||
|
||
fun setSelectableDays(selectableDays: List<DayOfWeek>) { | ||
dayTextViews.keys.forEach { | ||
if (selectableDays.contains(it)) { | ||
dayTextViews[it]?.isEnabled = true | ||
return@forEach | ||
} | ||
dayTextViews[it]?.isEnabled = false | ||
} | ||
} | ||
|
||
fun selectDay(day: DayOfWeek) { | ||
dayTextViews[day]?.isSelected = true | ||
} | ||
|
||
fun selectDays(days: List<DayOfWeek>) { | ||
days.forEach { day -> | ||
val textView: TextView = | ||
requireNotNull(dayTextViews[day]) { "$day 에 해당하는 TextView가 존재하지 않습니다." } | ||
|
||
textView.isSelected = !(textView.isSelected) | ||
} | ||
} | ||
|
||
private fun selectDayTextView(day: TextView) { | ||
day.isSelected = !day.isSelected | ||
} | ||
|
||
fun getSelectedDays(): List<DayOfWeek> { | ||
val selectedDayTextViews: List<TextView> = dayTextViews.values.filter { it.isSelected } | ||
return selectedDayTextViews.map { requireNotNull(textViewDays[it]) { "$it 에 해당하는 요일이 존재하지 않습니다." } } | ||
} | ||
|
||
fun setDayOnClickListener(dayOnClickListener: DayOnClickListener) { | ||
dayOnClick = dayOnClickListener | ||
} | ||
|
||
fun getSelectedDaysSize(): Int { | ||
return dayTextViews.values.count { it.isSelected } | ||
} | ||
|
||
companion object { | ||
|
||
@JvmStatic | ||
@BindingAdapter("selectableDays") | ||
fun setSelectableDays( | ||
dayOfWeekSelector: DayOfWeekSelector, | ||
selectableDays: List<DayOfWeek>, | ||
) { | ||
dayOfWeekSelector.setSelectableDays(selectableDays) | ||
} | ||
|
||
@JvmStatic | ||
@BindingAdapter("dayOnClick") | ||
fun setDayOnClickListener( | ||
dayOfWeekSelector: DayOfWeekSelector, | ||
dayOnClickListener: DayOnClickListener, | ||
) { | ||
dayOfWeekSelector.setDayOnClickListener(dayOnClickListener) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
79 changes: 79 additions & 0 deletions
79
...com/created/team201/presentation/studyDetail/bottomSheet/StudyStartBottomSheetFragment.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
package com.created.team201.presentation.studyDetail.bottomSheet | ||
|
||
import android.os.Bundle | ||
import android.view.View | ||
import android.widget.Toast | ||
import androidx.fragment.app.activityViewModels | ||
import com.created.team201.R | ||
import com.created.team201.databinding.FragmentStudyStartBottomSheetBinding | ||
import com.created.team201.presentation.common.BindingBottomSheetFragment | ||
import com.created.team201.presentation.studyDetail.StudyDetailViewModel | ||
|
||
class StudyStartBottomSheetFragment : | ||
BindingBottomSheetFragment<FragmentStudyStartBottomSheetBinding>( | ||
R.layout.fragment_study_start_bottom_sheet, | ||
) { | ||
private val studyDetailViewModel: StudyDetailViewModel by activityViewModels() | ||
|
||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { | ||
super.onViewCreated(view, savedInstanceState) | ||
|
||
initBinding() | ||
setupDayOnClickListener() | ||
} | ||
|
||
private fun initBinding() { | ||
binding.viewModel = studyDetailViewModel | ||
binding.onCancelClickListener = { dismiss() } | ||
binding.onStartClickListener = ::onStartButtonClick | ||
binding.lifecycleOwner = viewLifecycleOwner | ||
} | ||
|
||
private fun setupDayOnClickListener() { | ||
binding.dowsStudyStartBottomSheetDayOfWeekSelector.setDayOnClickListener { | ||
val selectedDaysSize: Int = | ||
binding.dowsStudyStartBottomSheetDayOfWeekSelector.getSelectedDaysSize() | ||
|
||
if (selectedDaysSize > 0) { | ||
binding.tvStudyStartBottomSheetBtnStart.isEnabled = true | ||
return@setDayOnClickListener | ||
} | ||
binding.tvStudyStartBottomSheetBtnStart.isEnabled = false | ||
} | ||
} | ||
|
||
private fun onStartButtonClick() { | ||
// val studyId = arguments?.getLong(KEY_STUDY_ID) ?: INVALID_STUDY_ID | ||
// validateStudyId(studyId) | ||
// studyDetailViewModel.startStudy(studyId) ToDo: 서버 연결시 수정 | ||
Toast.makeText( | ||
context, | ||
binding.dowsStudyStartBottomSheetDayOfWeekSelector.getSelectedDays().toString(), | ||
Toast.LENGTH_SHORT, | ||
).show() | ||
dismiss() | ||
} | ||
|
||
private fun validateStudyId(studyId: Long) { | ||
if (studyId == INVALID_STUDY_ID) { | ||
Toast.makeText( | ||
context, | ||
getString(R.string.study_start_bottom_sheet_dialog_fragment_not_valid_study), | ||
Toast.LENGTH_SHORT, | ||
).show() | ||
dismiss() | ||
} | ||
} | ||
|
||
companion object { | ||
private const val KEY_STUDY_ID: String = "KEY_STUDY_ID" | ||
private const val INVALID_STUDY_ID: Long = 0L | ||
|
||
fun newInstance(studyId: Long): StudyStartBottomSheetFragment = | ||
StudyStartBottomSheetFragment().apply { | ||
arguments = Bundle().apply { | ||
putLong(KEY_STUDY_ID, studyId) | ||
} | ||
} | ||
} | ||
} |
8 changes: 8 additions & 0 deletions
8
android/app/src/main/res/drawable/bg_day_of_week_selector.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<selector xmlns:android="http://schemas.android.com/apk/res/android"> | ||
<item> | ||
<shape android:shape="rectangle"> | ||
<corners android:radius="10dp" /> | ||
</shape> | ||
</item> | ||
</selector> |
11 changes: 11 additions & 0 deletions
11
android/app/src/main/res/drawable/bg_day_of_week_selector_multi_select.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<selector xmlns:android="http://schemas.android.com/apk/res/android"> | ||
|
||
<item android:state_selected="true"> | ||
<shape android:angle="0" android:shape="oval" android:useLevel="false"> | ||
|
||
<solid android:color="@color/green10_CC3AD353" /> | ||
</shape> | ||
</item> | ||
|
||
</selector> |
18 changes: 18 additions & 0 deletions
18
android/app/src/main/res/drawable/bg_day_of_week_selector_single_select.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<selector xmlns:android="http://schemas.android.com/apk/res/android"> | ||
|
||
<item android:state_enabled="true" android:state_selected="true"> | ||
<shape android:angle="0" android:shape="oval" android:useLevel="false"> | ||
|
||
<solid android:color="@color/green10_CC3AD353" /> | ||
</shape> | ||
</item> | ||
|
||
<item android:state_enabled="true" android:state_selected="false"> | ||
<shape android:angle="0" android:shape="oval" android:useLevel="false"> | ||
|
||
<solid android:color="@color/green03_016D32" /> | ||
</shape> | ||
</item> | ||
|
||
</selector> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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="32dp" | ||
android:height="32dp" | ||
android:viewportWidth="32" | ||
android:viewportHeight="32"> | ||
<path | ||
android:pathData="M17.414,16L24,9.414L22.586,8L16,14.586L9.414,8L8,9.414L14.586,16L8,22.586L9.414,24L16,17.414L22.586,24L24,22.586L17.414,16Z" | ||
android:fillColor="#ffffff"/> | ||
</vector> |
5 changes: 5 additions & 0 deletions
5
android/app/src/main/res/drawable/selector_study_start_bottom_sheet_btn_start_text_color.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<selector xmlns:android="http://schemas.android.com/apk/res/android"> | ||
<item android:state_enabled="false" android:color="@color/green09_799E82" /> | ||
<item android:color="#ffffff"/> | ||
</selector> |
Oops, something went wrong.