package in.srain.cube.app; import android.app.ActivityManager; import android.content.Context; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; import android.text.TextUtils; import android.view.View; import android.view.WindowManager; import android.view.inputmethod.InputMethodManager; import android.widget.Toast; import in.srain.cube.util.CLog; import java.util.List; public abstract class CubeFragmentActivity extends FragmentActivity { private final static String LOG_TAG = "cube-fragment"; public static boolean DEBUG = true; protected CubeFragment currentFragment; private boolean mCloseWarned; /** * return the string id of close warning * <p/> * return value which lower than 1 will exit instantly when press back key * * @return */ protected abstract String getCloseWarning(); protected abstract int getFragmentContainerId(); public void pushFragmentToBackStack(Class<?> cls, Object data) { FragmentParam param = new FragmentParam(); param.cls = cls; param.data = data; goToThisFragment(param); } protected String getFragmentTag(FragmentParam param) { StringBuilder sb = new StringBuilder(param.cls.toString()); return sb.toString(); } private void goToThisFragment(FragmentParam param) { int containerId = getFragmentContainerId(); Class<?> cls = param.cls; if (cls == null) { return; } try { String fragmentTag = getFragmentTag(param); FragmentManager fm = getSupportFragmentManager(); if (DEBUG) { CLog.d(LOG_TAG, "before operate, stack entry count: %s", fm.getBackStackEntryCount()); } CubeFragment fragment = (CubeFragment) fm.findFragmentByTag(fragmentTag); if (fragment == null) { fragment = (CubeFragment) cls.newInstance(); } if (currentFragment != null && currentFragment != fragment) { currentFragment.onLeave(); } fragment.onEnter(param.data); FragmentTransaction ft = fm.beginTransaction(); if (fragment.isAdded()) { if (DEBUG) { CLog.d(LOG_TAG, "%s has been added, will be shown again.", fragmentTag); } ft.show(fragment); } else { if (DEBUG) { CLog.d(LOG_TAG, "%s is added.", fragmentTag); } ft.add(containerId, fragment, fragmentTag); } currentFragment = fragment; ft.addToBackStack(fragmentTag); ft.commitAllowingStateLoss(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } mCloseWarned = false; } public void goToFragment(Class<?> cls, Object data) { if (cls == null) { return; } CubeFragment fragment = (CubeFragment) getSupportFragmentManager().findFragmentByTag(cls.toString()); if (fragment != null) { currentFragment = fragment; fragment.onBackWithData(data); } getSupportFragmentManager().popBackStackImmediate(cls.toString(), 0); } public void popTopFragment(Object data) { FragmentManager fm = getSupportFragmentManager(); fm.popBackStackImmediate(); if (tryToUpdateCurrentAfterPop() && currentFragment != null) { currentFragment.onBackWithData(data); } } public void popToRoot(Object data) { FragmentManager fm = getSupportFragmentManager(); while (fm.getBackStackEntryCount() > 1) { fm.popBackStackImmediate(); } popTopFragment(data); } @Override protected void onStart() { super.onStart(); debugTaskInfo(); } protected void debugTaskInfo() { ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE); List<ActivityManager.RunningTaskInfo> taskList = manager.getRunningTasks(10); CLog.d("test", "debugTaskInfo: %s %s", this.getClass().getName(), taskList.size()); for (int i = 0; i < taskList.size(); i++) { ActivityManager.RunningTaskInfo info = taskList.get(i); CLog.d("test", "RunningTaskInfo: %d %s, %s", info.numActivities, info.topActivity.getClassName(), info.baseActivity.getClassName()); } } /** * process the return back logic * return true if back pressed event has been processed and should stay in current view * * @return */ protected boolean processBackPressed() { return false; } /** * process back pressed */ @Override public void onBackPressed() { // process back for fragment if (processBackPressed()) { return; } // process back for fragment boolean enableBackPressed = true; if (currentFragment != null) { enableBackPressed = !currentFragment.processBackPressed(); } if (enableBackPressed) { int cnt = getSupportFragmentManager().getBackStackEntryCount(); if (cnt <= 1 && isTaskRoot()) { String closeWarningHint = getCloseWarning(); if (!mCloseWarned && !TextUtils.isEmpty(closeWarningHint)) { Toast toast = Toast.makeText(this, closeWarningHint, Toast.LENGTH_SHORT); toast.show(); mCloseWarned = true; } else { doReturnBack(); } } else { mCloseWarned = false; doReturnBack(); } } } private boolean tryToUpdateCurrentAfterPop() { FragmentManager fm = getSupportFragmentManager(); int cnt = fm.getBackStackEntryCount(); if (cnt > 0) { String name = fm.getBackStackEntryAt(cnt - 1).getName(); Fragment fragment = fm.findFragmentByTag(name); if (fragment != null && fragment instanceof CubeFragment) { currentFragment = (CubeFragment) fragment; } return true; } return false; } protected void doReturnBack() { int count = getSupportFragmentManager().getBackStackEntryCount(); if (count <= 1) { finish(); } else { getSupportFragmentManager().popBackStackImmediate(); if (tryToUpdateCurrentAfterPop() && currentFragment != null) { currentFragment.onBack(); } } } public void hideKeyboardForCurrentFocus() { InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); if (getCurrentFocus() != null) { inputMethodManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0); } } public void showKeyboardAtView(View view) { InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); inputMethodManager.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT); } protected void exitFullScreen() { getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); } }