기존의 코드
1. HistoryPicturesAdapter : RecyclerView Adapter
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HistoryPicturesViewHolder {
itemBinding = ItemHistoryPicturesBinding.inflate(LayoutInflater.from(parent.context))
return HistoryPicturesViewHolder(itemBinding)
}
2. RecyclerView가 포함된 main화면 xml
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/myMushHistory"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
android:orientation="horizontal"
tools:listitem="@layout/item_history_pictures"
>
</androidx.recyclerview.widget.RecyclerView>
3. item_history_pictures (리사이클러 뷰 아이템 )
<FrameLayout
android:layout_width="100dp"
android:layout_height="100dp"
...
>
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
...
/>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
...
/>
</FrameLayout>
구현하고자 한 디자인이다.
3(아이템)에서 FragmentLayout의 width와 height를 100dp로 고정하여 RecyclerView에 100dp(20dp 패딩)의 정사각형 이미지가 들어가게 만들고자 하였다.
하지만 실제 구동 화면에서는 예상과는 다르게 고정되지 않은 직사각형의 화면 (wrap_content로 보임) 이 보인다.
이전에도 이런 상황이 있었는데, 원인은 viewholder의 LayoutInflater에 있었다.
LayoutInflater
여기서 root의 LayoutParams를 제공한다는 말이 이해가 잘 가지 않았다.
'내 코드에서 FrameLayout의 width와 height가 이미 100으로 고정되어 있는데, 내부에서 match_parent를 사용한 TextView와 ImageView의 크기가 왜 100dp로 고정이 안되는 것일까'
이는 LayoutParams의 계층 구조에 대한 잘못된 이해로부터 생긴 문제였다.
ViewGroup.LayoutParams
그림 2에서 볼 수 있듯이, 상위 뷰 그룹이 각 하위 뷰의 레이아웃 매개변수를 정의합니다(하위 뷰 그룹 포함).
LayoutParams가 xml상에서는 View에 속해 있는 것처럼 보이지만, 상위 ViewGroup의 LayoutParams에 정의된다는 것을 이해하면 앞서 본 설명이 이해가 된다.
FrameLayout(예제 xml 상 루트)의 LayoutParams가 부모에 속해 있어 전달이 되지 않았던 것이다.
예로 다음과 같은 코드는 기대와 같이 실행됨을 확인가능했다.
예제2
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
>
<data>
...
</data>
<FrameLayout
android:layout_height="0dp"
android:layout_width="0dp"
>
<FrameLayout
android:layout_width="100dp"
android:layout_height="100dp"
android:padding="10dp"
>
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
...
/>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
...
/>
</FrameLayout>
</FrameLayout>
</layout>
해당 코드는 루트로 껍데기뿐인 프레임레이아웃을 하나 더 감싼 예제로 width와 height를 0dp로 설정한 모습이다.
동일하게 Binding.inflate(LayoutInflater.from(parent.context))으로 inflate 하면, root의 LayoutParams는 전달되지 않아 원래 기대한 뷰의 모습이 실행되는 것이 확인가능했다.
예제2 코드는 LayoutParam의 계층 구조를 확인하기 위한 코드로
LayoutInflater.from(context).inflate(R.layout.layout_to_load, parent, false);
를 사용할 시 root의 LayoutParams가 제공되기에 앞선 예제2 코드와 같이 짤 필요는 없다.
추가적으로, attachRoot의 경우 true를 하면 inflate와 동시에 parent의 계층 구조에 속하게 되므로, viewholder에는 적합하지 않다. ( 해당 링크의 예시 코드를 보면 inflate 후 addView를 하여 뷰를 추가하는 것이 확인가능하며, attachRoot = ture인 경우 addView가 필요없음을 확인가능하다. )
수정된 1 어댑터 ( + 기존 Adapter Item XML )
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HistoryPicturesViewHolder {
itemBinding = ItemHistoryPicturesBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return HistoryPicturesViewHolder(itemBinding)
}
-> LayoutInflater.from(context).inflate(R.layout.layout_to_load, parent, false);
Why does LayoutInflater ignore the layout_width and layout_height layout parameters I've specified?
I've had severe trouble getting LayoutInflater to work as expected, and so did other people: How to use layoutinflator to add views at runtime?. Why does LayoutInflater ignore the layout parameter...
stackoverflow.com
레이아웃 | Android 개발자 | Android Developers
레이아웃 | Android 개발자 | Android Developers
레이아웃은 활동 또는 앱 위젯의 UI와 같은 사용자 인터페이스의 시각적 구조를 정의합니다. 두 가지 방법으로 레이아웃을 선언할 수 있습니다. Android 프레임워크를 통해 이 두 가지 메서드의 하
developer.android.com
LayoutInflater | Android Developers
LayoutInflater | Android Developers
developer.android.com
'Android > Feedback on Failures' 카테고리의 다른 글
<Refactoring> Retrofit과 데이터 모델 (0) | 2023.09.12 |
---|---|
<Refactoring> DTO 계층구조 (0) | 2023.09.11 |
<Refactoring> LiveData Observing (0) | 2023.09.10 |
ListAdapter의 submitList UI 반영 문제 (0) | 2023.08.15 |
RecyclerView에서의 ViewBinding 사용 (0) | 2023.08.03 |