2014年12月4日木曜日

単一Fragmentを表示するActivityの共通化

全画面想定のFragmentをActivityで取り回したい場合。AaaFragment, BbbFragmentに合わせてAaaActivity, BbbActivityとか作るのは面倒なのでActivityのWrapperを共通化。

Fragmentは public static XxxFragment newInstance(Bundle args);を実装している想定。
画面遷移時は、FragmentからならWrapperActivity.openFragmentActivity(getActivity(), SecondFragment.class, secondFragmentsArguments); という感じで行える。

package hoge.fuga.activities;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.View;
import android.view.View.OnClickListener;
import jp.arithmetic.arithmusic.R;
import jp.arithmetic.arithmusic.model.FragmentReplacer;

public class WrapperActivity extends Activity {
 public static final String TAG = "WrapperActivity";
 public static final String ARGS_FRAGMENT = "app-fragment";
 
 
 /** 
  * 1つのFragmentを全面に表示する共通化Activity
  * @param fromActivity
  * @param clazz
  * @param args
  */
 public static void openFragmentActivity(Activity fromActivity, Class clazz, Bundle args) {
  // setup bundle
  if (args == null) {
   args = new Bundle();
  }
  args.putString(ARGS_FRAGMENT, clazz.getName());
  
  // setup intent
  Intent i = new Intent(fromActivity, WrapperActivity.class);
  i.putExtras(args);
  
  // start activity
  fromActivity.startActivity(i);
 }
 
 /** 
  * close
  * @param fromActivity
  */
 public static void closeFragmentActivity(Activity fromActivity) {
  fromActivity.finish();
 }
 
 public static void closeToStartActivity(Activity fromActivity) {
  Intent i = new Intent(fromActivity, SomeStartActivity.class);
  i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
  i.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
  fromActivity.startActivity(i);
 }
 
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_empty_container);

  // intentパラメータ優先
  Bundle args = (getIntent() != null) ? getIntent().getExtras() : savedInstanceState;
  if (args == null) {
   throw new RuntimeException("Wrapper: Empty arguments");
  }
  
  // 呼び出しFragment特定、初期化
  String className = args.getString(ARGS_FRAGMENT);
  if (className == null || className.isEmpty()) {
   throw new RuntimeException("Wrapper: Empty class name");
  }
  Fragment f = null;
  try {
   Class clazz = Class.forName(className);
   Method newInstance = clazz.getMethod("newInstance", Bundle.class);
   f = (Fragment)newInstance.invoke(null, args);

   replaceFragment(f);
   
  } catch (ClassNotFoundException e) {
   e.printStackTrace();
   finish();
  } catch (NoSuchMethodException e) {
   e.printStackTrace();
   finish();
  } catch (IllegalAccessException e) {
   e.printStackTrace();
   finish();
  } catch (IllegalArgumentException e) {
   e.printStackTrace();
   finish();
  } catch (InvocationTargetException e) {
   e.printStackTrace();
   finish();
  }
 }
 
 @Override
 public void onBackPressed() {
  if (getSupportFragmentManager().getBackStackEntryCount() == 1) {
   closeFragmentActivity(this);
  } else {
   super.onBackPressed();
  }
 }
 
 
 public void replaceFragment(Fragment f) {
  getSupportFragmentManager()
  .beginTransaction()
  .addToBackStack(null)
  .replace(R.id.empty_container, f)
  .commit();
 }
}