Wednesday, August 22, 2012

Android Layout Tricks #1

효율적인 레이아웃 구성에 대한 이야기



다음 글은 아래의 글을 내맘대로 번역한 것임을 밝힙니다.
원본출처: http://android-developers.blogspot.kr/2009/02/android-layout-tricks-1.html

안드로이드 UI 툴킷은 사용하기 편한 몇 개의 레이아웃 매니저를 제공하며, 대부분의 경우에는 이 레이아웃 매니저의 기본적인 특성들만을 이용해서 UI를 개발하게 되지. 하지만, 그런 기본적인 특성을 고집하면 효과적으로 UI를 구성할 수가 없어. 대표적인 예가 LinearLayout을 과도하게 사용하는 것인데, 뷰 계층내에 쓸데 없이 많은 뷰가 존재하게 하지.

모든 뷰는 그만큼의 댓가를 요구해. 초기화를 해야하잖아. 레이아웃을 구성하고 그리고 하는 작업이 꽤나 느려지는 건 당연하지 않겠어?  weight 파라메터를 사용하는 LinearLayout을 몇 개 사용하게 되면 ( 자식 노드(child)들의 크기가 다시 한번 계산되어야 하기 때문에) 더더욱 그렇게 되겠지.

레이아웃과 관련된 아주 간단하면서도 일반적인 예를 들어 설명해볼께. 아래 그림 처럼 만들어볼 건데, 왼쪽에는 아이콘이, 오른쪽 위에는 제목을 아래에는 추가적인 설명을 붙이려고 해


위의 모습처럼 나타나게 하려면 하나의 ImageView와 두 개의 TextView로 레이아웃을 구성해야 한다는 정도는 알지? HierachyViewer로 보면 아래와 같은 모습일거야.



LinearLayout 을 이용한 레이아웃 구성

이 정도의 레이아웃은 LinearLayout을 이용해서 아주 쉽게 구현할 수가 있어. Horzontal LinearLayout 내부에 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 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>


RelativeLayout을 이용해서 구현한 것이나 이전 것이나 동일하지만 다른 점이 하나 있어.
첫 번째나 두번째나 두 개의 TextView을 가지고 있잖아? 만약에 추가 설명이 리스트 아이템에 주어지지 않아서 제목만 출력해야한다면 어떻게 할 수 있을까? 이러한 상황이라면 두 번째 TextView의 Visibiility 속성을 Gone으로 설정해서 해당 항목을 제외시킬 수가 있을거야.

여기서 중요한 건, 이게 LinearLayout에서는 완벽하게 동작하지만 RelativeLayout을 사용하면 그렇지 않다는 거지.




RelativeLayout, alignWithParentIfMissing

RelativeLayout에서는  부모 뷰나 RelativeLayout 자신, 혹은 다른 뷰를 기반으로 해서 정렬이 되잖아? 앞의 예시 코드에만 봐도 추가 설명은 RelativeLayout의 아래(bottom)에, 제목은 추가설명위, 부모 뷰의 윗쪽에 고정되도록 구성했지. 근데 여기서, 추가 설명을 GONE으로 해버리면 RelativeLayout은  제목에 해당하는 TextView의 bottom 부분을 어디에 맞춰야 할지를 모르게 되어 버린다는 거야.

아주 다행스럽게도 이러한 문제는  alignWithParentIfMissing 이라는 아주 특별한 속성을 사용해서 해결할 수가 있어. 이 파라메터 값는 boolean 값으로 지정할 수가 있는데, RelativeLayout에게 '혹시라도 네 모습을 결정할 근거가 되는 객체가 없을 경우엔  네 자신(RelativeLayout)을 기준으로 삼아라'라고 말해주는 거라 생각하면 돼.

예를 들어 설명해볼까? 앞의 예제에서는 제목 TextView를 선언하면서 '아이콘 그림의 오른쪽에, 부모 뷰의 오른쪽 위에, secondLine(추가설명)의 위에' 위치한다고 정의했잖아? 근데 제목의 bottom값으로 정해야할, 아래에 당연히 있어야 할 추가설명 TextView가 없으니, 자기 자신(Relativelayout)의 바닥(bottom)을 제목의 bottom으로 지정해버리는 거지.






이제 우리가 작성한 레이아웃이 아주 잘 동작할거야. 일부 예외 적인 상황에서도 말이야. 게다가 뷰 계층도 아주 심플해졌어. LinearLayout의 weight도 사용하지 않았으니 더 효율적이고 말이야. 두 가지 구현 방법의 차이점은 아래 뷰 계층도를 보면 더 분명해질거야.

다시한번 말하지만,  이 두 구현방법의 차이점은 '(예로) ListView의 리스트 아이템으로 사용할 레이아웃을 구성해야 할 때'와 같은 상황에서라면 아주 중요하게 고려할 부분이라는 거야. 레이아웃을 구성하는 방법을 보여주는 아주 간단한 예제였지만 이것을 통해서 사용자 인터페이스를 효과적으로 구성하는 방법을 배웠길 바라. 끝!


No comments:

Post a Comment