<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> の詳細については、レイアウト リソースをご覧ください。