从google在Android3.0推出fragment之后,fragment的使用场景越来越多。fragment可以将UI界面一块儿一块儿的封装,有更加强大、灵活的生命周期,更快的启动速度。现在越来越多的app,会较少的使用activity,而是用fragment完成大部分页面的展示。
在这里,我将记录关于fragment的使用方法。
首先,我们要建立一个大致的结构模型。我们使用Activity作为App的底层界面容器。在Activity中用一个控件,来显示fragment。然后界面的切换就是用这个控件来切换它显示的fragment。
所以Activity的xml比较简单:
activity_main.xml:
<LinearLayout 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" android:orientation="vertical" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity"> <FrameLayout android:id="@+id/main_framelayout" android:layout_width="match_parent" android:layout_height="match_parent"></FrameLayout> </LinearLayout>
将要用来显示fragment的容易就是这个framelayout。
在开始MainAcitivy.java的代码编写之前,先要在此说明两个类。
1.FragmentManager
它像一个管理fragment的类,它类似一个fragment的容器,能够使用add,remove,findFragmentByTag方法,操作fragment。但是除了findFragmentByTag,我们不能直接操作add和remove,也不能直接操作fragment。我们需要另一个类来进行操作——FragmentTransaction。
2.FragmentTransaction
它是一个一次性的事务,我们通过fragmentManager.beginTransaction();获取它,用fragmentTransaction.commit();完成操作。fragmentTransaction提交过一次之后,就不能再提交了。下一次操作时,就要创建新的实例。
public class MainActivity extends Activity implements mBaseUiFragment.OnUiFragmentJumpToListener { FrameLayout mainFrameLayout; FragmentManager fragmentManager; Fragment mainFragment; Stack<Fragment> mFragmentStack; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mainFrameLayout = (FrameLayout) findViewById(R.id.main_framelayout); initFragment(); } private void initFragment(){ fragmentManager = getFragmentManager(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); mFragmentStack = new Stack<>(); mainFragment = new MainFragment(); fragmentTransaction.add(R.id.main_framelayout, mainFragment, MainFragment.FRAGMENT_TAG); mFragmentStack.push(mainFragment); fragmentTransaction.show(mainFragment); fragmentTransaction.commit(); }
}
mFragmentStack是一个存放fragment的栈。用于模仿activity的堆栈返回机制。
我们在给fragmentManager中添加fragment时,我们需要设置一个tag.这样,我们想再操作这个fragment时,我们就可以通过findFragmentByTag这个方法,获得这个fragment的引用。
mBaseUiFragment.OnUiFragmentJumpToListener 是一个接口,用于fragment对activity的回调。这个接口定义在uiFragment的基类中。
mBaseUiFragment.java:
public class mBaseUiFragment<T extends mBaseUiFragment> extends mBaseFragment { Context mContext; View rootView; OnUiFragmentJumpToListener onUiFragmentJumpToListener; public interface OnUiFragmentJumpToListener{ void jumpToFragment(Class<? extends Fragment> fragmentClass , String toFragmentTag); void fragmentBack(); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mContext = getActivity(); onUiFragmentJumpToListener = (OnUiFragmentJumpToListener) getActivity(); } }
在这个基类中,定义了OnUiFragmentJumpToListener接口,并赋予它实例。OnUiFragmentJumpToListener接口中暂时只声明了跳转和返回的方法。
因为,我们在MainActivity中可以加上这一段的实现
MainActivity.java:
public class MainActivity extends Activity implements mBaseUiFragment.OnUiFragmentJumpToListener { FrameLayout mainFrameLayout; FragmentManager fragmentManager; Fragment mainFragment; Stack<Fragment> mFragmentStack; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mainFrameLayout = (FrameLayout) findViewById(R.id.main_framelayout); initFragment(); } private void initFragment(){ fragmentManager = getFragmentManager(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); mFragmentStack = new Stack<>(); mainFragment = new MainFragment(); fragmentTransaction.add(R.id.main_framelayout, mainFragment, MainFragment.FRAGMENT_TAG); mFragmentStack.push(mainFragment); fragmentTransaction.show(mainFragment); fragmentTransaction.commit(); } @Override public void jumpToFragment(Class<? extends Fragment> fragmentClass , String toFragmentTag) { FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); Fragment targetFragment = fragmentManager.findFragmentByTag(toFragmentTag); if (targetFragment == null){ try { targetFragment = fragmentClass.newInstance(); fragmentTransaction.add(R.id.main_framelayout , targetFragment , toFragmentTag); fragmentTransaction.show(fragmentClass.newInstance()); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } }else { fragmentTransaction.show(targetFragment); } fragmentTransaction.hide(mFragmentStack.get(0)); mFragmentStack.push(targetFragment); fragmentTransaction.commit(); } @Override public void fragmentBack() { FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); Fragment fromFragment = mFragmentStack.pop(); fragmentTransaction.hide(fromFragment); fragmentTransaction.show(mFragmentStack.get(0)); fragmentTransaction.commit(); } }
最后,贴上MainFragment和TestFragment的代码。MainFragment中可以”跳转“至TestFragment,TestFragment可以”返回“。
MainFragment:
public class MainFragment extends mBaseUiFragment implements View.OnClickListener { static public String FRAGMENT_TAG = "MainFragment"; // View TextView downLoadProgress; Button startOrPauseBtn; Button stopBtn; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { rootView = inflater.inflate(R.layout.main_layout , null); initView(); return rootView; } private void initView(){ downLoadProgress = (TextView) rootView.findViewById(R.id.download_progress_id); startOrPauseBtn = (Button) rootView.findViewById(R.id.start_or_pause_btn); startOrPauseBtn.setOnClickListener(this); stopBtn = (Button) rootView.findViewById(R.id.stop_btn); stopBtn.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()){ case R.id.start_or_pause_btn: onUiFragmentJumpToListener.jumpToFragment(TestFragment.class , TestFragment.FRAGMENT_TAG); break; case R.id.stop_btn: break; } } }
TestFragment:
public class TestFragment extends mBaseUiFragment { static public String FRAGMENT_TAG = "TestFragment"; Button backBtn; @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { rootView = inflater.inflate(R.layout.test_fragment_layout , null); backBtn = (Button) rootView.findViewById(R.id.back_btn); backBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onUiFragmentJumpToListener.fragmentBack(); } }); return rootView; } }
这样就构建起一个基本的以Fragment代替Activity的界面切换的结构。
Done!