Uing? Uing!!

[안드로이드 팁] include 태그: 반복되는 레이아웃을 재사용하자! 본문

Android

[안드로이드 팁] include 태그: 반복되는 레이아웃을 재사용하자!

Uing!! 2021. 10. 27. 03:48
반응형

반복되는 레이아웃

하나의 앱에는 자주 재사용되는 레이아웃이 있는 경우가 많다.

예를 들면, 거의 비슷하게 툴바가 앱 전역에 걸쳐 사용되고 있을 수 있다.

 

같은 툴바가 FirstActivity와 SecondActivity에 사용되는 경우를 살펴보자.

각 액티비티의 레이아웃은 이런 식으로 생성될 것이다.

<!-- First Activity -->
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    
    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/black">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:text="Title Text"
            android:textColor="@color/white"/>
    </FrameLayout> <!-- 툴바 -->

    <TextView
        android:id="@+id/edit_text_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center"
        android:text="FirstActivity"/>
</LinearLayout>
<!-- Second Activity -->
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    
    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/black">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:text="Title Text"
            android:textColor="@color/white"/>
    </FrameLayout> <!-- 툴바 -->

    <TextView
        android:id="@+id/edit_text_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center"
        android:text="SecondActivity"/>
</LinearLayout>

이 예시에서는 화면이 Frist Activity와 Second Activity 두 개밖에 없지만, 같은 타이틀 바가 100여개의 화면에 적용되어야 한다면 어떨까.

모든 화면마다 툴바에 해당하는 이 부분이 추가되어야 할 것이다.

<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/black">
    <TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:text="Title Text"
    android:textColor="@color/white"/>
</FrameLayout> <!-- 툴바 -->

이렇듯 반복되는 레이아웃을 재활용할 수 있도록 만들어진 것이 include 태그이다.

 

<include/> 태그

include 태그는 한 번 작성한 레이아웃의 일부를 여기저기에서 가져다 쓸 수 있도록 해 준다.

위의 툴바 사례를 include를 활용하여 개선해 보자. 두 단계면 충분하다.

 

1) 반복적으로 사용될 레이아웃(이 경우에는 툴바 부분)을 별도 레이아웃 파일로 추출한다.

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/black">
    <TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:text="Title Text"
    android:textColor="@color/white"/>
</FrameLayout>

2) 원하는 다른 레이아웃에 include 태그로 해당 레이아웃을 추가한다.

<!-- Second Activity -->
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    
    <include layout="@layout/layout_title"/> <!-- 툴바 -->

    <TextView
        android:id="@+id/edit_text_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center"
        android:text="FirstActivity"/>
</LinearLayout>
<!-- Second Activity -->
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    
    <include layout="@layout/layout_title"/> <!-- 툴바 -->

    <TextView
        android:id="@+id/edit_text_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center"
        android:text="SecondActivity"/>
</LinearLayout>

 

이렇게 하면 FirstActivity와 SecondActivity 레이아웃이 훨씬 간결해질 뿐 아니라,

layout_title의 일부가 변경되면 이 레이아웃이 include된 모든 레이아웃에서 변경사항이 반영된다는 장점도 있다.

 

데이터바인딩으로 include 응용하기

데이터바인딩을 활용하는 경우에는 이 include 태그를 훨씬 다채롭게 활용할 수 있다.

특히 레이아웃이 거의 반복적으로 사용되지만, 모든 부분이 완벽하게 똑같지는 않은 경우에 유용하게 적용할 수 있다.

 

위의 툴바 예시에서 'Title View'에 해당하는 부분이 두 액티비티에서 'First Activity', 'Second Activity'로 분기되어야 한다고 하자.

관련된 모든 레이아웃에 데이터바인딩이 적용되어 있다면 아래와 같이 TextView 내부 text에 들어갈 값을 지정할 수 있다.

 

아래는 이 사례를 데이터바인딩으로 작성한 예시이다.

(글 길이를 줄이기 위해 SecondActivity는 생략하고 FirstAcitvity의 레이아웃만 첨부했다.)

 

1) 먼저 include할 레이아웃(layout_title.xml)에서 변경 가능한 부분에 대한 변수(variable)를 지정한다.

<?xml version="1.0" encoding="utf-8"?>
<layout>
    <data>
        <variable
            name="titleText"
            type="String" /> <!-- 변경 가능한 변수 -->
    </data>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/black">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:text="@{titleText == null ? `Default Title Text` : titleText}"
            android:textColor="@color/white"/> <!-- 여기에서 변수가 활용되고 있음 -->
    </FrameLayout>
</layout>

2) include하는 레이아웃(activity_first.xml)에서 include 태그 내부로 해당 변수를 전달한다.

<?xml version="1.0" encoding="utf-8"?>
<layout>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <include layout="@layout/layout_title"
            app:titleText="@{`First Activity Title`}"/> <!-- 변수 활용 -->

        <TextView
            android:id="@+id/edit_text_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center"
            android:text="First Activity"/>
    </LinearLayout>
</layout>

이 때, include 태그 내부에 전달받을 값(이 경우 titleText)는 데이터바인딩으로만 전달할 수 있다.

즉, app:titleText="First Activity Title"처럼은 사용할 수 없고, app:titleText="@{`First Activity Title`}"와 같이 전달해야 한다.

 

만일 include하는 액티비티에서도 데이터바인딩으로 변수를 전달한다면 이렇게 작성할 수 있다.

<?xml version="1.0" encoding="utf-8"?>
<layout>
    <data>
        <variable
            name="titleText"
            type="String" /> <!-- 변수 활용 -->
    </data>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <include layout="@layout/layout_title"
            app:titleText="@{`First Activity Title`}"/> <!-- 변수 활용 -->

        <TextView
            android:id="@+id/edit_text_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center"
            android:text="First Activity"/>
    </LinearLayout>
</layout>

결과물은 이렇다. 상단 까만 타이틀의 제목이 서로 다르게 잘 적용되었음을 볼 수 있다.

 

반응형
Comments