[안드로이드] Adapter에서 inflate하는 view의 layout_height가 무시될 때

안녕하세요. 개발자 드리머즈입니다.


RecyclerView에서 사용하는 Recycler.ViewHolder(Adapter)의 onCreateViewHolder()에서 생성되는 view의 android:layout_height="45dp" 속성이 무시되는 문제를 발견했습니다. 아래의 xml 코드에서 가장 상위에 위치한 RelativeLayout의 android:layout_height가 무시됐습니다.(마치 wrap_content처럼 동작함) RelativeLayout의 child view의 android:layout_height는 무시되지 않고 정상적으로 동작했습니다.


item_header_row.xml 또는 item_content_row.xml

1
2
3
4
5
6
7
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="45dp"
    >
   (...생략...)
</RelativeLayout>
cs


위의 xml이 inflate되는 Recycler.ViewHolder(Adapter)의 코드는 아래와 같았습니다.

1
2
3
4
5
6
7
8
9
10
11
    // Create new views (invoked by the layout manager)
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == ITEM_TYPE_HEADER) {
            View headerRow = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_header_row, null);
            return new ItemHeaderViewHolder(headerRow); // view holder for header items
        }else/* if (viewType == ITEM_TYPE_NORMAL)*/ {
            View normalView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_content_row, null);
            return new ItemContentViewHolder(normalView); // view holder for normal items
        }
    }
cs


이 코드에 문제가 없는 줄 알았는데 그게 아니었습니다. 꺼림칙하게도 Android Studio에서 아래의 워닝?을 보여주고 있었습니다.


When inflating a layout, avoid passing in null as the parent view, since otherwise any layout parameters on the root of the inflated layout will be ignored.



해석을 하면,

레이아웃을 inflate할 때 parent view로 null을 넣는 것을 피하세요. 만약 그렇게 하지 않으면 inflate된 레이아웃의 root에 대한 모든 layout 파라미터들은 무시될 것이기 때문입니다.


이와 문제에 대한 설명이 있는 링크도 있습니다.(https://possiblemobile.com/2013/05/layout-inflation-as-intended/)

하지만 설명이 너무 길어 요점만 말하겠습니다.


1
2
inflate(int resource, ViewGroup root)
inflate(int resource, ViewGroup root, boolean attachToRoot)
cs


inflate함수는 위의 두 종류가 존재하는데 1번째 함수를 사용하면서 2번째 인자에 null을 주면 inflate된 레이아웃의 root에 대한 모든 layout 파라미터들이 무시된다는 것입니다. 그래서 2번째 함수를 아래처럼 사용하면 됩니다.


1
2
3
4
5
6
7
8
9
10
11
    // Create new views (invoked by the layout manager)
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == ITEM_TYPE_HEADER) {
            View headerRow = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_header_row, parent, false);
            return new ItemHeaderViewHolder(headerRow); // view holder for header items
        }else/* if (viewType == ITEM_TYPE_NORMAL)*/ {
            View normalView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_content_row, parent, false);
            return new ItemContentViewHolder(normalView); // view holder for normal items
        }
    }
cs


2번째 인자에는 적당한 값을 넣고(parent를 넣으면 됨) 3번째 인자를 false로 설정하는 것이 핵심입니다. 

3번째 인자를 false로 지정하는 것은 2번째 인자를 사용하지 않겠다는 의미라서 2번째 인자는 중요하지 않은 것 같습니다. 

이렇게 함수를 수정하고나니 무시되었던 android:layout_height="45dp" 속성이 정상적으로 적용됨을 확인했습니다.


작성자

Posted by 드리머즈

관련 글

댓글 영역