효율적인 레이아웃 구성하는 기법
안드로이드 UI 툴은 사용하기 쉽고 편한 관리툴을 제공합니다.
대부분의 경우에는 관리툴이 제공하는 몇몇 기본적인 것들만 이용하면 UI를 간편하게 구성할 수 있습니다.
하지만 기본적인 것들만 이용해서는 효율적인 사용자 UI를 만들지 못하겠죠.
보기 좋은 예가 LinearLayout의 남용을 들 수 있는데 이렇게 남용하게 되면 View 계층에서 View가 넘쳐나게 되는 결과를 야기합니다.
애플리케이션에서 보여지는 모든 뷰와 레이아웃 관리툴은 초기화라는 비용을 수반합니다.
이런 비용은 레이아웃과 그리기 성능을 저하시키죠. 특히 다중 LinearLayout 에서 weight 속성을 여러번 사용하면
weight 속성의 특성상 자식객체를 두번 측정해야하기 때문에 매우 값비싼 비용을 치르게 됩니다.
여기 아주 단순하고 흔한 레이아웃 예제가 있습니다. 리스트 아이템 왼쪽에 아이콘이 있고, 제목이 있고 제목 밑에 설명이 잇습니다.
어떻게 생겼는지 한 번 보죠.
위의 예제를 분석해 봅시다.
하나의 ImageView 와 두개의 TextView가 각각의 자리를 차지하고 있습니다. HierarchyViewer 를 통해서 캡쳐한 예제의 틀을 한번 살펴봅시다.
LinearLayout을 통하면 이 레이아웃을 단번에 만들수 있습니다.
아이템 자체는 수평 LinearLayout 이고 하나의 ImageView와 두개의 TextView를 포함한 수직 LienarLayout 이 있습니다.
이 레이아웃의 코드를 살펴봅시다.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:padding="6dip">
<ImageView
android:id="@+id/icon"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_marginRight="6dip"
android:src="@drawable/icon" />
<LinearLayout
android:orientation="vertical"
android:layout_width="0dip"
android:layout_weight="1"
android:layout_height="fill_parent">
<TextView
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:gravity="center_vertical"
android:text="My Application" />
<TextView
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:singleLine="true"
android:ellipsize="marquee"
android:text="Simple application that shows how to use RelativeLayout" />
</LinearLayout>
</LinearLayout>
이렇게 만들면 동작은 하지만 ListView의 각각의 아이템을 인스턴스화 한다면 매우 소모적입니다.
같은 레이아웃을 RelativeLayout을 통해서 만들수가 있는데, 이렇게 함으로서 하나의 View를 아낄수 있고 View 계층에서 한단계 더 높습니다.
RelativeLayout을 사용한 코드를 한 번 살펴봅시다.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:padding="6dip">
<ImageView
android:id="@+id/icon"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_alignParentTop="true"
android:layout_alignParentBottom="true"
android:layout_marginRight="6dip"
android:src="@drawable/icon" />
<TextView
android:id="@+id/secondLine"
android:layout_width="fill_parent"
android:layout_height="26dip"
android:layout_toRightOf="@id/icon"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:singleLine="true"
android:ellipsize="marquee"
android:text="Simple application that shows how to use RelativeLayout" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/icon"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_above="@id/secondLine"
android:layout_alignWithParentIfMissing="true"
android:gravity="center_vertical"
android:text="My Application" />
</RelativeLayout>
이 구조로 된 레이아웃은 물론 이전의 레이아웃과 똑같이 동작합니다.
단, 리스트아이템을 두 줄로 하고 싶을 때를 제외합니다. 즉, 제목과 설명이 필요하다면 다른 접근이 필요합니다.
주어진 리스트 아이템에 제목말고 설명이 없다면 애플리케이션은 설명에 해당하는 TextView 의 Visibility(보임옵션)을 GONE(보이지도 않고 자리를 차지하지도 않음)으로 처리해버립니다.
이 방식은 LinearLayout에는 완벽하게 동작하지만 RelativeLayout은 동작하지 않습니다.
RelativeLayout에서는 View가 부모객체를 기준으로 정렬을 합니다. 부모가 RelativeLayout 자신이 될 수도 있고, 다른 View가 될 수도 있습니다.
예를 들어, 개발시에 설명 TextView를 RelativeLayout의 아래를 기준으로 정렬하고 제목은 설명위로 정렬하고 부모객체위에 자리를 잡게 설정했다고 한다면 이 상황에서 설명 TextView의 Visibility를 GONE으로 설정시에는 RelativeLayout은 제목의 하단을 어디를 기준으로 정렬해야 할지 모르는 상황이 발생합니다. 이 문제를 해결하기 위해서 아주 특별한 속성값을 사용할 수 있습니다.
layout_alignWithParentIfMissing 입니다.
Boolean 속성을 지니는 이 값이 하는 일은 지정된 타켓이 사라진다면 그에 맞춰 정렬된 다른 객체의 하단을 고정시키는 역할을 합니다.
예를 들어, View를 Visibility 속성이 GONE인 View 옆에 두고 alignParentIfMissing 속성을 true로 놓으면 RelativeLayout은 View를 왼쪽 가장자리에 고정시킵니다.
위의 예에 적용시키면 alignWithParentIfMisiing 속성은 RelativeLayout을 제목의 아래에 정렬시키게됩니다.
결과화면은 다음과 같습니다.
레이아웃의 출력결과는 완벽합니다. 설명이 GONE 이라도 완벽하게 동작합니다. LinearLayout의 weight 옵션도 쓰지 않기 때문에 더 효율적이고 간단합니다.
HierarchyViewer 에서 두 레이아웃의 View 계층도를 확인해보면 더 확실히 구분할 수 있습니다.
다시 말하지만 인스턴스를 위한 리스트뷰에서 각각의 아이템을 나타내기위한 두 레이아웃의 차이점은 매우 중요합니다.
바라건데 UI를 구성하고 최적화하는 방법을 배우는데에 이런 예제들이 도움이 될 수 있었으면 좋겠습니다.