안드로이드 UI 툴킷은 사용하기 쉬운 몇개의 레이아웃 관리자를 제공하여, 레이아웃 관리자의 기본적인 기능만으로도 사용자 인터페이스를 구현할수 있도록 해준다.
불행하게도 기본 기능을 고집하는 것은 사용자 인터페이스 작성시 매우 효과적인 방법은 아니다. 대표적인 사례가 view 계층구에서 뷰의 확산을 야기시키는 LinearLayout 의 남용이다. 추가 하는 모든 view (더 심한 경우 모든 layout 관리자)는 비용적인 측면에서 초기화, 레이아웃, 그리기(drawing)가 느려져 어플리케이션에 부담을 준다. 몇개의 LinearLayout을 중첩하고 그 LinearLayout의 child가 두번 측정되어 지도록 weight 파라미터를 사용할 경우 레이아웃 과정은 특히 고비용이 된다.
아주 간단하고 일반적인 예인, 왼쪽에 아이콘, 윗쪽에 제목, 제목밑에 옵션으로 설명이 있는 리스트 아이템을 보자.
이 view들을 명확히 이해하기 위해 하나의 ImageView 와 두개의 TextView 로 구성되어 있고 HierarcyViewer 를 통해 캡쳐한 레이아웃의 와이어 프레임은 아래와 같다.
LinearLayout으로 이 레이아웃은 간단히 구현된다. 아이템 자체는 ImageView와 수직 LinearLayout을 갖는 수평 LinearLayout 이고 수직 LienarLayout은 두개의 Textview를 갖는다. 이 레이아웃의 소스 코드는 아래와 같다.
<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 계층 구조에서 리스트 아이템당 한 레벨이 사라지는 것이다. 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>
새로운 구현은 한 사례만 제외하고 이전의 구현과 완벽하게 동일하게 동작한다. 디스플레이 하고자 하는 리스트 아이템은 2줄의 텍스트를 가지고 있다. (제목과 설명, 설명은 옵션) 주어진 리스트 아이템에서 설명 부분이 가용하지 않을 경우 어플리케이션은 두번째 TextView를 눈에 보이지 않게 처리하는데 이는 LinearLayout구현에서는 완벽하게 동작하지만 RelativeLayout 버전에서는 그렇지 않다.
RelativeLayout에서 view들은 부모, RelativeLayout 자체, 다른 뷰와 함께 배치된다. 예를 들어 설명 부분이 RelativeLayout의 바닥에 배치되고 제목이 설명 부분 위에 배치되고 부모의 위에 연결되도록 선언하였다. 설명 부분이 사라지게 되면 RelativeLayout은 제목의 바닥위치가 어디인지 알수 없게 된다. 이 문제를 해결하기 위해layout_alignWithParentifMissing 이라 불리는 매우 특별한 레이아웃 파라미터를 사용할 수 있다.
이 boolean 파라미터는 RelativeLayout의 타겟이 사라졌을 경우 그 기준으로 자기자신의 위치를 사용할 수 있도록 한다. 예를 들어 사라진 view의 오른쪽에 view를 위치시키고 alighWithParentIfMissing을 true로 설정하면 alighWithParentIfMissing은 RelativeLayout이 자신의 바닥에 제목의 바닥을 배치할수 있도록 해줄 것이다. 우리의 경우, alighWithParentIfMissing의 사용은 RelativeLayout 자신의 바닥에 제목의 바닥을 배치할수 하도록 할 것이다. 결과는 아래와 같다.
이 레이아웃의 설명 부분이 사라지더라도 완벽하게 동작한다. 더 좋아진 것은 계층 구조가 단순화 되었고 LinearLayout의 weights를 사용하지 않았기 때문에 좀더 효율적이다. 두 구현의 차이점은 HierarchyViewer에서 view 계층 구조를 비교해보면 명확해 진다.
다시한번, 이 차이점은 ListView에 있는 모든 아이템을 인스턴스화 할때 매우 중요하다. 이 단순한 에제는 개발하고자하는 레이아웃을 이해하는 것이 UI를 최적화 할수 있는 최고의 방법이라는 것을 말해준다.