<include> でレイアウトを再利用する

Compose の方法を試す
Jetpack Compose は、Android に推奨される UI ツールキットです。Compose でレイアウトを扱う方法について説明します。

Android ではさまざまなウィジェットが用意されており、小型で再利用できるインタラクティブな要素を提供していますが、特別なレイアウトが必要な大規模コンポーネントの再利用が必要となる場合もあります。レイアウト一式を効率的に再利用するには、<include> タグと <merge> タグを使用して、1 つのレイアウトを別のレイアウト内に埋め込みます。

これにより、複雑なレイアウト(「はい」または「いいえ」のボタンパネル、説明テキスト付きのカスタム進行状況バーなど)を作成できます。つまり、複数のレイアウトに共通するアプリの要素を抽出して個別に管理し、各レイアウトに含めることができます。カスタムの View を記述して個々の UI コンポーネントを作成することもできますが、レイアウト ファイルを再利用すると簡単に作成できます。

再利用可能なレイアウトを作成する

まず、新しい XML ファイルを作成し、再利用できるレイアウトを定義します。次の例は、各アクティビティに含まれるタイトルバーを定義するレイアウト(titlebar.xml)です。

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/titlebar_bg"
    tools:showIn="@layout/activity_main" >

    <ImageView android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               android:src="@drawable/gafricalogo" />
</FrameLayout>

ルート View は、このレイアウトを追加する各レイアウトでの表示方法を示します。

<include> タグを使用する

再利用可能なコンポーネントを追加するレイアウト内に、<include> タグを追加します。たとえば、上記の例のタイトルバーを含むレイアウトを次に示します。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/app_bg"
    android:gravity="center_horizontal">

    <include layout="@layout/titlebar"/>

    <TextView android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:text="@string/hello"
              android:padding="10dp" />
    ...
</LinearLayout>

また、レイアウトのルートビューのレイアウト パラメータ(android:layout_* 属性)はすべてオーバーライドできます。そのためには、<include> タグ内でパラメータを指定します。これを次の例に示します。

<include android:id="@+id/news_title"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         layout="@layout/title"/>

ただし、<include> タグを使用してレイアウト属性をオーバーライドする場合は、android:layout_heightandroid:layout_width もオーバーライドして、他のレイアウト属性を有効にする必要があります。

<merge> タグを使用する

<merge> タグを使用すると、1 つのレイアウトを別のレイアウトに含める際に、ビュー階層内の冗長なビューグループを削除できます。<merge> のユースケースの 1 つは、ViewGroup を拡張してカスタムビューを実装する場合です。

たとえば、メイン レイアウトが垂直の LinearLayout で、2 つの連続したビューを複数のレイアウトで再利用できる場合、2 つのビューを配置する再利用可能なレイアウトには独自のルートビューが必要です。しかし、再利用可能なレイアウトのルートとして別の LinearLayout を使用すると、縦長の LinearLayout 内に縦長の LinearLayout が配置されます。LinearLayout のネスト化は、UI パフォーマンスの低下を招くだけです。

代わりに、LinearLayout を拡張してカスタムビューを作成し、レイアウト XML を使用してその子ビューを記述します。次の例に示すように、XML の最上位タグは LinearLayout ではなく <merge> です。

<merge xmlns:android="http://schemas.android.com/apk/res/android">

    <Button
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/add"/>

    <Button
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/delete"/>

</merge>

このレイアウトを別のレイアウトに含めると(<include> タグを使用)、<merge> 要素は無視され、<include> タグの代わりに 2 つのボタンがレイアウト内に直接配置されます。

<include> の詳細については、レイアウト リソースをご覧ください。