ActivityにFragmentをアタッチしてみましょう。
2021.1.1 patch 2
Fragment
前回は 簡単なFragmentを表示 させたので、最初からFragmentが表示されたままです。
Activityの実行中に、Fragmentの追加、削除、置換などのFragmentTransactionを実行することでプログラマブルにFragmentを扱えます。
1. Fragment をActivityに追加
1.1 Activity のレイアウト
1.2 Fragment クラス
1.3 Fragment のレイアウト
1.4 AndroidX Fragment library
1.5 MainActiviy
2. サンプルコード
Fragment をActivityに追加
プログラムでActivityのレイアウトにFragmentを追加するには、レイアウトにフラグメントコンテナとして機能するFragmentContainerViewを前回と同様に含め、FragmentTransactionを使用してFragmentをインスタンス化し、Activityのレイアウトに追加します。
Activity のレイアウト
activity_main.xml にFragmentContainerViewを追加しますが
android:name 属性はいりません
1 2 3 4 5 6 7 8 9 |
<androidx.fragment.app.FragmentContainerView android:id="@+id/fragment" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.5" /> |
Fragment クラス
次にFramentを継承したクラスを作成。例として、SampleFragment とします。
以下のように記述
SampleFragment.kt
1 2 3 4 5 6 7 8 9 10 11 |
class SampleFragment : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { // Inflate the layout for this fragment return inflater.inflate(R.layout.fragment_main, container, false) } } |
Fragment のレイアウト
Fragment用のレイアウトファイル fragment_main.xml を作成
これにTextViewを入れて Hello Fragment の文字列をリソースから呼びます。
fragment_main.xml
1 2 3 4 5 6 7 8 9 10 11 12 |
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <TextView android:text="@string/hello_fragment" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </LinearLayout> |
AndroidX Fragment library
build.gradle にandroidx.fragment:fragment-ktxを追加します。
バージョンは適宜合わせてください
1 2 3 4 5 |
dependencies { ... implementation 'androidx.fragment:fragment-ktx:1.4.1' ... } |
MainActivity
MainActivity.kt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
... import androidx.fragment.app.add import androidx.fragment.app.commit class MainActivity : AppCompatActivity(R.layout.activity_main) { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) if (savedInstanceState == null) { supportFragmentManager.commit { setReorderingAllowed(true) add<SampleFragment>(R.id.fragment) } } } } |
savedInstanceState == null
最初に、BundleのsavedInstanceStateがnull、何もないときだけ設定をするようにします。FragmentはActivityのライフサイクル中に何度でも呼ばれることが可能なので最初だけ設定をするようにします。
setReorderingAllowed:
setReorderingAllowed(true)を使わないとFragmentの遷移、back stack やアニメーションに問題が生じるようです。
You should always use
setReorderingAllowed(true)
when performing aFragmentTransaction
. For more information on reordered transactions, see Fragment transactions.
サンプルコード
プログラマブルな生成についてまとめてみます。
ただこのままだとFragmentの大きさやActivityとの違いが分かりにくいので、サイズや背景色を設定してみます。
activity_main.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="20dp" android:background="#def" tools:context=".MainActivity"> <androidx.fragment.app.FragmentContainerView android:id="@+id/fragment" android:layout_width="match_parent" android:layout_height="300dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.5" /> </androidx.constraintlayout.widget.ConstraintLayout> |
SampleFragment.kt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
//package your.package.name import androidx.fragment.app.Fragment; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; class SampleFragment : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { // Inflate the layout for this fragment return inflater.inflate(R.layout.fragment_main, container, false) } } |
fragment_main.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#bcd" android:orientation="vertical" android:gravity="center" > <TextView android:text="@string/hello_fragment" android:layout_width="wrap_content" android:textSize="40sp" android:textColor="#03f" android:layout_height="wrap_content"/> </LinearLayout> |
リソース
strings.xml
1 2 3 4 |
<resources> <string name="app_name">YourAppName</string> <string name="hello_fragment">Hello Fragment</string> </resources> |
build.gradle
1 2 3 4 5 |
dependencies { ... implementation 'androidx.fragment:fragment-ktx:1.4.1' ... } |
MainActivity.kt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
//package your.package.name import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.add import androidx.fragment.app.commit class MainActivity : AppCompatActivity(R.layout.activity_main) { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) if (savedInstanceState == null) { supportFragmentManager.commit { setReorderingAllowed(true) add<SampleFragment>(R.id.fragment) } } } } |
これで実行させてみるとこのようになります。
全体のMainActivityの画面の中にある、Hello Fragmentの背景が灰色っぽい矩形範囲がFragmentになります。
References:
androidx.fragment.app | Android Developers
フラグメント | Android Developers