lightbulb_outline Help shape the future of the Google Play Console, Android Studio, and Firebase. Start survey

フレキシブルな UI のビルド

さまざまな画面サイズに対応したアプリケーションをデザインする場合、異なるレイアウト構成でフラグメントを再利用することで、利用可能な画面の領域に応じて最適な使い心地を実現できます。

たとえば携帯端末の場合、 1 つのユーザー インターフェースに表示するのは 1 つのフラグメントのみが良い場合があります。 一方で、より横幅の広いタブレットでは、フラグメントを横並びに配置してより多くの情報をユーザーに表示できます。

図 1 サイズの異なる画面上の同じアクティビティで、異なる構成で表示される 2 つのフラグメント。 大きな画面では、両方のフラグメントが横並びに配置されていますが、携帯端末では同時に 1 つのフラグメントしか表示できないため、ユーザーの操作に基づいてフラグメントを置き換える必要があります。

FragmentManager クラスでは、アクティビティの実行時にフラグメントを追加、削除、置換して動的な操作感を実現できるメソッドが提供されています。

実行時にフラグメントをアクティビティに追加する

前のレッスンのように <fragment> 要素を使用してレイアウト ファイルのアクティビティにフラグメントを定義するのではなく、アクティビティの実行時にフラグメントを追加できます。 アクティビティが実行されている間にフラグメントを変更する予定がある場合は、この方法を使う必要があります。

フラグメントの追加や削除といったトランザクションを実行するには、FragmentManager を使用して FragmentTransaction を作成する必要があります。ここから、追加、削除、置換する API が提供され、他のフラグメントのトランザクションを実行できます。

アクティビティでフラグメントの削除や置換を許可する場合は、アクティビティの onCreate() メソッド中に最初のフラグメントを追加します。

フラグメントを扱う際の重要なルール(特に実行時にフラグメントを追加する場合)として、アクティビティのレイアウトにフラグメントを挿入できるコンテナ View が含まれていることがあげられます。

次のレイアウトは、前のレッスンで説明した一度に 1 つのフラグメントのみを表示するレイアウトの代替となるレイアウトです。1 つのフラグメントを別のフラグメントに置き換えるため、アクティビティのレイアウトにはフラグメント コンテナとして機能する空の FrameLayout が含まれています。

ファイル名は前のレッスンのレイアウト ファイルと同一ですが、レイアウトのディレクトリには large 修飾子がないため、端末の画面が「large(大)」よりも小さい(両方のフラグメントを同時に表示する領域がない)場合に、このレイアウトが使用されることになります。

res/layout/news_articles.xml:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/fragment_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

アクティビティ内で getSupportFragmentManager() を呼び出し、Support Library API を使用して FragmentManager を取得します。次に、beginTransaction() を呼び出して FragmentTransaction を作成し、add() を呼び出してフラグメントを追加します。

アクティビティのフラグメント複数のトランザクションは、同じ FragmentTransaction を使用して実行できます。変更を加える準備ができたら、commit() を呼び出す必要があります。

以下は、先ほどのレイアウトにフラグメントを追加する方法の一例です。

import android.os.Bundle;
import android.support.v4.app.FragmentActivity;

public class MainActivity extends FragmentActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.news_articles);

        // Check that the activity is using the layout version with
        // the fragment_container FrameLayout
        if (findViewById(R.id.fragment_container) != null) {

            // However, if we're being restored from a previous state,
            // then we don't need to do anything and should return or else
            // we could end up with overlapping fragments.
            if (savedInstanceState != null) {
                return;
            }

            // Create a new Fragment to be placed in the activity layout
            HeadlinesFragment firstFragment = new HeadlinesFragment();

            // In case this activity was started with special instructions from an
            // Intent, pass the Intent's extras to the fragment as arguments
            firstFragment.setArguments(getIntent().getExtras());

            // Add the fragment to the 'fragment_container' FrameLayout
            getSupportFragmentManager().beginTransaction()
                    .add(R.id.fragment_container, firstFragment).commit();
        }
    }
}

<fragment> 要素を使用してアクティビティのレイアウトで定義する代わりに、実行時にフラグメントが FrameLayout コンテナに追加されたため、アクティビティはフラグメントを削除して別のフラグメントに置き換えることができます。

フラグメントを別のフラグメントに置き換える

フラグメントを置き換える手順は、フラグメントを追加する場合と似ていますが、add() メソッドの代わりに replace() メソッドが必要になります。

置換や削除といったフラグメントのトランザクションを行う場合、ユーザーが「元に戻す」などの操作を行えるようにしておくようにしましょう。 フラグメントのトランザクション中にユーザーの「戻る」操作を許可するには、FragmentTransaction をコミットする前に、addToBackStack() を呼び出す必要があります。

注: フラグメントを削除または置換してトランザクションをバック スタックに追加するとき、削除されたフラグメントは停止します(破棄はされません)。 ユーザーが操作を戻してフラグメントを復元すると、再開します。 トランザクションをバック スタックに追加しない場合は、削除または置換時にフラグメントは破棄されます。

フラグメントを別のフラグメントに置き換える場合の例を示します。

// Create fragment and give it an argument specifying the article it should show
ArticleFragment newFragment = new ArticleFragment();
Bundle args = new Bundle();
args.putInt(ArticleFragment.ARG_POSITION, position);
newFragment.setArguments(args);

FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();

// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack so the user can navigate back
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);

// Commit the transaction
transaction.commit();

addToBackStack() メソッドが、トランザクションの一意の名前を指定する任意の文字列パラメーターを取得します。 FragmentManager.BackStackEntry API を使用して高度なフラグメント操作を実行する予定がない場合は、この名前は必要ありません。