rakuishi.com

[Android] Fragment をタブで切り替える FragmentTabHost を使う

タブが実装できる TabHost は、Android 3.0 以降は非推奨となり、FragmentTabHost を使う必要があります。TabHost では、Activity を TabHost に追加していましたが、FragmentTabHost では、Fragment を追加して使います。

この記事では、Android Studio で FragmentTabHost を使う方法を紹介します。

v4 support library の導入

Fragment を使うために、v4 support library を導入する必要があります。

メニュー → Tools → Android → SDK Manager から Android Support Repository をインストールします。

Project Structure(command + ;)→ Module → プロジェクト名 → Dependencies → + → Library dependency から、com.android.support:support-v4:+ を追加する。[Apply] → [OK] で自動的に、gradle の sync が始まり、成功したら OK です。

Fragment

Fragment を用意します。Fragment は、ビューとロジックを持ち、それらをひとつのものとして扱えるものです。単なるカスタムビューとは異なり、フラグメント自身もライフサイクルを持ち、さらにアクティビティのライフサイクルと同期しています。

Project 上で、副クリック → New → Android(Other)から Fragment を簡単に追加出来ます。以下に用意した Fragment のレイアウトとロジックは、標準で準備されるものから必要なものだけを残しました。

・fragment_sample.xml

<FrameLayout 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"
  tools:context="com.rakuishi.fragment.fragment.SampleFragment">

  <TextView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:text="Hello World!" />

</FrameLayout>

・SampleFragment.java

package com.rakuishi.fragment.fragment;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class SampleFragment extends Fragment {

  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container,
               Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    return inflater.inflate(R.layout.fragment_sample, container, false);
  }
}

Fragment を扱う Activity

FragmentTabHost に、TabWidget(id/tabs)と FrameLayout(id/tabcontent)が紐付きます。TabWidget と FrameLayout は、id 固定で必須です。FrameLayout(id/container)に Fragment が入ります。

・activity_main.xml

<android.support.v4.app.FragmentTabHost
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@android:id/tabhost"
  android:layout_width="match_parent"
  android:layout_height="match_parent">

  <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TabWidget
      android:id="@android:id/tabs"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:orientation="horizontal"
      android:layout_weight="0" />

      <FrameLayout
        android:id="@android:id/tabcontent"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_weight="0" />

      <FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

    </LinearLayout>

</android.support.v4.app.FragmentTabHost>

FragmentTabHost を setup() し、実際に表示するタブ TabSpec を追加 addTab() していきます。addTab() する際には、TabSpec, Fragment, Fragment に渡す値を指定できます。ここでは特に渡す必要がないので null としています。

・MainActivity.java

package com.rakuishi.fragment.fragment;

import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTabHost;
import android.util.Log;
import android.widget.TabHost;

public class MainActivity extends FragmentActivity implements FragmentTabHost.OnTabChangeListener {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // FragmentTabHost を取得する
    FragmentTabHost tabHost = (FragmentTabHost)findViewById(android.R.id.tabhost);
    tabHost.setup(this, getSupportFragmentManager(), R.id.container);

    TabHost.TabSpec tabSpec1, tabSpec2;

    // TabSpec を生成する
    tabSpec1 = tabHost.newTabSpec("tab1");
    tabSpec1.setIndicator("tab1");
    // TabHost に追加
    tabHost.addTab(tabSpec1, SampleFragment.class, null);

    // TabSpec を生成する
    tabSpec2 = tabHost.newTabSpec("tab2");
    tabSpec2.setIndicator("tab2");
    // TabHost に追加
    tabHost.addTab(tabSpec2, SampleFragment.class, null);

    // リスナー登録
    tabHost.setOnTabChangedListener(this);
  }

  @Override
  public void onTabChanged(String tabId) {
    Log.d("onTabChanged", "tabId: " + tabId);
  }
}