IT_Programming/Android_Java

Android Layout Tricks: Efficiency

JJun ™ 2014. 6. 17. 23:52

 


 출처: http://huewu.blog.me/110083521070


Layout Tricks: Creating Efficient Layouts


Layout Tricks 시리즈 두 번째 글입니다. 첫 번째 글 보다는 조금 더 도움이 되는 듯 하네요~ 역시 대세는 RelativeLayout 인 듯 합니다. 

  안드로이드 UI 툴킷은 몇 가지 Layout 매니저(LinearLayout / RelativeLayout 등의 ViewGroup)를 제공한다. Layout 매니저들은 쉽게 사용할 수 있으며, 많은 경우 기본적인 기능만을 이용해서 원하는 사용자 인터페이스를 구현할 수 있다. 

 하지만 불행하게도, 기본적인 구성요소만을 사용하는 것이 사용자 인터페이스를 작성하는데 가장 효율적인 방법은 아니다. 예를 들어, 개발자가 LinearLayout 을 남용해서 사용할 경우, 전체 UI를 구성하는 View의 계층구조가 복잡해지고, 사용되는 View 의 숫자가 크게 증가될 수 있다. 화면을 구성하는데 사용된 모든 View 와 Layout 매니저들을 처리하는데는 비용이 든다. 특히 LinearLayout 의 weight 파라매터를 사용하는 경우, Layout 화면을 구성하기 위해,  두 번의 Measure Pass 를 거쳐야 하기 때문에 더욱 많은 비용이 소모된다.

 여기 매우 단순하고 일반적인 예가 하나 있다. 아래의 그림과 같이 하나의 리스트 아이템을 표현하기 위한 Layout 을 생각해 보자. 왼쪽에는 아이콘 이미지가 있고, 상단에는 타이틀 텍스트가 그 아래는 부가적인 설명이 포함된 Layout 이다. 

 


 HierarchyViewer 로 캡처한 Layout 와이어 프레임을 살펴보면, 하나의 ImageView 와 두 개의 TextView 가 어떻게 구성되어 있는지 보다 명확하게 확인 할 수 있다. 


 LinearLayout 을 이용하 이러한 화면을 구성하는 것은 어렵지 않다. 전체 Layout 은 Horizontal LinearLayout (orientation 속성값이 Horizontal ) 이며, 하나의 ImageView 와 Vertical LinearLayout 을 포함하고 있다. 또한 Vertical LinearLayout 은 두 개의 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" />
           
   
</LinearLayout>

</LinearLayout>

 이 Layout 은 정상적으로 작동하지만, 낭비 요소를 담고 있다. 개발자는 하나의 RelativeLayout 이용해서 동일한 형태의 UI를 구성할 수도 있다. 그럼으로 화면을 구성하는데 사용되는 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" />

   
<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>

  새로운 구현 방식은 이전에 LinearLayout을 이용한 구현한 것과 거의 동일하게 작동하지만, 한가지 주의해야할 점이 있다. 위의 Layout 중에, 만일 특정 리스트 아이템에 대해서, 부가적인 설명을 나타내는 TextView 가 사용될 필요가 없는 경우 이전 LinearLayout 을 이용해서 구성한 경우, 해당 TextView 의 Visibility 속성을 Gone 으로 설정하면 손쉽게 부가 설명 항목을 제외 시킬 수 있다. 하지만 그러한 방식은, RelativeLayout 을 사용하는 경우 정상적으로 작동하지 않을 수도 있다.

 RelativeLayout 에서 View 들은 특정 부모 View (RelativeLayout 자체나 아니면 해당 Layout이 참조하고 있는 View) 를 기반으로 정렬되어 진다. 예를 들어, 위 예제의 경우, 부가적인 설명을 표시하는 TextView 는 RelativeLayout 의 바닦면에 정렬되며, 타이틀을 표시하는 TextView 는 그 View 위에 위치하도록 선언되어 있다. 이 때, 부가적인 설명을 표시하는 TextView 가 Gone 이 될 경우, RelativeLayout 은 타이틀을 표시하는 View 를 어디에 위치시켜야 할지 알 수 없게 된다. 이러한 문제를 해결하기 위해, 개발자는 layout_alignWithParentIfMissing 파라매터를 사용할 수 있다. 

 이 Boolean 인자는 만일 특정한 View 가 기준으로 삼아야되는 부모 View 가 없을 경우, 해당 View 를 포함하고 있는 RelativeLayout 자체를 기준으로 삼으라고 알려준다.  예제의 경우, aliginWithParentIfMissing 를 설정함으로서, 만일 타이틀을 표시하는 TextView 가 기준으로 삼고 있는 TextView 가 없을 경우 (Gone 에 의해...), 해당 View 대신 RelativeLayout 을 기준으로 삼게 되고, 그 결과 TextView 는 아래와 같이 RelativeLayout 의 바닦면 바로 위에 위치하게 된다.

 이로서 RelativeLayout 을 이용해 구성한 두 번째 UI도 완벽하게 작동한다. 무엇보다도, 계층구조는 더 단순해 졌고, LinearLayout 의 weight 파라메터를 사용하지 않았기 때문에 더 효율적이다. 두 가지 구현 방식의 차이점은 HierarchyViewer 를 이용해 살펴 보면 확실하게 들어난다.

 다시한번 말하지만, 이러한 차이는 ListView 를 구성하는 개발 아이템 아이템 마다, 동일한 형식의 Layout 을 사용하게 되면 훨씬 더 중요해 질 수 있다.  개발자들이 이번 글에서 예로든 간단한 예제를 통해, 여러가지 레이아웃에 대해 잘 아는 것이, UI 를 최적화하는데 최선의 길임을 알 수 있기를 희망한다.