10
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Android / Java】 フラグメントでの画面遷移と戻る処理

Last updated at Posted at 2020-09-29

はじめに

Android Studio で Javaを用いたモバイルアプリの開発を学んでいます。
layoutファイルについてはあまり力を入れて記述していません(ざっくりです)。画面切り替えの動作等にフォーカスしているため、stringファイルは使用しませんでした。

学んだ内容

  • FragmentManager FragmentTransaction を用いた表示フラグメントの切り替え(画面遷移)
  • addToBackStack popBackStack を用いたアクションバー戻るボタンクリックで戻る動作

学習のために作成したサンプルアプリの概要

1つのアクティビティにメインとなるフラグメントを用意し、そこからボタンを押すことによって2つのフラグメントに行き来ができるだけの簡単なアプリ。
アクティビティ:1つ
フラグメント:3つ(メイン1つ、サブ2つ)

この①、②ボタンでサブフラグメント1、サブフラグメント2にそれぞれ遷移する

メイン画面(MainFragment)
サブ1画面(SubFragment1)
サブ2画面(SubFragment2)

ディレクトリ構成

各javaファイルの処理内容

  • MainActivity.java

    • MainFragmentの表示
    • SubFragmentのアクションバーに戻るボタン「←」を表示するメソッドを定義
  • MainFragment.java

    • Fragmentの表示を切り替えるメソッドを定義
    • 設置したボタンのクリックリスナとFragmentを切り替えるメソッドの呼び出し
  • SubFragment(1, 2).java

    • アクションバーに戻るボタンの表示
    • 戻るボタンをクリックしたときに戻る処理を記述

ファイルのコードと解説

それぞれ、ファイルのコードを記載

layoutファイル

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>

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

</FrameLayout>

fragment_main.xml
<?xml version="1.0" encoding="utf-8"?>

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

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:textSize="25dp"
        android:text="メインフラグメントだよ"/>

    <Button
        android:id="@+id/bt1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="250dp"
        android:layout_marginLeft="70dp"
        android:textSize="25dp"
        android:text="①"/>

    <Button
        android:id="@+id/bt2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="250dp"
        android:layout_marginLeft="250dp"
        android:textSize="25dp"
        android:text="②"/>

</FrameLayout>

fragment_sub1.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/SubFragment1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".SubFragment1">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:textSize="25dp"
        android:text="サブフラグメント1だよ"/>

</FrameLayout>

fragment_sub2.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/SubFragment2"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".SubFragment2">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:textSize="25dp"
        android:text="サブフラグメント2だよ" />

</FrameLayout>

javaファイル

※package, import 文は記載していません。

MainActivity.java

MainActivity.java

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // メソッドを呼び出し、デフォルトでMainFragmentを表示
        addFragment(new MainFragment());
    }

    // Fragmentを表示させるメソッドを定義(表示したいFragmentを引数として渡す)
    private void addFragment(Fragment fragment) {
        // フラグメントマネージャーの取得
        FragmentManager manager = getSupportFragmentManager();
        // フラグメントトランザクションの開始
        FragmentTransaction transaction = manager.beginTransaction();
        // MainFragmentを追加
        transaction.add(R.id.activityMain, fragment);
        // フラグメントトランザクションのコミット。コミットすることでFragmentの状態が反映される
        transaction.commit();
    }

    // 戻るボタン「←」をアクションバー(上部バー)にセットするメソッドを定義
    public void setupBackButton(boolean enableBackButton) {
        // アクションバーを取得
        ActionBar actionBar = getSupportActionBar();
        // アクションバーに戻るボタン「←」をセット(引数が true: 表示、false: 非表示)
        actionBar.setDisplayHomeAsUpEnabled(enableBackButton);
    }
}

画面表示に指定したフラグメントを表示したいので transaction.add をする

引数はこのような値をいれる

transaction.add(追加先のレイアウト画面部品のR値, 追加する(表示したい)Fragmentオブジェクト);

MainFragment.java

MainFragment.java

public class MainFragment extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        // フラグメントで表示する画面をlayoutファイルからインフレートする
        View view = inflater.inflate(R.layout.fragment_main, container, false);

        // 所属している親アクティビティを取得
        MainActivity activity = (MainActivity) getActivity();
        // アクションバーにタイトルをセット
        activity.setTitle("メインフラグメント");
        // 戻るボタンは非表示にする(MainFragmentでは戻るボタン不要)
        // ここをfalseにしておかないとサブフラグメントから戻ってきた際に戻るボタンが表示されたままになってしまう
        activity.setupBackButton(false);

        // ボタン要素を取得
        Button bt1 = view.findViewById(R.id.bt1);
        Button bt2 = view.findViewById(R.id.bt2);

        // ①ボタンをクリックした時の処理
        bt1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // SubFragment1に遷移させる
                replaceFragment(new SubFragment1());
            }
        });

        // ②ボタンをクリックした時の処理
        bt2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // SubFragment2に遷移させる
                replaceFragment(new SubFragment2());
            }
        });

        return view;
    }

    // 表示させるFragmentを切り替えるメソッドを定義(表示したいFragmentを引数として渡す)
    private void replaceFragment(Fragment fragment) {
        // フラグメントマネージャーの取得
        FragmentManager manager = getFragmentManager(); // アクティビティではgetSupportFragmentManager()?
        // フラグメントトランザクションの開始
        FragmentTransaction transaction = manager.beginTransaction();
        // レイアウトをfragmentに置き換え(追加)
        transaction.replace(R.id.activityMain, fragment);
        // 置き換えのトランザクションをバックスタックに保存する
        transaction.addToBackStack(null);
        // フラグメントトランザクションをコミット
        transaction.commit();
    }
}

すでにメインフラグメントを表示しており、ボタンクリックで表示を切り替えたいので transaction.replace を使用
引数は add の処理と同じイメージ
transaction.replace(表示先のレイアウト画面部品のR値, 置き換える(表示したい)Fragmentオブジェクト);

メインフラグメントから遷移したサブフラグメントではアクションバーの戻るボタン「←」でメインフラグメントに戻れるようにしたいため
transaction.addToBackStack(null);
を記述することにより、遷移前に表示していたフラグメントを保存している。
この記述により遷移先のフラグメントで
getFragmentManager().popBackStack();
を呼び出すことで、戻るボタン「←」をクリックしたときに戻る処理ができるようになる

SubFragment1.java / SubFragment2.java

SubFragment1.java

public class SubFragment1 extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        // フラグメントで表示する画面をlayoutファイルからインフレートする
        View view = inflater.inflate(R.layout.fragment_sub1, container, false);

        // 所属親アクティビティを取得
        MainActivity activity = (MainActivity) getActivity();
        // アクションバーにタイトルをセット
        activity.setTitle("サブフラグメント1");
        // 戻るボタンを表示する
        activity.setupBackButton(true);

        // この記述でフラグメントでアクションバーメニューが使えるようになる
        setHasOptionsMenu(true);

        return view;
    }

    // アクションバーボタンを押した時の処理
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        switch (item.getItemId()) {
            // android.R.id.homeで戻るボタン「←」を押した時の動作を検知
            case android.R.id.home:
                // 遷移前に表示していたFragmentに戻る処理を実行
                getFragmentManager().popBackStack();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }
}

SubFragment2.java

public class SubFragment2 extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        // フラグメントで表示する画面をlayoutファイルからインフレートする
        View view = inflater.inflate(R.layout.fragment_sub2, container, false);

        // 所属親アクティビティを取得
        MainActivity activity = (MainActivity) getActivity();
        // アクションバーにタイトルをセット
        activity.setTitle("サブフラグメント2");
        // 戻るボタンを表示する
        activity.setupBackButton(true);

        // この記述でフラグメントでアクションバーメニューが使えるようになる
        setHasOptionsMenu(true);

        // View viewのが良い?
        return view;
    }

    // アクションバーのボタンを押した時の処理
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        switch (item.getItemId()) {
            // 戻るボタン「←」を押した時android.R.id.homeに値が入る
            case android.R.id.home:
                // 遷移前に表示していたFragmentに戻る処理を実行
                getFragmentManager().popBackStack();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }
}

getFragmentManager().popBackStack();この記述で一つ前のフラグメントに戻る。

最後に

今回は内容に含みませんでしたが、今後フラグメント間のデータの受け渡しについても書けたら良いと思っています。

Java / Android を学び始めて1ヶ月弱程度の初心者です。ご指摘等ありましたらコメントください。

参考にさせていただいた資料

非常にわかりやすく助かりました!ありがとうございました!

10
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?