【Android】Fragmentを使う(1) レイアウトに直接配置する

By | 2016年4月21日

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);
    }
}

以上でアプリは完成である。
実行すると以下のようになる。
device-2016-04-21-231706

ところで、配置したFragmentはどのようにViewに置き換わっているのだろうか?
Viewのヒエラルキーを見ると以下のようになっている。
hierarchy
activity_main.xmlで宣言したfragmentの部分が、そのままmy_fragment.xmlの内容に置き換わっているのが分かる。
まずは「FragmentとはViewのまとまりをコンポーネント化する仕組みである」ということをおさえておくと良いと思う。

さて、とは言うものの、実はレイアウトファイルにタグで直接Fragmentを配置する方法は固定的であまり融通が利かないのである。
例えば、画面上のFragmentを動的に入れ替えたり、バックスタックに乗せたり、ということをするにはそのためのコードを書いていく必要がある。
そういった意味では今回紹介した方法ではあまりFragmentにする恩恵を受けているとは言えず、
実際ほとんど使われていないのではないか、という気がする。
しかし、入門編としてはこのくらいの内容が良いだろう。


コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です