【Android-Codelabs】10/36 〜 Fragmentの使い方 〜



2019年にGoogleから，Web上でAndroidを学べるコースが提供されました．([Android Kotlin Fundamentals Course](https://codelabs.developers.google.com/android-kotlin-fundamentals/))
この記事では，そのコースを実際にやってみてアウトプットしてみるといった内容です．
何かツッコミなどあれば編集リクエストかコメントかTwitterでいただければ修正いたします 

#今回学ぶこと
・Fragmentをアプリに追加する方法

#目指す成果物

今回は，このようなクイズアプリを作っていきます．

<img width="619" alt="3-1-1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249786/12dbe608-b0e5-d9f6-2852-6ac3dcb5b615.png">


アプリの仕様
・左のスクリーンショットのタイトル画面で，ゲームを開始します．
・真ん中のスクリーンショットのゲーム画面で，解答を送信します．
・右のスクリーンショットの画面で，navigationドロワーメニューは，アプリの横からスライドすると出てきます．


#ステップ
###1. スタータープロジェクトをダウンロードする

今回は，アプリに必要なテンプレートコードとFragmentクラスをダウンロードした状態から進めます．

1. AndroidTrivia-Starter Android Studioプロジェクトをダウンロードします．
2. Android Studioでプロジェクトを開き，アプリを実行します．アプリを開くと，アプリ名と空白の画面を表示する以外は何もしません．

![3-1-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249786/309b516d-ef68-cadc-cb5c-29bd83793035.png)


###2. Fragmentを追加する

Fragmentは，アクティビティの動作やUIの一部のことをいいます．
一つのアクティビティで，複数のFragmentを組み合わせてmulti-pane UIを構築し，複数のアクティビティでFragmentを再利用できます．

Fragmentは，`サブアクティビティ`のようなものです．

・Fragmentには，独自のライフサイクルがあり，独自の入力イベントを受け取る
・Fragmentは，アクティビティの実行中に追加や削除ができる
・Fragmentは，Kotlinクラスで定義される
・FragmentのUIは，XMLレイアウトファイルで定義される

今回のアプリには，MainActivityといつくかのFragmentがあります．
ここのステップでは，Fragmentを作成し，そのFragmentをアプリのMainActivityに追加していきます．

まず，空の`TitileFragment`クラスを作成します．
`[File]`>`[New]`>`[Fragment]`>[Fragment(blank)]

Nameを，`TitleFragment`にして，チェックアウトをすべて外しFragmentを作成します．

`TitleFragment.kt`を開くと，`onCreateView()`メソッドが含まれていて，これはFragmentのライフサイクル中に呼び出されるメソッドの一つです．

```
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                         savedInstanceState: Bundle?): View? {
}
```

次にバインディングオブジェクトを作成します．
Fragmentは現在コンパイルされません．Fragmentをコンパイルするには，バインディングオブジェクトを作成し，Fragmentのビューをinflateさせる必要があります．

まず，`onCreateView()`メソッド内で，変数`binding`を作成します．
そしてFragmentのビューをinflateさせるには，`DataBindingUtil.inflate()`メソッドを呼び出します．

```
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
   val binding = DataBindingUtil.inflate<FragmentTitleBinding>(inflater, R.layout.fragment_title,container,false)
   return binding.root
}
```

ここでメソッドには，４つのパラメーターを渡します．
・inflater：　バインディングレイアウトをinflateさせるため　
・R.layout.fragment_title：　展開するレイアウトのXMLレイアウトリソースを指定
・container：　親のViewGroupのために指定
・false：　attachToParentのために指定

変数`binding`に，`DataBindingUtil.inflate()`を割り当てます．

戻り値は`binding.root`を返します．

###3. Fragmentをメインレイアウトファイルに追加する．

ここでは，Fragmentの`TitleFragment.kt`を，レイアウトファイルの`activity_main.xml`に追加します．

LinearLayout要素内に，`fragment`要素を追加し，idを指定します．

Fragmentのnameを，Fragmentクラスのフルパスに設定します．
（ここでは`com.example.android.navigation.TitleFragment`とします．）

そしてレイアウトファイル`activity_main.xml`はこのようになります．

```activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">
            <fragment
                android:id="@+id/titleFragment"
                android:name="com.example.android.navigation.TitleFragment"
                android:layout_width="match_parent"
                android:layout_height="match_parent"/>
        </LinearLayout>
</layout>
```

アプリを実行して，Fragmentがメイン画面に追加せれたことを確認してください．

![3-1-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249786/19e4c294-abf8-0989-5dc1-4e7cb6e85738.png)



#まとめ
・Fragmentには独自のライフサイクルがあり，独自の入力イベントを受け取る
・Fragmentのレイアウトを定義するには，XMLレイアウトで<faragment>タグを使う
・Fragmentは，アクティビティの実行中に追加や削除ができる
・inflateは，onCreateView()内で，Fragmentのレイアウトを拡張します


#クイズ
>1問目
FragmentとActivityの違いはなんですか？　正しいものをすべて選んでください

・Fragmentを作成するとき，`onCreateView()`メソッドのレイアウトをinflateします．Activityを作成するとき`onCreateView`メソッドでレイアウトをinflateします．
・Activiyには独自のレイアウトがありますが，Fragmentには独自のレイアウトを設定できません.
・Activityには独自のライフサイクルがありますが，Fragmentにはありません．
・FragmentまたはActivityのいずれかのレイアウトをinflateする場合，レイアウトをとして`R.layout.layoutname`を参照する．

>2問目
Fragmentに関する次の記述のうち，正しいものをすべて選んでください

・Fragmentを複数のActivityで使用できる
・複数のFragmentを一つのActivityに含めることができる
・FragmentをKotlinクラスで定義すると，自動的にFragmentは`activity_main.xml`のレイアウトファイルに追加される
・Fragmentを挿入する場所は，<fragment>タグを使って定義する

###クイズの正解

1問目    

・Fragmentを作成するとき，`onCreateView()`メソッドのレイアウトをinflateします．Activityを作成するとき`onCreateView`メソッドでレイアウトをinflateします．
・Activityには独自のライフサイクルがありますが，Fragmentにはありません．
・FragmentまたはActivityのいずれかのレイアウトをinflateする場合，レイアウトをとして`R.layout.layoutname`を参照する．

2問目    

・Fragmentを複数のActivityで使用できる
・複数のFragmentを一つのActivityに含めることができる
・Fragmentを挿入する場所は，<fragment>タグを使って定義する

#ソースコード
Github:
https://github.com/syuheifujita/android-codeLab-fundamental-3-1

#言葉の定義
・Fragment
アクティビティの動作やUIの一部のことをいいます．

#参考資料
###CodeLabs by Google
https://codelabs.developers.google.com/android-kotlin-fundamentals/
![スクリーンショット 2020-02-05 4.07.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249786/3ad2d3c9-d57f-1b4b-85cf-1c92a57b464b.png)


#おわりに：他にもっとわかりやすい方法あれば教えてください

僕は「Codelabs」をやることでFragmentの使い方をまとめてみました．

もしかすると，情報が古かったり間違っていたり，他にもっとわかりやすい方法があるのかもしれません．


皆さんの中で上手にFragmentの使い方をまとめている方がいれば，ぜひ教えてください！
Twitterやコメントなどでお待ちしています．
質問でもお気軽に！