【Androidアプリ】Fragment間の遷移(切り替え)

# はじめに

こんにちは、エンジニアのkeitaMaxです。

今回は前回作成したFragmentをもう一つ作成して、Fragment間の遷移(切り替え)をやろうと思います。

前回の記事

https://qiita.com/keitaMax/items/720f92d9b51e642b079c


# 実装方法

MainActivityにフラグメントを切り替える関数を作成し、それを各フラグメントから呼んで、画面遷移(切り替え)をおこなようと思います。

# Fragment作成

Fragmentをもう一つ作成しました。名前を`ExampleTwoFragment`としました。

```kotlin:ExampleTwoFragment

class ExampleTwoFragment : Fragment() {

    private var _binding: FragmentExampleTwoBinding? = null
    private val binding get() = _binding!!

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _binding = FragmentExampleTwoBinding.inflate(inflater, container, false)
        return binding.root
    }
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

    }
    override fun onResume() {
        super.onResume()
    }

    override fun onPause() {
        super.onPause()
    }

    override fun onDestroy() {
        super.onDestroy()
    }

```
```xml:fragment_example_two
<?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:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/black"
    tools:context=".ExampleTwoFragment">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:textColor="@color/white"
        android:text="フラグメント2" />

</FrameLayout>
```
# Fragmentの置き換え処理の作成

MainActivityに`replaceFragment`という関数を用意しました。

```kotlin:MainActivity
class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        if (savedInstanceState == null) {
            supportFragmentManager.commit {
                setReorderingAllowed(true)
                add(binding.fragmentContainerView.id, ExampleFragment())
            }
        }
    }
    public fun replaceFragment(fragment: Fragment) {
        supportFragmentManager.commit {
            setReorderingAllowed(true)
            replace(binding.fragmentContainerView.id,fragment)
        }
    }
}
```

replaceFragmentの引数に次に表示したいフラグメントをいれて呼び出すように作成しました。

# Fragment側の修正

`ExampleFragment`からボタンが押された時に`replaceFragment`を呼び出すような処理を書いていきます。

```kotlin:ExampleFragment
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        activity = context as? MainActivity
        binding.button.setOnClickListener{
            activity?.replaceFragment(ExampleTwoFragment())
        }
    }
```
`onViewCreated`を上のように修正しました。

# 実際に遷移するか試す

実際に起動して確かめてみます。

初期画面は以下になります。

<img width="200px" alt="スクリーンショット 2024-07-23 16.31.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3715123/c3ade01d-11b9-dc99-f4b9-295721750882.png">

ここから、下の`フラグメント２へ`とかかれているボタンを押します。

<img width="200px" alt="スクリーンショット 2024-07-23 16.31.13.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3715123/e9ca16e2-3cbe-0376-3b82-7897d5b9bb5b.png">

すると上のように遷移することができました。

# おまけ　バックボタンについて

このままだと、フラグメント２の状態でバックボタンを押すとアプリが終了してしまいます。

これをバックボタンを押した時に一つ目の画面に戻れるようにするには、以下のように`addToBackStack`を追加する必要があります。

```kotlin:MainActivity
    public fun replaceFragment(fragment: Fragment) {
        supportFragmentManager.commit {
            setReorderingAllowed(true)
            replace(binding.fragmentContainerView.id, fragment)
            addToBackStack("name") // 追加
        }
    }
```

これをすると、ボックボタンを押したら一つ前に表示されていたフラグメントの画面を表示することができます。

# おわりに

この記事での質問や、間違っている、もっといい方法があるといったご意見などありましたらご指摘していただけると幸いです。

最後まで読んでいただきありがとうございました！

# 参考

https://developer.android.com/guide/fragments/fragmentmanager?hl=ja


# 次の記事