在项目中经常遇到一个activity+多个fragment组合,这就要考虑fragmeng之间的切换了,如下示例是用于应用初始化时把fragmeng建好,并管理的一个Navigator。
一、新建父级Navigator抽象类
/**
* author : CrazyDong
* description :用于切换fragment的导航器,布局分为左、右两部分fragment
*/
public abstract class AbstractEnergyFragmentNavigator {
private static final String TAG = "AbstractEnergyFragmentNavigator";
public static final byte SHOW_IN_LEFT_SIDE = 1;//左边fragment标志
public static final byte SHOW_IN_RIGHT_SIDE = 2;//右边fragment标志
public static final int SIDE_EMPTY = -1;//布局空显示ID
private FragmentManager _fragmentManager;
private BaseFragment mLeftPreviousFragment;//当前左边的fragment
private BaseFragment mRightPreviousFragment;//当前右边的fragment
private int mLeftViewId; //显示左侧Fragment使用的FrameLayout的ID
private int mRightViewId; //显示右侧Fragment使用的FrameLayout的ID
private Map<Integer, BaseFragment> _frmStorage = new HashMap();//总的fragment容器
private Map<Integer, BaseFragment> mLeftAddedFragments = new HashMap();//左边fragment容器
private Map<Integer, BaseFragment> mRightAddedFragments = new HashMap();//右边fragment容器
protected OnFragmentChangeListener mOnFragmentChangeListener;//切换fragment时的监听
private List<Integer> _plugIn;//所有所要建立的fragment的key集合
//初始化的方法
public void initialize(final FragmentManager fragmentManager, final int leftViewId, final int rightViewId) {
_fragmentManager = fragmentManager;
mLeftViewId = leftViewId;
mRightViewId = rightViewId;
}
//释放对象,防止OOM
public void finalized() {
mLeftPreviousFragment = null;
mRightPreviousFragment = null;
mRightAddedFragments.clear();
mLeftAddedFragments.clear();
_frmStorage.clear();
}
//将Fragment放入总的容器
public void insertView(final int key, final BaseFragment view) {
_frmStorage.put(key, view);
}
/**
* commit()方法并不立即执行transaction中包含的动作,而是把它加入到UI线程队列中.
* 如果想要立即执行,可以在commit之后立即调用FragmentManager的executePendingTransactions()方法.
*/
protected void insertViewFinish() {
_fragmentManager.executePendingTransactions();
}
/**
* 默认将Fragment显示在左侧画页中
*
* @param key
*/
public void gotoView(final int key) {
gotoView(key, SHOW_IN_LEFT_SIDE);
}
/**
* 页面跳转方法
* @param key 页面ID
* @param side 显示在哪一边
*/
public void gotoView(final int key, final byte side) {
LogTool.d(TAG, "gotoView() Fragment add to which side :" + side);
if (SHOW_IN_LEFT_SIDE == side) {
gotoLeftView(key);
} else {
gotoRightView(key);
}
if (mOnFragmentChangeListener != null) {
mOnFragmentChangeListener.onFragmentChange(key, side);
LogTool.d(TAG, "pageId is " + key);
} else {
LogTool.d(TAG, "pageId is " + key + " mOnFragmentChangeListener is null.");
}
}
private synchronized void gotoRightView(final int key) {
LogTool.d(TAG, "AbstractFragmentNavigator has showed --right key=>" + key);
FragmentTransaction transaction = _fragmentManager.beginTransaction();
if (SIDE_EMPTY == key && mRightPreviousFragment != null) {
transaction.hide(mRightPreviousFragment);
transaction.commitAllowingStateLoss();
mRightPreviousFragment = null;
}
BaseFragment fragment = _frmStorage.get(key);
if (null == fragment)//容器中没有此fragmeng
return;
if (fragment == mRightPreviousFragment)//当前fragmeng等于想要跳转的fragmeng
return;
if (null != mRightPreviousFragment)
transaction.hide(mRightPreviousFragment);
if (mRightAddedFragments.containsKey(key)) {
transaction.show(fragment);
LogTool.d(TAG, "%d gotoRightView() fragment has show---", key);
LogTool.d(TAG, "%s gotoRightView() show fragment name---", fragment.toString());
} else {
transaction.add(mRightViewId, fragment);
mRightAddedFragments.put(key, fragment);//TODO 需要做side的检测,是否是有效值
}
transaction.commitAllowingStateLoss();
mRightPreviousFragment = fragment;
}
private synchronized void gotoLeftView(final int key) {
LogTool.d(TAG, "AbstractFragmentNavigator has showed --left => " + key);
BaseFragment fragment = _frmStorage.get(key);
if (null == fragment) {
LogTool.d(TAG, "gotoLeftView() fragment is null return. key=> " + key);
return;
}
if (fragment == mLeftPreviousFragment) {
LogTool.d(TAG, "gotoLeftView() key fragment == mLeftPreviousFragment return. key=> " + key);
return;
}
FragmentTransaction transaction = _fragmentManager.beginTransaction();
if (null != mLeftPreviousFragment) {
transaction.hide(mLeftPreviousFragment);
LogTool.d(TAG, "gotoLeftView() key hide mLeftPreviousFragment. key=>");
}
if (mLeftAddedFragments.containsKey(key)) {
transaction.show(fragment);
LogTool.d(TAG, "%d fragment has show---", key);
LogTool.d(TAG, "%s show fragment name---", fragment.toString());
} else {
LogTool.d(TAG, "gotoLeftView() add key=> " + key);
transaction.add(mLeftViewId, fragment);
mLeftAddedFragments.put(key, fragment);//TODO 需要做side的检测,是否是有效值
}
transaction.commitAllowingStateLoss();
mLeftPreviousFragment = fragment;
}
//添加key的方法
protected abstract List<Integer> buildPlugIn();
protected abstract BaseFragment createFragment(final int frmId, final AbstractEnergyFragmentNavigator navigator);
public void buildFragment() {
_plugIn = buildPlugIn();
for (int id : _plugIn) {
BaseFragment baseFragment = createFragment(id, this);
int idd = id;
LogTool.d(TAG, "baseFragment " + baseFragment + " idd " + idd);
insertView(idd, baseFragment);
}
insertViewFinish();
}
/**
* 返回上级菜单
*/
public void goBack() {
if (mLeftPreviousFragment != null) {
mLeftPreviousFragment.onBackEvent();
}
}
public interface OnFragmentChangeListener {
void onFragmentChange(int pageId, int whichSide);
}
public void registerOnFragmentChangeListener(OnFragmentChangeListener listener) {
mOnFragmentChangeListener = listener;
}
}
二、新建一个MyActivityNavigator继承AbstractEnergyFragmentNavigator
public class MyActivityNavigatorextends AbstractEnergyFragmentNavigator{
public static final String TAG = "MyActivityNavigator";
private Context mContext;
public void init(Context context, final FragmentManager fragmentManager, final int leftViewId, final int rightViewId) {
LogTool.d_end(TAG, "init()");
super.initialize(fragmentManager, leftViewId, rightViewId);
mContext = context;
buildFragment();
}
public void finalized() {
super.finalized();
}
@Override
protected List<Integer> buildPlugIn() {
final List<Integer> plugIns = new ArrayList<>();
plugIns.add(Variables.aa);//Variables.aa是key值
plugIns.add(Variables.bb);
return plugIns;
}
@Override
protected BaseFragment createFragment(int frmId, AbstractEnergyFragmentNavigator navigator) {
switch (frmId){
case Variables.aa://根据key值new 索要使用的fragmeng
Afragment afragment = new Afragment();
return afragment ;
case Variables.bb:
BFragment bFragment = new BFragment ();
return bFragment ;
default:
return null;
}
}
}
所用到的常量可以放到一个常量类中,如下:
/**
* author : CrazyDong
* description :用于存储常量
*/
public class Variables {
public static final int aa = 100;
public static final int bb= 200;
}
三、在MainActivity中使用
public class MainActivity extends Activity implements View.OnClickListener {
public static final String TAG = "EnergyMainActivity";
public static int cMenuLeft = -1;
public static int cMenuRight = -1;
private EnergyMainActivityNavigator _navigator;
public Button btn_test;
@Override
protected void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_NO_TITLE);
savedInstanceState = null;
super.onCreate(savedInstanceState);
LogTool.d(TAG, "onCreate start");
setContentView(R.layout.new_energy_main);
VehicleBean.getInstance().initCallBack();
buildFragment();
btn_test = (Button) findViewById(R.id.btn_test);
btn_test.setOnClickListener(this);
_navigator.gotoView(Variables.aa);//左边跳转AFragment
_navigator.gotoView(Variables.bb,SHOW_IN_RIGHT_SIDE);//右边跳转BFragment
LogTool.d(TAG, "onCreate end");
}
public void buildFragment() {
_navigator = new EnergyMainActivityNavigator();
_navigator.init(getApplicationContext(), getFragmentManager(), R.id.fragment_left_energy, R.id.fragment_right);
_navigator.registerOnFragmentChangeListener(new EnergyOnFragmentChangeListener());
}
class EnergyOnFragmentChangeListener implements AbstractEnergyFragmentNavigator.OnFragmentChangeListener {
@Override
public void onFragmentChange(int pageId, int whichSide) {
//监听fragmeng改变时的接口
int type = pageId / 100;
switch (type) {
case 1:
break;
default:
LogTool.d(TAG, "onFragmentChange() invalid value : " + pageId);
break;
}
}
}
@Override
public void onClick(View view) {
LogTool.d(TAG, "onClick() text=>" + ((RadioButton) view).getText());
switch (view.getId()) {
case R.id.btn_test:
_navigator.gotoView(Variables.aa);
_navigator.gotoView(Variables.bb,SHOW_IN_RIGHT_SIDE);
break;
default:
break;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
//回收一下资源,防止内存泄漏而OOM
_navigator.finalized();
_navigator = null;
}
@Override
public void onBackPressed() {
_navigator.goBack();
}
}
layout布局文件如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/main_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/common_background"
android:fitsSystemWindows="true"
android:orientation="horizontal">
<Button
android:id="@+id/btn_test"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/fragment_left_energy"
android:layout_width="@dimen/dimen780dp"
android:layout_height="match_parent"/>
<FrameLayout
android:id="@+id/fragment_right"
android:layout_width="@dimen/dimen980dp"
android:layout_height="match_parent"
android:layout_toEndOf="@id/fragment_left_energy"/>
</RelativeLayout>
</LinearLayout>