定义:A Fragment represents a behavior or a portion of user interface in an Activity.
一个Activity可包括多个Fragments,用来创建一个多pane的UI,并可在多个Activity中重用这些Fragment。此外,可将其看做是一个Activity的模块化部分,它有本身的生命周期,可接受用户输入,可在Activity运行时进行添加或者修改。
一个Fragment必须嵌入到一个Activity中,且受宿主Activity的影响。如Activity pause了,那么全部的Fragment都将进入pause,当全部Activity destory了,全部的Fragment也都destory了。当Activity在运行时,可添加或者删除fragment,还能够将其加入back stack,这样可经过back button 进行回退。
当添加一个Fragment时,它将做为ViewGroup的一个部分,而且可定义本身的View。可经过在Activity的代码中插入< fragment>标签,或者在运行时将其添加到一个已经存在ViewGroup。
然而Fragment并不一必定要做为Activity Layout的一部分,它也能够是无UI的,做为Activity不可见的Worker。android
- OnCreate(), 初始化必须的组建,即须要在fragement的onPause, onStop, onResume等状态时retain这些。
- onCreateView(), 为Fragemnt建立UI,而且须要返回布局的根View。若是该fragment不须要界面,也能够返回Null。
- onPause(), 这是指示用户须要离开该fragment,所以须要提交须要持久化的数据。app
还有3个Fragment能够继承的:less
提供用户接口,必须实现onCreateView(),返回布局的根View。如果ListFragment,则返回ListView。
To return a layout from onCreateView(), 可inflate an xml layout resource。 onCreateView的默认参数包含了一个LayoutInflater的对象。
代码以下:ide
public static class ExampleFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment return inflater.inflate(R.layout.example_fragment, container, false); } }
其中 container 是Activity布局里的ViewGroup对象,而后inflate出来的布局会被出入到该container。Bundler则是用于传递参数或者其余恢复布局的状态。然而,inflate方法的3个参数,第一个为布局的resource id, 第二个为container, 第3个指示是否须要attach 到 viewgroup,因为指定了container,于是此处应设为false,不然Android System将会create a redundant view group in the final layout.模块化
two ways to add。
1. 在activity的xml layout文件中,声明fragment xml 布局文件。布局
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent"> <fragment android:name="com.example.news.ArticleListFragment" android:id="@+id/list" android:layout_weight="1" android:layout_width="0dp" android:layout_height="match_parent" /> <fragment android:name="com.example.news.ArticleReaderFragment" android:id="@+id/viewer" android:layout_weight="2" android:layout_width="0dp" android:layout_height="match_parent" /> </LinearLayout>
其中android:name 属性为指定Fragment类来初始化layout。在系统初始话该布局时,它会初始化每一个fragment类,而后调用onCreateView()方法,获取到每一个fragment的布局。
为了重用the fragment,须要为每一个fragment分配一个unique id:使用android:id; 使用adndroid:tag; 不设置,系统使用container的id。
2. 代码中添加到一个现存的ViewGroup动画
// 获取fragmentTransaction,就可实现诸如add, remove, or replace a fragment等行为。 FragmentManager fragmentManager = getFragmentManager() FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); // 添加一个fragment到R.id.fragment_container,并提交。 ExampleFragment fragment = new ExampleFragment(); fragmentTransaction.add(R.id.fragment_container, fragment); fragmentTransaction.commit();
可将该fragment做为一个后台worker。
方法:ui
使用add(Fragment, String), 其中String是一个字符串tag,因为不提供layout给activity,所以该fragment也无需建立onCreateView()。tag将做为该fragment的标识,并使用findFragmentByTag()方法来寻找。this
- getFragmentById(), or getFragmentByTag();
- pop fragments off the back stack with popBackStack()
- addOnBackStackChangedListener(), register a listener for changes。
- open a FragmentTransaction, 处理add, remove fragment等事务。spa
Steps:
1. acquire an instance of FragmentTransaction
FragmentManager fragmentManager = getFragmentManager(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
// Create new fragment and transaction Fragment newFragment = new ExampleFragment(); FragmentTransaction transaction = getFragmentManager().beginTransaction(); // Replace whatever is in the fragment_container view with this fragment, // and add the transaction to the back stack transaction.replace(R.id.fragment_container, newFragment); transaction.addToBackStack(null); // Commit the transaction transaction.commit();
上述代码替换掉container中的当前fragment。
若调用了多个操做,add,replace等且调用了addToBackStack,在commit以前的全部操做都会被保存,并可被一块儿恢复。
commit必须被最后执行,添加多个fragment到同一个container,添加顺序将绝定每一个fragment在view hierarchy的顺序。
Tip:, 调用setTransition(),可为fragment之间的切换添加动画。另,若不调用addToBackStack,则调用remove,该fragment就会被destory。如果调用了addToBackStack,则该fragment将进入stopped,而且可被resumed when the user navigate it。
此外,commit()不是马上执行transation,而是会根据主线程调度状况执行。除非必需要马上执行,可调用executePendingTransaction()。
最后须要注意的是,commit()必须先于activity的saving its state(即pause或stop),不然将致使异常。解决这个问题,可调用cimmitAllowingStateless()。
View listView = getActivity.findViewById(R.id.list)
ExampleFragment fragment = getFragmentManager.findFragmentById(R.id.example_fragment);
public static class FragmentA extends ListFragment { ... // Container Activity must implement this interface public interface OnArticleSelectedListener { public void onArticleSelected(Uri articleUri); } ... }
public static class FragmentA extends ListFragment { OnArticleSelectedListener mListener; ... @Override public void onAttach(Activity activity) { super.onAttach(activity); try { mListener = (OnArticleSelectedListener) activity; } catch (ClassCastException e) { throw new ClassCastException(activity.toString() + " must implement OnArticleSelectedListener"); } } ... }
mListener.onArticleSelected(uri)
事件处理流程是Activity先处理,发现无人处理后才会向下传递到fragment中。
管理一个生命周期,仍然包括三个态:
- Resumed,运行时,可见。
- Paused, 被另外一个Activity挡住了,但本Activity仍然可见(未被彻底遮住,如dialog)。
- Stopped, 彻底不可见,但all state and member information is retained by the system。
可用onSaveInstanceState()保存数据,并在onCreate(), onCreateView(), or onActivityCreated()中重装。
其中Activity会自动进入BackStack,而fragment须要明确调用addToBackStack()。