티스토리 뷰

반응형


이번 시간에는 복잡한 xml을 좀 더 보기좋고 효율적으로 바꿀수 있는 xml tag(include, merge)에 대해 알아보겠습니다.



<include> tag 사용

먼저 <include> 태그를 사용하면 레이아웃을 여러 파일로 나눌 수 있습니다. 복잡하거나 아주 긴 GUI를 구현하는데 도움이 됩니다.

reuse_item1.xml, reuse_item2.xml 파일을 사용하여 복잡한 레이아웃을 구성한다고 가정하고, 해당 activity의 xml(이름은 main_activity로 하였습니다.)을 작성해 봤습니다.

main_activity.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/main_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <!-- First include file -->
    <include layout="@layout/reuse_item1" />

    <!-- Second include file -->
    <include layout="@layout/reuse_item2" />

</LinearLayout>

이제 activity의 xml을 작성했으니 reuse_item1.xmlreuse_item2.xml 도 작성해보겠습니다.

reuse_item1.xml
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/textView1"
    android:text="First include"
    android:textAppearance="?android:attr/textAppearanceMedium"/>

reuse_item2.xml
<?xml version="1.0" encoding="utf-8"?>
<Button xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/button1"
    android:text="Button" />

각 xml들은 위와 같이 뷰그룹 없이 위젯으로만 작성하였습니다.

참고로 xmlns:android="http://schemas.android.com/apk/res/android 안드로이드 네임 스페이스를 선언해야합니다.

그럼 main_activity.xml 의 최종 렌더링 된 모습을 살펴 보겠습니다.

main_activity.xml 렌더링된 모습
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/main_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <!-- First include file -->
    <TextView
        android:id="@+id/textView1"
        android:text="First include"
        android:textAppearance="?android:attr/textAppearanceMedium"/>

    <!-- Second include file -->
    <Button
        android:id="@+id/button1"
        android:text="Button" />
</LinearLayout>

이렇게 <include>를 통해 구현한 xml은 여러분이 구현한 자바 코드에서 findViewById(R.id.textView1)를 통해 해당 위젯을 잘 받아올 수 있습니다.

이제 좀 더 복잡한 xml에 대해서도 같은 작업을 진행해 보겠습니다. 기존에는 reuse 된 xml들이 TextView 하나만 가지고 있었는데 이제 두 개 이상의 위젯을 넣어보도록 하겠습니다. 우선 해당 xml에 존재하는 위젯들을 ViewGroup으로 감싸줘야 합니다. 위젯이 두개 이상이라 꼭 감싸줘야됩니다.
저는 LinearLayout으로 감싸보겠습니다.

아래와 같이 reuse_item1.xml을 수정하였습니다.

reuse_item1.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/reuse_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/textView1"
        android:text="Second include"
        android:textAppearance="?android:attr/textAppearanceMedium"/>

    <TextView
        android:id="@+id/textView2"
        android:text="More text"
        android:textAppearance="?android:attr/textAppearanceMedium"/>

</LinearLayout>

reuse_item2.xml, main_activity.xml은 그대로 사용한다는 가정하에 바꿘 reuse_item1.xml로 인해 main_activity.xml은 다음과 같이 렌더링됩니다.

reuse_item1.xml 수정 이후 main_activity.xml의 렌더링 된 모습
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/main_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <!-- First include file -->
    <LinearLayout
        android:id="@+id/reuse_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >

       <TextView
            android:id="@+id/textView1"
            android:text="Second include"
            android:textAppearance="?android:attr/textAppearanceMedium"/>

       <TextView
            android:id="@+id/textView2"
            android:text="More text"
            android:textAppearance="?android:attr/textAppearanceMedium"/>

   </LinearLayout>

     <!-- Second include file -->
   <Button
        android:id="@+id/button1"
        android:text="Button" />

</LinearLayout>

 <!-- First include file --> 주석 밑으로 변경한 reuse_item1.xml의 요소들이 잘 들어갔습니다.
이렇게 손쉽게 <include> 를 사용하여 복잡한(?) 레이아웃을 보기 쉽게 나눠보았습니다.

그런데 위 main_activity.xml은 한가지 문제점을 가지고 있습니다.

바로 <include>로 인해 불필요하게 LinearLayout의 중복이 발생하였습니다.

Layout을 분리해서 좀 더 깔끔하게 구현해 보려고 한건데, 이로 인해 부작용이 발생하였습니다.
이 문제를 어떻게 해야될까요? reuse_item1.xmlinclude 하지 말고 main_activity.xml 파일에 직접 채워 넣을까요?

아닙니다. 눈치 채셨겠지만 저희는 <merge> tag를 이용하여 이 문제를 좀 더 스마트하게 해결할 수 있습니다.


<merge> tag 사용

<merge> 는 이러한 종류의 중복 문제를 처리하는 최상위 요소를 제공하는 더미 태그입니다.

우리는 문제의 그 reuse_item1.xml을 다음과 같이 고칠 수 있습니다.

<merge>를 적용한 include1.xml
<merge xmlns:android="http://schemas.android.com/apk/res/android">

    <TextView
        android:id="@+id/textView1"
        android:text="Second include"
        android:textAppearance="?android:attr/textAppearanceMedium"/>

    <TextView
        android:id="@+id/textView2"
        android:text="More text"
        android:textAppearance="?android:attr/textAppearanceMedium"/>

</merge>

그럼 이제 main_activity.xml 이 어떻게 렌더링 되나 살펴보겠습니다.

새롭게 렌더링 된 main_activity.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/main_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <!-- First include file -->
    <TextView
        android:id="@+id/textView1"
        android:text="Second include"
        android:textAppearance="?android:attr/textAppearanceMedium"/>

    <TextView
        android:id="@+id/textView2"
        android:text="More text"
        android:textAppearance="?android:attr/textAppearanceMedium"/>

    <!-- Second include file -->
    <Button
        android:id="@+id/button1"
        android:text="Button" />

</LinearLayout>

<merge> 를 통해 우리가 고민하던 문제가 사라졌습니다.

그런데!!!
우리는 <include>의 문제를 수정하면서 <merge>의 새로운 문제에 당면할 수 있습니다.

사실 위와 같은 구조의 xml에서는 <merge>로 인해 다른 문제가 발생하지 않습니다.
main_activity.xml을 조금 수정해서 <merge>의 단점을 들춰보겠습니다.

<merge>의 단점을 확인할 수 있는 main_activity.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/main_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <!-- First include file -->
    <include
        android:id="@+id/reuse_layout1"
        layout="@layout/reuse_item1" />
    <!-- Second include file -->
    <include
        android:id="@+id/reuse_layout2"
        layout="@layout/reuse_item1" />
</LinearLayout>

수정한 main_activity.xml에서는 동일한 reuse_item1.xml을 두 번 include 하였고, 각 includeid를 지정하였습니다.
이전 예제에서는 id를 지정하지 않았지만, 우리는 <include> 를 사용할 때 id를 지정할 수 있습니다. <include> 에 설정된 id나 다른 attribute들은 includelayout의 최상단 layout에 설정되게 됩니다. 그래서 이 id를 통해 나중에 findViewById()를 통해 원하는 위젯이나 ViewGroup을 가져올 때 사용할 수 있는 것이죠.

하지만 <merge>reuse_item1.xml에서 사용하면서 include 될 reuse_tiem1.xml의 root layout이 사라지게 되었습니다. 따라서 <include> 에서 지정한 id는 모두 사라지게 됩니다.

id가 사라졌기 때문에 우리는 reuse_item1.xml의 내부 위젯에 접근할 방법이 사라졌습니다. <merge> 의 단점이라고 할만하죠?

따라서 <merge>를 쓴 xml은 한 곳에서 두 번 <include>하지 않아야합니다.

이렇게 <include>, <merge> 에 대해 알아봤습니다. 혹시 잘못된 점이나 궁금한 점 있으면 댓글로 남겨주세요.
감사합니다.


반응형
댓글
공지사항
최근에 올라온 글