RecyclerView 공백 ViewHolder 문제
DoDoBest
·2024. 2. 14. 05:50
ConstraintLayout 내부에 ConstraintLayout을 topToBottom=parent 설정으로 숨겼다. 특정 버튼을 선택하면 이 Constraintlayout의 Top 제약 변경해서 사용자에게 보이도록 구현했다. 제약을 update 하는 함수만 있고, delete 하는 함수는 없는데, UNSET은 기존에 설정된 제약 설정을 없애는 것과 동일한 효과를 준다.
findViewById<View>(R.id.lyric_view).updateLayoutParams<ConstraintLayout.LayoutParams> {
topToTop = binding.root.id
topToBottom = ConstraintLayout.LayoutParams.UNSET
}
ConstraintLayout이 보일 때, 아래에서 올라오는 효과를 주기 위해 android:animateLayoutChanges="true" 속성을 추가하고, onCreate 함수에서 아래 코드를 호출했다.
binding.lyricView.root.layoutTransition.enableTransitionType(
LayoutTransition.CHANGING
)
X 버튼을 누르면 다시 topToBottom을 parent로 설정하여 사용자에게 보이지 않도록 했다.
findViewById<View>(R.id.lyric_view).updateLayoutParams<ConstraintLayout.LayoutParams> {
topToTop = ConstraintLayout.LayoutParams.UNSET
topToBottom = binding.root.id
}
아래와 같이 행동하면 예상하지 않은 결과가 나타났다.
1. 내부 ConstraintLayout이 보이도록 한다.
2. 내부 ConstraintLayout에 있는 RecyclerView를 아래로 드래그한다.
3. 내부 ConstraintLayout이 보이지 않도록 한다.
4. 내부 ConstarintLayout이 보이도록 한다.
개발자 모드의 레이아웃 표시로 UI 상태를 확인해보면 ViewHolder 사이에 빈 공간이 생겼다.
이것은 빈 공간의 ViewHolder다. 현재 ViewHolder에 사용되는 item layout은 아래와 같이 되어 있다.
<?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="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Very Very Very Very Very Very Very Very Very Long Lyric" />
</androidx.constraintlayout.widget.ConstraintLayout>
layout_margin 13dp를 설정하면 명확히 알 수 있다.
빈 공간의 ViewHolder가 안 보이도록 드래그하면, 재활용되어 사라진다.
왜 생긴 것일까? 전에도 비슷한 문제를 겪은 적이 있다. 당시에는 ViewHolder의 height을 match_parent로 설정하여 발생했다.
https://github.com/DoTheBestMayB/UpbitAPI/discussions/30
하지만 이번에는 ViewHolder의 height도 wrap_content로 설정했다.
android:animateLayoutChanges="true" 속성을 지워봤으나, 여전히 똑같은 문제가 발생했다.
발생 조건을 좀 더 확인해보니, 최상단으로부터 아주 조금이라도 아래로 드래그하면 빈 공백의 ViewHolder가 생성됐다.
아주 느린 화면으로 살펴보면, X 버튼을 눌러 RecyclerView가 속한 ConstraintLayout의 ConstraintSet을 수정(topToTop parent 에서 topToBottom parent로)하자마자 빈 ViewHolder가 생기는 것을 볼 수 있다.
빈 ViewHolder가 생성되지 않을 때는 아래와 같다
LayoutInflater로 확인해보니, 빈 ViewHolder가 아닌 text가 존재하는 ViewHolder 였다. 또한 width가 0dp로 설정되어 있었다.
현재 ViewHolder의 ConstraintLayout width는 wrap_content로 되어 있다.
ViewHolder의 ConstraintLayout width를 match_parent로 설정해서 무조건 펴지게 하면 어떻게 될까?
그러자 width가 0dp이고, 세로로 긴 ViewHolder가 사라졌다.
그렇다면 정확한 원인은 무엇일까? 비슷한 사례가 있는지 찾아보면서 아래와 같은 게시물을 발견했다.
원인이 무엇인지 알려면 View가 그려지는 원리를 이해해야할 것 같다.
View가 그려지는 원리에 대한 학습 및 정리 후, 다시 위에서 발생한 문제의 원인을 분석하는 글을 작성하겠다.
최종적으로 ViewHolder의 xml은 아래와 같다.
<?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_marginVertical="5dp">
<TextView
android:id="@+id/text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textSize="18sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Very Very Very Very Very Very Very Very Very Long Lyric" />
</androidx.constraintlayout.widget.ConstraintLayout>
'학습' 카테고리의 다른 글
for .. in 은 무엇일까 (0) | 2024.03.08 |
---|---|
Android에서 ConstraintLayout은 왜 사용하는 걸까 (0) | 2024.03.03 |
Android에서 View는 어떻게 그려질까? - 1 (0) | 2024.02.28 |
Android에서 Retrofit은 왜 사용하는 걸까 (0) | 2024.02.08 |
Android popUpTo가 동작하지 않는 경우 (0) | 2023.11.13 |