2013年11月6日水曜日

Fragmentを使ってみる(ファクトリメソッドを利用して引数を渡す)

今回は、Fragmentを生成する際に引数を渡したいと思います。

以前の「Fragmentを使ってみる(動的に追加&引数を渡す)」で、
Fragmentに値を渡したい場合にはBandleを利用する必要があると書きましたが、
どうしても生成時に値を渡したい方は、次のようにファクトリメソッドを用意する事で実現が可能になります。

Fragmentを使ってみる(動的に追加&引数を渡す)で利用したコードを、
一部変更してファクトリメソッドに対応したバージョンに書き換えたいと思います。

■AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.fragment9"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="8" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.fragment9.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

■fragment_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center"
    android:background="#eeeeee"
    >
     
    <TextView
        android:id="@+id/text_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="10dp"
        />
     
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_launcher"
        />
 
</LinearLayout>

■activity_main.xml
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
 
    <LinearLayout
        android:id="@+id/layout_fragment_1"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:orientation="vertical"
        android:background="#ff0000"
        />
 
    <LinearLayout
        android:id="@+id/layout_fragment_2"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:orientation="vertical"
        android:background="#00ff00"
         />
 
</LinearLayout>

■MainFragment.java

ファクトリメソッドのnewInstanceを用意します。
インスタンスを生成する場合にはこの関数を経由して必ず生成するようにします:(;゙゚'ω゚'):

ファクトリメソッドの中で、引数で渡された値を保持しておきます。
(保持させないとFragmentの再構成時に引数が引き継がれない)
package com.example.fragment9;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class MainFragment extends Fragment {
 
 /*
  * フラグメントを作成するためのファクトリメソッド
  */
 public static MainFragment newInstance(String title) {
  MainFragment fragment = new MainFragment();
  
  Bundle args = new Bundle();
  args.putString("title", title);
  // フラグメントに渡す値をセット
  fragment.setArguments(args);

  return fragment;
 }

 /**
  * Viewnoの生成
  * 
  * @see android.support.v4.app.Fragment#onCreateView(android.view.LayoutInflater,
  *      android.view.ViewGroup, android.os.Bundle)
  */
 @Override
 public View onCreateView(LayoutInflater inflater, ViewGroup container,
   Bundle savedInstanceState) {

  // Bundleで保存されたデータを復元
  String title = getArguments().getString("title");

  //
  Log.d("onCreateView", title);

  // 第1引数:レイアウトXMLファイルのリソースID、
  // 第2引数:
  // 第3引数:trueにするかfalseにするかで戻り値となるルートビュー(View)が変わる。
  // trueの場合には、第2引数で渡したViewGrou、falseの場合には第1引数で渡したリソースIDがルートビューになる
  View view = inflater.inflate(R.layout.fragment_main, container, false);
  //
  TextView text = (TextView) view.findViewById(R.id.text_view);
  text.setText(title);
  //
  return view;
 }

}
■MainActivity.java
Fragmentを生成するところの処理が次のように変更します。

・変更前
        //1つ目のfragmentを生成
        MainFragment fragment1 = new MainFragment();
        Bundle bundle1 = new Bundle();
        bundle1.putString("title", "キタ――(゚∀゚)――!!");
        // フラグメントに渡す値をセット
        fragment1.setArguments(bundle1);
・変更後
        //1つ目のfragmentを生成
        MainFragment fragment1 = MainFragment.newInstance("キタ――(゚∀゚)――!!");
変更後の方は内部でBundleを行っているためスッキリしました( ´∀`)bグッ!
package com.example.fragment9;

import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
 
public class MainActivity extends FragmentActivity {
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        //Fragmentを管理するFragmentManagerを取得
        FragmentManager manager = getSupportFragmentManager();
        //追加や削除などを1つの処理としてまとめるためのトランザクションクラスを取得
        FragmentTransaction tx = manager.beginTransaction();
        
        //1つ目のfragmentを生成
        MainFragment fragment1 = MainFragment.newInstance("キタ――(゚∀゚)――!!");

        //2つ目のfragmentを生成
        MainFragment fragment2 = MainFragment.newInstance("クル━━━━(゚∀゚)━━━━!!");
        
        //Fragment をスタックに追加する
        //メインレイアウトに対して追加先のビューのID、Fragment、Fragmentのタグ。
        //add() したときに既にバックスタックに同じタグの Fragment が存在する場合、
        //Fragment は新規作成されず、既にインスタンス化してある Fragment が再表示される。
        tx.add(R.id.layout_fragment_1, fragment1, "layout_fragment_1");
        tx.add(R.id.layout_fragment_2, fragment2, "layout_fragment_2");
        // 
        tx.commit();
    }
 
}
実行結果は次のようになります。


Fragment側でBundleした方が呼び出し側のコードがスッキリするし、
FragmentのことはFragment側だけで殆どの流れが把握できるので(・∀・)イイネ!!

今度からこっちを使っていこうかな~(ΦωΦ)フフフ…

以上です(`・ω・´)ゞビシッ!!

参考URL

0 件のコメント:

コメントを投稿