かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

Xamarin.AndroidでFragment使ってみた

時代はFragmentらしいので、使ってみました。MainActivityはFragmentをホストするためのFrameLayoutを置いてるだけのシンプル構造。

Main.axml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:minWidth="25px"
    android:minHeight="25px">
    <FrameLayout
        android:minWidth="25px"
        android:minHeight="25px"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/Container" />
</LinearLayout>

今回はFragmentを2つ切り替えるようにしてみようと思うので、layoutにFragment1.axmlとFragment2.axmlを作りました。どちらもTextViewを置いただけの必要最低限です。

Fragment1.axml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:minWidth="25px"
    android:minHeight="25px"
    android:padding="10dp">
    <TextView
        android:text="Fragment1"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/textView1" />
</LinearLayout>

Fragment2.axml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:minWidth="25px"
    android:minHeight="25px">
    <TextView
        android:text="Fragment2"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/textView1"
        android:padding="10dp" />
</LinearLayout>

このレイアウトを読み込むFragmentを作ります。今回はViewをレイアウトファイルから読み込むだけのシンプルなやつにしました。必要最低限って大事ですよね。

class Fragment1 : Fragment
{
    public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        return inflater.Inflate(Resource.Layout.Fragment1, container, false);
    }
}

class Fragment2 : Fragment
{
    public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        return inflater.Inflate(Resource.Layout.Fragment2, container, false);
    }
}

最後にMainActivityを作りこんでいきます。MainActivityにメニューを2つ追加します。こいつがタップされたら、それぞれFragment1とFragment2を画面に表示するようにしてみたいと思います。

public override bool OnCreateOptionsMenu(IMenu menu)
{
    menu.Add(0, 0, 0, Resource.String.Menu1Text);
    menu.Add(0, 1, 1, Resource.String.Menu2Text);
    return true;
}

第二引数がIDになります。このIDをもとにOnMenuItemSelectedでswitch文を書きます。

public override bool OnMenuItemSelected(int featureId, IMenuItem item)
{
    switch (item.ItemId)
    {
        case 0:
            var f1 = this.FragmentManager.FindFragmentByTag<Fragment1>(typeof(Fragment1).Name);
            if (f1 == null)
            {
                this.FragmentManager
                    .BeginTransaction()
                    .Replace(Resource.Id.Container, new Fragment1(), typeof(Fragment1).Name)
                    .AddToBackStack(null)
                    .Commit();
            }
            else
            {
                this.FragmentManager
                    .BeginTransaction()
                    .Replace(Resource.Id.Container, f1)
                    .AddToBackStack(null)
                    .Commit();
            }
            break;
        case 1:
            var f2 = this.FragmentManager.FindFragmentByTag<Fragment2>(typeof(Fragment2).Name);
            if (f2 == null)
            {
                this.FragmentManager
                    .BeginTransaction()
                    .Replace(Resource.Id.Container, new Fragment2(), typeof(Fragment2).Name)
                    .AddToBackStack(null)
                    .Commit();
            }
            else
            {
                this.FragmentManager
                    .BeginTransaction()
                    .Replace(Resource.Id.Container, f2)
                    .AddToBackStack(null)
                   .Commit();
            }
            break;
        default:
            throw new Java.Lang.IllegalArgumentException();
    }
    return true;
}

タグ名(ここではクラス名をタグ名にしてます)で検索してなかったら新規に作ったものをFrameLayoutに設定して、みつかったら、みつかったやつをFrameLayoutに設定しています。

実行すると、Menu1を押すとFragment1が表示されてMenu2を押すとFragment2が表示されます。戻るボタンで戻るにも対応しています(AddToBackStackがそれ)。