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

[AN/USER] feat: 검색 화면을 구현한다.(#784) #799

Merged
merged 61 commits into from
Apr 1, 2024
Merged

Conversation

SeongHoonC
Copy link
Member

@SeongHoonC SeongHoonC commented Mar 20, 2024

📌 관련 이슈

✨ PR 세부 내용

1. ClearEditText

처음엔 Material Design 의 EditText 를 사용하려 했으나 디자인이 원하는 대로 커스텀되지 않았습니다.

따라서 입력중인 문자열을 clear 할 수 있는 Custom EditText 를 넣었습니다.
박상권님 코드를 사용했습니다.

https://gun0912.tistory.com/56

2. 복잡한 화면

화면 상태가 좀 복잡합니다.

  1. 최근 검색어 화면
  • 최근 검색어 성공 RecentSearchSuccess & Empty
  • 최근 검색어 성공 RecentSearchSuccess & NotEmpty
image image
  1. 검색 중 : Loading

  2. 검색 성공

  • 검색 성공 SearchSuccess & Empty
  • 검색 성공 SearchSuccess & NotEmpty
image image
  • 검색 결과가 없어요 까지만 구현되어있고 추가 요청하러가기는 구현하지 않았습니다.
sealed interface SearchUiState {
    object Loading : SearchUiState

    data class RecentSearchSuccess(
        val recentSearchQueries: List<RecentSearchItemUiState>,
    ) : SearchUiState

    data class SearchSuccess(
        val searchedFestivals: List<FestivalSearchItemUiState>,
        val searchedArtists: List<ArtistSearchItemUiState>,
        val searchedSchools: List<SchoolSearchItemUiState>,
    ) : SearchUiState

    object Error : SearchUiState

    val shouldShowRecentSearchSuccessNotEmpty get() = this is RecentSearchSuccess && recentSearchQueries.isNotEmpty()
    val shouldShowEmptyRecentSearchSuccessEmpty get() = this is RecentSearchSuccess && recentSearchQueries.isEmpty()
    val shouldShowEmptyRecentSearchSuccess get() = this is RecentSearchSuccess
    val shouldShowSearchSuccess get() = this is SearchSuccess
    val shouldShowLoading get() = this is Loading
    val shouldShowError get() = this is Error
}

3. 상태 저장 문제

뷰페이저와 탭 레이아웃을 TabLayoutMediator 로 attach 해서 축제, 아티스트, 학교 화면을 전환시킵니다.

[검색] -(�목록 선택)-> [상세] - (뒤로가기 클릭)-> [검색]  

이렇게 이동하거나 구성변경 발생시 탭 포지션이 0으로 초기화되는 문제가 있었습니다. 그래서 해당 상태를 ItemSearchScreenUiState 객체를 뷰모델 프로퍼티로 저장합니다.

이 부분도 uiState 로 관리하려고 했으나 분리하지않으면 로직 관리가 힘들고 사이드 이팩트가 발생해서 분리했습니다.

아직 고치지 못한 부분이 홈 화면을 갔다오거나 핸드폰 껐다가키면 초기화 됩니다. restarted 되면 발생하는 것으로 예상 (고쳐보려고했는데 모르겠습니다.. 구성 변경은 대응이 되는데 왜...)

다행히 고쳤습니다..휴

4. 최근 검색어는 Room 으로 저장합니다.

searchQuery 가 primary_key 이고 createdAt 시간과 함께 저장합니다. 시간순으로 내림차순 불러옵니다.

시연 영상

KakaoTalk_Video_2024-03-20-15-06-54.mp4

@SeongHoonC SeongHoonC added AN 안드로이드에 관련된 작업 USER labels Mar 20, 2024
@SeongHoonC SeongHoonC self-assigned this Mar 20, 2024
@SeongHoonC SeongHoonC linked an issue Mar 20, 2024 that may be closed by this pull request
@github-actions github-actions bot requested review from EmilyCh0 and re4rk March 20, 2024 06:08
Copy link
Collaborator

@re4rk re4rk left a comment

Choose a reason for hiding this comment

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

고생하셨습니다!
코드가 엄청깔끔하네요! 생각 엄청하신게 느껴집니다!

style="@style/B3Medium14Lh14"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{@string/festival_list_tv_date_range_format(item.startDate.format(DateTimeFormatter.ofPattern(@string/festival_list_tv_date_format)),item.endDate.format(DateTimeFormatter.ofPattern(@string/festival_list_tv_date_format)))}"
Copy link
Collaborator

Choose a reason for hiding this comment

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

BindingAdapter가 마려워지네요 ㅋㅋㅋ


val shouldShowRecentSearchSuccessNotEmpty get() = this is RecentSearchSuccess && recentSearchQueries.isNotEmpty()
val shouldShowEmptyRecentSearchSuccessEmpty get() = this is RecentSearchSuccess && recentSearchQueries.isEmpty()
val shouldShowEmptyRecentSearchSuccess get() = this is RecentSearchSuccess
Copy link
Collaborator

Choose a reason for hiding this comment

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

네이밍은 shouldShowEmptyRecentSearchSuccess인데 내용은 Empty랑 관련 없는 것같습니다!
다음과 같은 네이밍은 어떤가요?

Suggested change
val shouldShowEmptyRecentSearchSuccess get() = this is RecentSearchSuccess
val shouldShowRecentSearchSuccess get() = this is RecentSearchSuccess

Comment on lines 18 to 19
val shouldShowRecentSearchSuccessNotEmpty get() = this is RecentSearchSuccess && recentSearchQueries.isNotEmpty()
val shouldShowEmptyRecentSearchSuccessEmpty get() = this is RecentSearchSuccess && recentSearchQueries.isEmpty()
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
val shouldShowRecentSearchSuccessNotEmpty get() = this is RecentSearchSuccess && recentSearchQueries.isNotEmpty()
val shouldShowEmptyRecentSearchSuccessEmpty get() = this is RecentSearchSuccess && recentSearchQueries.isEmpty()
val shouldShowNotEmptyRecentSearchSuccess get() = this is RecentSearchSuccess && recentSearchQueries.isNotEmpty()
val shouldShowEmptyRecentSearchSuccess get() = this is RecentSearchSuccess && recentSearchQueries.isEmpty()

과 같은 네이밍은 어떤가요??

import androidx.core.graphics.drawable.DrawableCompat
import com.festago.festago.presentation.R

class ClearEditText : AppCompatEditText, TextWatcher, OnTouchListener, OnFocusChangeListener {
Copy link
Collaborator

Choose a reason for hiding this comment

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

오 깔끔하네요 이렇게 만드니까


constructor(context: Context, attrs: AttributeSet) : super(context, attrs)

constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(
Copy link
Collaborator

Choose a reason for hiding this comment

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

자바 문법 같은데 코틀린은 생성자 하나로 합칠 수 있지 않나요?

constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0)
: View(context, attrs, defStyleAttr)```

Copy link
Member Author

Choose a reason for hiding this comment

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

수정해봤는데 제대로 동작을 안해서 되돌렸는데.. 다시 해보겠습니다!!

@@ -188,7 +188,8 @@ class FestivalListFragment : Fragment() {
}

private fun showSchoolDetail() {
findNavController().navigate(actionFestivalListFragmentToSchoolDetailFragment(0))
// findNavController().navigate(actionFestivalListFragmentToSchoolDetailFragment(0))
Copy link
Collaborator

Choose a reason for hiding this comment

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

주석 제거 해도 될 것같습니다!

}

private fun initSearchTab() {
binding.vpSearch.doOnNextLayout {
Copy link
Collaborator

Choose a reason for hiding this comment

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

뭔가 고급져보이는 방식이네요

Copy link
Member

@EmilyCh0 EmilyCh0 left a comment

Choose a reason for hiding this comment

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

리뷰 너무 늦어져서 죄송합니다.. 🥲 깔끔하네요 LGTM 👍👍

Comment on lines 38 to 51
<androidx.cardview.widget.CardView
android:id="@+id/cvSearch"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginVertical="12dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:backgroundTint="@color/background_gray_03"
android:elevation="0dp"
app:cardCornerRadius="1000dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/ivBack"
app:layout_constraintTop_toTopOf="parent">
Copy link
Member

Choose a reason for hiding this comment

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

android:outlineProvider="none" 속성 추가해서 그림자 없애는 게 어떨까요?

Comment on lines +24 to +26
if (times % 5 == 0) {
return Result.failure(Exception())
}
Copy link
Member

Choose a reason for hiding this comment

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

왜 가끔 Error로 넘어가는건가 했네요 🤣

Comment on lines 152 to 161
<TextView
android:id="@+id/tvRecentSearchEmpty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:text="@string/search_tv_recent_search_empty"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvRecentSearch"
app:visibility="@{uiState.shouldShowEmptyRecentSearchSuccess}" />
Copy link
Member

Choose a reason for hiding this comment

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

font 설정해주세요!

@SeongHoonC SeongHoonC merged commit ca21e27 into dev Apr 1, 2024
1 check passed
@SeongHoonC SeongHoonC deleted the feat/#784 branch April 1, 2024 06:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
AN 안드로이드에 관련된 작업 USER
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

[AN] 검색 화면을 구현한다.
3 participants