Fragmentを効果的に使うことで、画面構成が柔軟になり、UI部分のコードの再利用がしやすくなる。
しかし、使い方を理解するには少し複雑である。
そこで、Fragmentの使い方について、小さなところから順に見ていくことにする。
今回紹介するのは「Fragmentをレイアウトにタグで直接配置する方法」である。
まずはAndroidStudioで新しいプロジェクトを作る。
プロジェクトのテンプレートは、「Empty Activity」とする。
プロジェクトが作成されたら、以下の手順で進めていく。
1.FragmentのためのUIレイアウトを作る
まずは、FragmentのためのUIレイアウトを作る。
my_fragment.xmlという名前でres/layout下に保存し、内容は適当に以下のようにした。
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#ea6c6c"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="This is my fragment!" android:id="@+id/textView" android:layout_alignParentTop="true" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="New Button" android:id="@+id/button" android:layout_below="@+id/textView" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" /> </RelativeLayout>
テキストとボタンを配置しただけの単純なレイアウトである。
配置された場所を分かりやすくするため、全体の背景色を赤系にしてある。
2.Fragmentを継承したクラスを作る
次は、Fragmentのためのソースを作成する。
ソースコードは以下のようになる。
import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; public class MyFragment extends Fragment { @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { // 引数で渡ってきたinflaterを使ってレイアウトをinfrateする final View layout = inflater.inflate(R.layout.my_fragment, container); // 必要に応じてUIにコールバックを設定する layout.findViewById(R.id.button).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(getContext(), "Hello Fragment!!", Toast.LENGTH_SHORT).show(); } }); // infrateされたViewをそのまま返す return layout; } }
注意が必要なのは、android.app.Fragmentではなく、android.support.v4.app.Fragmentをインポートしているところである。(3行目)
これは、サポートライブラリに含まれるFragmentである。
あえてこちらのパッケージを使う理由は、Androidのバージョンが低い端末向けにアプリを配信する場合でも、最新の機能が反映されたFragmentを使えるからである。
apkのサイズが大きくなってしまうのとトレードオフだが、特に理由が無ければサポートライブラリ版を使ったほうが良いと思う。
さて、実装については今回は必要最低限とするため、onCreateView()のオーバーライドのみとした。
引数で渡ってくるinfratorを使ってレイアウトをinfrateしてやり、必要に応じてUIにコールバックをセットした後、infrateされたViewを返すだけである。
以上がFragmentの作成である。
3.メインのレイアウトにFragmentを配置する
Activityが読み込むためのレイアウトファイルに、fragmentタグを使って直接配置する。
ソースは以下のようになる。
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.zawapro.fragmentlesson.MainActivity"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" android:id="@+id/textView2" /> <fragment android:layout_width="wrap_content" android:layout_height="wrap_content" android:name="com.zawapro.fragmentlesson.MyFragment" android:id="@+id/fragment" android:layout_below="@+id/textView2" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:layout_alignParentEnd="true" /> </RelativeLayout>
ハイライトした18行目がFragmentを配置している個所である。
このように、普通のViewを配置する方法と何ら変わりは無いことが分かる。
4.Activityのコード
Activityのコードは以下のようになる。今回はAndroidStudioが自動生成したものに手を加えていない。
サポートライブラリを使うため、AppCompatActivity となっている点に気を付けておけば良いだろう。
import android.support.v7.app.AppCompatActivity; import android.os.Bundle; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } }
ところで、配置したFragmentはどのようにViewに置き換わっているのだろうか?
Viewのヒエラルキーを見ると以下のようになっている。
activity_main.xmlで宣言したfragmentの部分が、そのままmy_fragment.xmlの内容に置き換わっているのが分かる。
まずは「FragmentとはViewのまとまりをコンポーネント化する仕組みである」ということをおさえておくと良いと思う。
さて、とは言うものの、実はレイアウトファイルにタグで直接Fragmentを配置する方法は固定的であまり融通が利かないのである。
例えば、画面上のFragmentを動的に入れ替えたり、バックスタックに乗せたり、ということをするにはそのためのコードを書いていく必要がある。
そういった意味では今回紹介した方法ではあまりFragmentにする恩恵を受けているとは言えず、
実際ほとんど使われていないのではないか、という気がする。
しかし、入門編としてはこのくらいの内容が良いだろう。