AndroidStudioの標準デザインパターンで分かるFragment入門

#はじめに(この記事はもう内容が古いので注意してくださいね)
Androidアプリの制作において、押さえておけばもしかしたら幸せになれるポイントがFragmentだと思います。
２年ぶりにAndroidネィティブに関わってAndroidStudioを使い初めて２ヶ月ですが、標準のジェネレーターでつくれる標準のデザインパターンからFragmentの使い方に慣れるためのチュートリアルを作ってみました。


以下、いいわけ

 - 基本的に画面はFragment単位で設計するように癖をつけるとデザインの変更に強く、他のアプリを作るときにも使い回しがしやすい実装になりやすいです。
 - Android Studioが自動作成するデザインモデルのテンプレートもFragmentで構成されている場合が多いので、Fragmentに慣れているだけでかなり心理的に楽になれます。
 - Androidの入門書の入り口くらいは見たけどFragmentで挫折しそうな時と振り返りのために。
 - 私も２年くらい前に一度挫折しそうになりましたので、理解のポイントをまとめたい。

フラグメントの詳しい設計概念などはGoogleのドキュメントを確認すればよいのでここでは実際の利用にあたっての簡単に割り切った概念を説明し、自動生成のコードを改造していきながら、要点を順に説明します。

より詳しい概要が知りたい方は各種ドキュメントを参照してください。

何を調べればいいか分からないという状態から、ドキュメントから何を調べたらやりたい事が実現できるかが何となく出てくればいいと思う。

#Activityとフラグメント

ActivityはAndroidアプリのUIを構成する基本的な単位で、これを読みにきた方はご存知とは思いますが、よく分からない場合は、画面そのものだと、とりあえず思っていただいて大丈夫です。

 - 最初は深く考えないのが大事です。
 - 考えだすと挫折します。
 - パソコンでいうところの窓(windows)。
 - 陸軍でいうところの師団や旅団あたりの独立した戦闘群。
 - 海軍でいうところの航空母艦のような存在です(超適当)
 - FragmentやViewを保有・管理します。

FragmentはActivity上で運用されるものの独立した機能をもつのでFragment自身もViewを装備・使用できますが、UI画面としてのライフサイクルの根本をコントロールするのはActivityです。

 - 師団でいうところの連隊や大隊
 - 航空母艦でいうところの艦載機のような存在
 - Viewはミサイルや無誘導爆弾のようなイメージ
 - とまずは割り切りらないと挫折します。
 
またFragmentはViewを所有しないこと可能で、Activityのライフサイクルに準じた処理を、Activityの実装から切り離して容易に設計する器としても使えます。
センサーの処理やActivity内で横断的に利用されるデーターのライフサイクル管理を内包させることで柔軟性の高いモジュールを作成することができそうですが、ここではそういう事も可能だということを覚えておいて、いつか困った時は思い出してください。

ActivityとFragmentの使い方の正確な認識ついてはQiitaにも、いくつか優秀な記事があります。
[今さら聞けない Activity と Fragment の使い分け](http://qiita.com/KeithYokoma/items/c41b22bda8c8d924d8cd)などは参考になりましたありがとうございます。

##Activityの特徴
大雑把にいって

- アプリケーションのライフサイクルの管理
- FragmentとViewの搭載と管理

##Fragmentの特徴
割り切って

- 自分と自分が保有するViewのActivityに準じたライフサイクル管理
- FragmentとViewの搭載と管理

なおフラグメントは他のフラグメントを載せることができます。

ものすごく大雑把に考えて、FragmentとActivityの違いは独立したアプリケーションのUIとしてのライフサイクルを管轄するかしないかの差です。
FragmentはActivityの管轄下で自分自信のライフサイクルを持ち断片的な機能を提供します。名前のとおりの部品ということです。

次にFragmentを活用した簡単なアプリケーションを想定したワイヤーフレームを示します。

##Fragmentを活用したアプリケーションの模式図

![Untitled.png](https://qiita-image-store.s3.amazonaws.com/0/43688/bfe0a9a5-a64a-21fa-dcfc-2e77cfffe5af.png)
*こんなイメージで使いたい!*

#Example1
簡単にFragmentを活用したアプリというものの概念を説明したところで実践に入ります。
模式図と同じアプリケーションをとも思いましたが、画像を何枚も用意したり等、若干フラグメントとから脱線する話がどうしても出てきますので、ここではAndroidStudioが自動で生成してくれるテンプレートを見ながら、画像を表示する。テキストだけを表示するなど簡単な機能をもった独自のFragmentを３つ表示するように改造していきます。

##プロジェクトの作成
標準のモデルテンプレートから、`NavigationDrawer`を選んで新しいプロジェクトを作ります。

![スクリーンショット 2014-07-10 11.12.33.png](https://qiita-image-store.s3.amazonaws.com/0/43688/62fa954e-96f9-78c2-c536-3effb308dd89.png)


標準テンプレートから生成したNavigationDrawerにはダイアログで命名したメインの画面となるActivityとNavigationDrawerFragmentが生成されています。

ここでは**MainActivity**と名付けておきました。

**MainActivity**の実装を確認しましょう。
まずはlayout_xmlを開いてみると`NavigationDrawerFragment`を搭載していることが確認できます。

この記述でfragmentをViewにxmlから載せておくことができます。

```xml
<fragment android:id="@+id/navigation_drawer"
    android:layout_width="@dimen/navigation_drawer_width"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    android:name="jp.sample.app.fragmentsample.NavigationDrawerFragment"
    tools:layout="@layout/fragment_navigation_drawer" />
```

勘のいい方は、このMainActivityのlayoutXML上の中に宣言のある空の`FrameLayout`はなんだよと思われると思いますが、この後、Activityの実装をみると登場いたします。

この自動生成されたNavigationDrawerFragmentが左から出てくるメニューを構成するViewをまとめて管理してくれるので、我々は中身を作っていきます。

アクティビティの実装も確認しましょう。
**MainActivity.java**を開いてください。
`onNavigationDrawerItemSelected`というメソッドがonCreateのすぐ下あたりにあるハズです。このメソッドはNavigationDrawerでメニューをタップした時に呼ばれる通知を受け取るインタフェースの実装です。

```java
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
               .replace(R.id.container, PlaceholderFragment.newInstance(position + 1))
               .commit();
```

中身をみるとFragmentManagerを取得してbeginTransactionして、`PlaceholderFragment`をnewInstanceして、activity_manレイアウトのcontainerというViewGroupと入れ替えています。
ここで先ほど出てきた謎の`@+id/container`とIDが指定された`FrameLayout`が出てきました。
beginTransactionすると、`FragmentTransaction`というクラスのインスタンスが返却され、Fragmentに対して一度に行いたい操作をまとめて命令することができます。

初期の実装だと３つあるメニューがすべて`PlaceholderFragment`のインスタンスをのせていることが分かります。

今回はここを改造して別々な３つのフラグメントを自炊します。

##独自Fragmentクラスの作成
独自のフラグメントを３つ用意します。

とりあえず簡単に。

 - 画像を一枚表示する`PictureFragment`、
 - テキストを表示する`TextFragment`、
 - シンプルなリストを表示する`ListFragment`

以上３つの簡単なViewを構成するフラグメントを作ってみましょう。


##画像を表示するフラグメントクラスの生成

![スクリーンショット 2014-07-14 12.51.50.png](https://qiita-image-store.s3.amazonaws.com/0/43688/5ca687eb-39db-d815-4ed6-4f4885c1d45c.png)

javaソースのパッケージフォルダ下で右クリックし、画像のように選択すると、Fragmentを作成するダイアログが表示されます。

![スクリーンショット 2014-07-17 17.44.44.png](https://qiita-image-store.s3.amazonaws.com/0/43688/945d7cd3-d156-4f15-3245-bf524215c549.png)

`ImageFragment`と命名し`Include interface callback?`は不要なのでチェックボックスを外してください。

`Include Fragment factory methods`は今回のようにActivityから値を渡す必要がないFragmentの場合は不要なのですが、Fragmentは自動的に破棄されたり、初期化されたりする可能性があるためコンストラクタでの値渡しが基本的には非推奨ですから、factorymethodを使うくせを付けておきましょう。
また何もしないにしてもコンストラクタの宣言は必須です。コード生成アシスタントを使う分には大丈夫ですが、自分でフルスクラッチする場合などは注意してください。

フラグメントにもActivity同様ライフサイクルがありますがここでは習うより慣れろでいきたいと思いますので詳細ついてはGoogleのドキュメント等を確認してください。

[ライフサイクルについてはこことかを参考に](http://www.techdoctranslator.com/android/guide/activities/fragments#Lifecycle)

###fragment_image.xmlを編集する
自動でLayoutXMLも生成されていると思いますので、編集しましょう。
このあたりは普通にActivityに設定するのと同じ感覚で大丈夫です。

```fragment_image.xml
<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"
    tools:context="jp.sample.app.samplefragment.ImageFragment">

    <!-- TODO: Update blank fragment layout -->
    <ImageView
        android:id="@+id/image_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerInside"
        android:layout_centerInParent="true"
         />

</RelativeLayout>
```

###ImageFragment.javaを編集する
自動で生成されたコードには不要なパラメタをBundleに渡すコードが付いているの削除します。
せっかくなのでImageViewに指定する画像ファイルのリソースIDをBundleから取得してみましょう。
以下のメンバ変数を削除します。

```java
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
(中略)
private String mParam1;
private String mParam2;
```
以下のメンバ変数を追加します。

```java
private static final String ARG_PARAM_RESOURCE_ID = "resource_id";
private int mResourceId;
```

`newInstanceメソッド`を改造しましょう
余計なパラメタのputStringをとって、ARG_PARAM_RESOURCE_IDのputIntを記述します。
こちらのファクトリーメソッドで値をBundleに設定し、onCreateで取得します。

```java
public static ImageFragment newInstance(int resourceId) {
    ImageFragment fragment = new ImageFragment();
    Bundle args = new Bundle();
    args.putInt(ARG_PARAM_RESOURCE_ID, resourceId);
    fragment.setArguments(args);
    return fragment;
    }
```

続いて onCreateでのBundleからのパラメタ取得部分を修正します。

```java
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (getArguments() != null) {
        mResourceId = getArguments().getInt(ARG_PARAM_RESOURCE_ID);
    }
}
```

onCreateViewでimageViewにリソースを設定します。
onCreateViewではLayoutInflaterが渡されてきますので自分が提供するViewを返却します。

```java
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View rootView = inflater.inflate(R.layout.fragment_image, container, false);

    ImageView imageView = (ImageView)rootView.findViewById(R.id.image_view);
    imageView.setImageResource(mResourceId);

    return rootView;
}
```

###MainActivityをImageFragmentを使用するように編集する
MainActivityを編集してNavigationDrawerItemSelectedのpositionが0の場合は`PlaceholderFragment`ではなく`ImageFragment`を使用するように改造します。
画像ファイルは適当なフリー素材等を活用してください。

onNavigationDrawerItemSelectedを編集してください。

```java
public void onNavigationDrawerItemSelected(int position) {
    // update the main content by replacing fragments
    FragmentManager fragmentManager = getSupportFragmentManager();
    if(position == 0){
        fragmentManager.beginTransaction()
                .replace(R.id.container, ImageFragment.newInstance(R.drawable.hanabatake))
                .commit();
    }
    else {
        fragmentManager.beginTransaction()
                .replace(R.id.container, PlaceholderFragment.newInstance(position + 1))
                .commit();
    }

}
```

ここまで実装したら一度アプリを機動させてください。
この写真のようにSection1を選択した場合は写真が表示されると思います。
![device-2014-07-17-193436.png](https://qiita-image-store.s3.amazonaws.com/0/43688/b7c6b2a3-0d79-c208-5cd5-ca0c852ce4df.png)

ですが、他のSectionに切り替えるとActionBarのタイトルがNavigationDrawerのメニューから切り替えても変わらないことに気がつくと思います。

![device-2014-07-17-194145.png](https://qiita-image-store.s3.amazonaws.com/0/43688/fe69ba44-7ca3-73f6-24cc-b873a3b4d4c6.png) ![device-2014-07-17-194200.png](https://qiita-image-store.s3.amazonaws.com/0/43688/d9e856e9-f8e2-7a0e-dfd6-3dde837be3ac.png)
*タイトルが変わらない!*

###ImageFragmentでもタイトル文字列が変わるようにする

`PlaceholderFragment`の実装をみると`onAttachメソッド`で何事かしているのが分かると思います。
ActivityにAttachされると呼び出され、activityのインスタンスが渡されています。ここでMainActivityの`onSectionAttached`にnewInstanceで渡された`sectionNumber`を渡しています。
`onSectionAttached`ではmTitleというメンバ変数にセクションNOごとにタイトル文字列を渡しています。
このmTitleは、すぐ下の`restoreActionBar`メソッドでActionBarクラスのインスタンスにsetTitleしているのがわかります。

このインタフェースをImageFragmentにも実装しましょう。

それではImageFragmentのnewInstanceからのパラメタを追加しonAttachメソッドを追加しましょう。


```java
//追加
private static final String ARG_SECTION_NUMBER = "section_number";

//変更
public static ImageFragment newInstance(int sectionNumber, int resourceId) {
    ImageFragment fragment = new ImageFragment();
    Bundle args = new Bundle();
    args.putInt(ARG_SECTION_NUMBER, sectionNumber);
    args.putInt(ARG_PARAM_RESOURCE_ID, resourceId);
    fragment.setArguments(args);
    return fragment;
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (getArguments() != null) {
        mResourceId = getArguments().getInt(ARG_PARAM_RESOURCE_ID);
    }
}

//追加
@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    ((MainActivity) activity).onSectionAttached(getArguments().getInt(ARG_SECTION_NUMBER));
}
```

MainActivityでImageFragmentのnewInstanceの引数に`position + 1`をたします。

```java
fragmentManager.beginTransaction()
        .replace(R.id.container, ImageFragment.newInstance(position + 1, R.drawable.hanabatake))
        .commit();
```
ここまでで実行するときちんと最初から**Section1**というタイトルが表示され、画面を切り替えても**Section1**が表示されると思います。

ここまでのImageFragmentとMainActivityのソースをGistに載せました。
[こちら](https://gist.github.com/hoshi7/4bd0cab3d7aacc3ce211)を参照ください。

##テキストを表示するフラグメントの作成
ImageFragmentと同じ要領でTextFragmentも作成してみてください。
ここではTextFragmentという名前にしたと想定します。
生成した状態でTextViewが入っているのでやることはMainActivityでのonNavigationDrawerItemSelectedにTextFragmentを生成する分岐を増やし、TextFragmentでonAtachを追加するだけです。

一応こちらもGistにソースを載せてみました。
[こちら](https://gist.github.com/hoshi7/d89239842c7dda38a740)です。

##リストを表示するフラグメントの作成

リスト自体はここでの本質でないのとListFragmentの自動生成コードが参考になるのでパッとつくりましょう。
Fragmentを作成する際のコンテクストメニューの(Blank)の下に(List)があります。

それを選択しダイアログを以下のようにすれば自動でDummyContentを表示するListFragmentが生成されます。
ここはItemFragmentとします。

![スクリーンショット 2014-07-17 20.29.52.png](https://qiita-image-store.s3.amazonaws.com/0/43688/6202bd97-781c-dc48-441b-49efee4ab045.png)

これまでと同じようにItemFramentとMenuActivityを編集しますが、ItemFragmentは生成された時点で`OnFragmentInteractionListener`というinterfaceが作られていて、Activityでこのinterfaceを実装しないと実装クラスとしてonAtachのときにActivityのインスタンスをキャストしているため例外で落ちてしまいます。

この実装はInterfaceを利用したActivityとFragmentの連携のお手本になります。面倒でinterface書かずに固有のActivityのインスタンスからメンバ関数を呼ぶような実装をしがちですが、結合度を下げるためには見習いたいです。

MainActivityに`OnFragmentInteractionListener`を実装します。

implementsに追加

```java
public class MainActivity extends ActionBarActivity
        implements NavigationDrawerFragment.NavigationDrawerCallbacks
                   ,ItemFragment.OnFragmentInteractionListener{
```

onFragmentInteractionメソッドを実装

```java
@Override
public void onFragmentInteraction(String id) {

}
```
選択されたものにより何らかのActionをActivity側にやらせたい場合はここに実装を足せばよいわけですが、ここでは何のActionも不要ですので空のままにします。

OnNavigationDrawerItemSelectedの変更。
これで`PlaceholderFragment`が不要になりました。

```java
    public void onNavigationDrawerItemSelected(int position) {
        // update the main content by replacing fragments
        FragmentManager fragmentManager = getSupportFragmentManager();
        if(position == 0){
            fragmentManager.beginTransaction()
                    .replace(R.id.container, ImageFragment.newInstance(position + 1, R.drawable.hanabatake))
                    .commit();
        }
        else if(position == 1){
            fragmentManager.beginTransaction()
                    .replace(R.id.container, TextFragment.newInstance(position + 1))
                    .commit();
        }
        else if(position == 2){
            fragmentManager.beginTransaction()
                    .replace(R.id.container, ItemFragment.newInstance(position + 1))
                    .commit();
        }

    }
```

ついでなのでActivityのクラス内クラスになっているPlaceholderFragmentを削除しておいても構いませんが。結局あとで復活させるのでそのままにしておいても構いません。

ItemFragmentはここまでと同じように必要なものを追加し余計なものを削除してください。

こちらもGistを載せておきます。
これで３つのフラグメントが完成したはずですので４クラスをまとめて載せました。

[こちら](https://gist.github.com/hoshi7/7aac7baa4238be697c84)を参照ください。

実行すると３つのFragmentが無事表示されるアプリが完成しているはずです!

#Fragmentが便利なところ
Fragmentは大雑把にいってFragment毎に独立したUIを提供するモジュールとして使いやすいので便利だと最初に書きましたが、ここまでで作ったアプリをつかって実感していきます。

#Example2 メニューの順番入れ替え
「ごめん順番かえたんだけどさー」
「えーまじ面倒っすよ」
という会話とか。

FragmentであればFragmentTransactionでreplaceする場所やタイミングを変えればすぐに変更することができます。

いま作ったアプリの順番を逆にしたいのであれば`onNavigationDrawerItemSelected`の0と2を交換しreplaceするタイミングを変更するだけでよいです。

```java
if(position == 2){
    fragmentManager.beginTransaction()
            .replace(R.id.container, ImageFragment.newInstance(position + 1, R.drawable.hanabatake))
            .commit();
}
else if(position == 1){
    fragmentManager.beginTransaction()
            .replace(R.id.container, TextFragment.newInstance(position + 1))
            .commit();
}
else if(position == 0){
    fragmentManager.beginTransaction()
            .replace(R.id.container, ItemFragment.newInstance(position + 1))
            .commit();
}
```
*position == 2と1を入れ替えるだけで逆になる*

ものすごく結合度が低いと思いませんか？
簡単ですFragmentをどこで出すかだけ考えればいいので楽です。

もしスクロールビューで縦にならんでいるようなUIだったとしても、
３のreplaceようのダミーを用意してそれぞれview_0、view_1、view_2と命名し、
Fragmentを番号に応じてreplaceする仕様であれば、番号を入れ替えるだけでスクロールで出てくる部品の順番を入れ替えることができそうです。

#Example3 複数のUIからの利用

もう少しメリットがはっきりと分かりやすい感じにします。
新しい別なUIのActivityを作り両方にチェンジできるようにします。

すでに長いので細かい説明は省きますが、
Actionbar+TabのUIをもったActivityを作りこれまでに作成したUIをそちらのActivityにも載せ、メニューの選択で切り替えることができるアプリを作ります。

##TabActivityを作る
TabbedActivityから追加します。
![スクリーンショット 2014-07-18 12.06.40.png](https://qiita-image-store.s3.amazonaws.com/0/43688/06beb318-fcc5-5723-b211-ed8c648ef02e.png)

ここではTabActivityとしてActionBarTabs(With ViewPager)を選択してください。
![スクリーンショット 2014-07-18 12.07.21.png](https://qiita-image-store.s3.amazonaws.com/0/43688/8b6ecb4f-6ca4-3e23-9ec2-59ed29c96ed0.png)

とりあえずTabActivityを起動する手段を作ります。
MainActivityにもTabActivityにもActivionBarの右側にオプションメニューを開くボタンがあり、settingsという何も起きないメニューがあります。
今回はここを押したらActivityが切り替わるように実装してみます。

両方のActivityともにonOptionsItemSelectedを以下のように編集してください。

```java
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            Intent intentChengeUi = new Intent();
            intentChengeUi.setClassName(this.getPackageName(), this.getPackageName() + ".MainActivity");

            startActivity(intentChengeUi);
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
```

これでアプリを起動し、ActionBarの右側にある`・・・`が縦になったようなボタンからオプションメニューを開き、settingsを押すと相互にAcitivityが切り替わると思います。

まだこの状態ではTabActivity側はなにも表示されませんのでTabActivityのタブの選択に合わせてFragmentを挿入する処理を実装します。

##TabActivityに独自Fragmentを実装

TabActivityのViewPagerはFragmentPagerAdapterで作られていてSectionPagerAdapterというFragmentPagerAdapterを継承した実装がActivityの内部クラスとして存在しています。
そこを確認するとgetItemでpositionをもらい、NavigationDrawerの方でも出てきたPlaceholderFragmentが登場します。

###これまでのクラスの修正

大変お手数で、心苦しいのですが、今からMainActivityのほうもPlaceholderFragmentを復活させます。
申し訳ないでも大丈夫です。

Gistにソースコードを用意しました。
コピペしていただいて構いません。

今度はPlaceholderFragmentから３つのFragmentを生成して、FragmentにFragmentを搭載できるという点の例にもなります。

fatment_main.xmlとfragment_text.xmlも変更します。
こちらもgistに用意しておきます。
また３つの自作FragmentもOnAtattchでのタイトルの設定とSectionの保有が不要になりますので同じように修正してください。こちらも・・・おなじくです。

[デザインを切り替えるバージョンのGistはこちら](https://gist.github.com/hoshi7/009cac5bf448f71c86f5)

このあとTabの方も３つのFragmentを表示する形にしますので同じようにTabActivityとfragment_tabのレイアウトのソースも載せておきました。

###修正の要点解説
どう変わったかですが各フラグメントはこれまでに足したSectionNumberのパラメタに関する取り扱いとonAtachでのタイトルの設定をコールしていた箇所を全てとりました！
これでActivityとはItemFragmentのリストを選択したときの通知インタフェースの実装意外、結合せずに結合度合いがますます下がりました。

MainActivityは`onNavigationDrawerItemSelected`を最初の時点にもどし`PlaceholderFragment`を使用するように戻しました。

`PlaceholderFragment`を見てください。
ここでは`onCreateView`の時に３つの自作クラスをreplaceする実装がここに移り、PlaceholderFragmentのView内部にFragmentを置いています。置換の対象は`fragment_main.xml`内のTextViewに置換用のダミーのレイアウトを置きました。

ここで**add**じゃダメなのか？という疑問がでますね。**add**じゃダメです。**add**の場合、fragmentが**add**される前に**remove**が呼び出されないため、重ね合わせになっていってしまいます。
[おなじみのyanzmさんのブログに各メソッドの挙動が詳しく解説されていますのでご一読をオススメします。](http://y-anz-m.blogspot.jp/2012/03/androidfragmenttransaction_14.html)

##TabActivity側の修正

３つのフラグメントを表示させますが、ちょっと実装がNavigationDrawerとは変わります。
NavigationDrawerの場合、PlaceholderFragmentの場合、fragmentのレイアウトは常に１つしか画面上にありませんでしたが、今回はViewPagerですので両隣のItemが生成されviewのIDが重複してしまいます。
これだとreplaceにしろaddにしろ現在存在するPlaceholderFragmentが内包するTagFragmentの最初に定義されたcontinerにしているダミーviewの位置が操作されてしまいます。

そこでView.generateViewIdで動的にIDを取得したいのですがAndroid4.2からの対応になっています。
ここではSupportV4ライブラリを使用したサンプルですので、それではまずいので、こちらの記事のUtilクラスをプロジェクトに追加して下位互換のgenerateViewIdを使ってください。

[ここのクラスを追加](http://qiita.com/Hoshi_7/items/f29bfbd719b0bee8de48)

```TabActivity.java
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    int position = getArguments().getInt(ARG_SECTION_NUMBER);

    RelativeLayout rootView = (RelativeLayout)inflater.inflate(R.layout.fragment_tab, container, false);
    FrameLayout layout = (FrameLayout)rootView.getChildAt(0);

    layout.setId(ViewUtil.generateViewId());

    FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
    if(position == 1){
        fragmentManager.beginTransaction()
                .replace(layout.getId(),ImageFragment.newInstance(R.drawable.hanabatake))
                .commit();
    }
    else if(position == 2){
        fragmentManager.beginTransaction()
                .replace(layout.getId(), TextFragment.newInstance())
                .commit();
    }
    else if(position == 3){
        fragmentManager.beginTransaction()
                .replace(layout.getId(), ItemFragment.newInstance())
                .commit();
    }
    return rootView;
}
```

せっかくなのでこちらは順番を戻しました。

`ItemFragment.OnFragmentInteractionListener`インタフェースの実装もわすれないでください！こちらはMainActivityの時と同じです。

さて起動してみると両方のUIで正常に３つのFragmentが動作していると思います。

![device-2014-07-18-165616.png](https://qiita-image-store.s3.amazonaws.com/0/43688/39a593ad-31ab-986f-af13-6fc9a93d21a9.png)

最初の実装からさらに結合度が弱いActivityの断片となり、PlaceholderFragmentに仲介させることで、UIの違いによる実装差分を吸収しActivityが実現したいの方向性が違っても、同じFragmentが内部で分岐をせずに機能を提供しています。

ActivityとFragmentの関係をものすごくいい加減に図におこすと下のような違いになります。

![Untitled (2).png](https://qiita-image-store.s3.amazonaws.com/0/43688/1b7a40a5-45c9-cda5-1800-9b92226bff6d.png)

最初の実装のままであればonAtatchで今のUIがNavigationDrawerでタイトルを設定する必要があるかを判断する実装をすることになり、気軽に他でも使い回せるFragmentでなくなってしまいますね。


#まとめ

長々とありがとうございました。以上でAndroidStudioの標準デザインパターンテンプレートを活用したFragmentチュートリアルは終了です。
１週間くらいかけて仕事の合間にちょこちょこ作ってたので、中には不整合な内容があると思います。適当に読み替えてください。

恐らくなんとなくFragmentを使っていけそうな感じがしていると思いま・・・少なくても私は標準テンプレを何種類か組んだときにそう感じました！

なるべく疎結合なモジュールを増やすと楽になるというのは一般的には悪いことではないと思いますので積極的にFragmentを利用したいと自分に言いきかせて終了とさせていただきます。

このあとに記事中に登場したリンクをまとめてあります。
より正確な概念をこのあと学習していただければ幸いです。
ここでの大雑把解釈のままでいると他のエンジニアから馬鹿扱いされて窓際に追われる公算が高いので注意を促しておきます。

#参考
この記事の中でリンクして紹介したブログ等をまとめておきます。
大変勉強になりました。ありがとうございます。

[今さら聞けない Activity と Fragment の使い分け](http://qiita.com/KeithYokoma/items/c41b22bda8c8d924d8cd) @KeithYokomaさん
[ソフトウェア技術ドキュメントを勝手に翻訳](http://www.techdoctranslator.com/android/guide/activities/fragments#Lifecycle) umeda kaoruさん 
[Android　FragmentTransaction のまとめ](http://y-anz-m.blogspot.jp/2012/03/androidfragmenttransaction_14.html) yanzmさん


以下、私自信が投稿したもの
[View関連のUtilメモ](http://qiita.com/Hoshi_7/items/f29bfbd719b0bee8de48)
[Gist:ImageFragment作成までのコードの状態](https://gist.github.com/hoshi7/4bd0cab3d7aacc3ce211)
[Gist:TextFragment作成までのコード](https://gist.github.com/hoshi7/d89239842c7dda38a740)
[Gist:NavigationDrawer完成まで](https://gist.github.com/hoshi7/7aac7baa4238be697c84)
[Gist:複数のUIを切り替えるバージョン時(最終形態)](https://gist.github.com/hoshi7/009cac5bf448f71c86f5)