Fragment是在Android 3.0之后被引入的,为了跨分辨率的问题,词如其名,即通过管理分块(碎片)Fragment,更灵活地布局,能在手机、TV、平板上实现一套代码,多种样式的需求。Fragment的名词定义也是碎片、片段的意思。
Fragment可以写成可重用的模块,因为它有自己的layout,自己的响应事件,几乎与activity完全相同。从模块化角度去思考,activity是一个APP模块化不同界面的载体,而Fragment也是activity再模块化的一个体现。可以实现界面的重用,布局的灵活切换。对于不同的业务起到良好的扩展,也有利于性能的提升(因为不用一次性加载所有布局,虽然他们会设置GONE或VISIBLE,但是还是要被绘制出来的呀~)。
首先需要注意,Fragment是在3.0版本引入的,如果你使用的是3.0之前的系统,需要先导入android-support-v4的jar包才能使用Fragment功能。android.support.v4.app.Fragment:可以兼容到1.6的版本。
关于这两个fragment使用标签的问题
(1)app.fragment和v4.fragment都是可以使用< fragment >标签的
只是在使用的时候,如果是app.fragment则没有什么特殊的地方,这个Activity继承Activity即可。
(2)当v4.fragment使用< fragment >标签的时候就要特别注意了:
当这个Activity的布局中有< fragment >标签的时候,这个Activity必须继承FragmentActivity。
(3)app包中关于Fragment的类和方法在V4包中都是有对应的。
getFragmentManager()和getSupportFragmentManager()区别
当api>=14时,使用getFragmentManager(),有时候使用Fragment的时候为了兼容低版本,
会引入Android-support-v4.jar支持包,这个时候,需要使用getSupportFragmentManager()。
先附上一幅图,供君赏阅~
图上显示的是activity与fragment生命周期的关系,对activity的某个生命周期方法的调用也会产生对fragment相同方法的调用。
fragment比activity多的几个方法是为了与activity交互而设立的。如下:
onAttach()
当fragment被加入到activity时调用(在这个方法中可以获得所在的activity)。
onCreateView()
当activity要得到fragment的layout时,调用此方法,fragment在其中创建自己的layout(界面)。
onActivityCreated()
当activity的onCreated()方法返回后调用此方法。
onDestroyView()
当fragment的layout被销毁时被调用。
onDetach()
当fragment被从activity中删掉时被调用。
一旦activity进入resumed状态(也就是running状态),你就可以自由地添加和删除fragment了。因此,只有当activity在resumed状态时,fragment的生命周期才能独立的运转,其它时候是依赖于activity的生命周期变化的。
同样类似于activity,你可以把fragment的状态保存在一个Bundle中,在activity被recreated时就需用到这个东西。你可以在onSaveInstanceState()方法中保存状态并在onCreate()或onCreateView()或onActivityCreated()中恢复,关于更多的保存状态的信息,请参考Activity章节。
最终效果如下:
activity的XML布局如下:
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<FrameLayout
android:id="@+id/fragment_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="50dp">
FrameLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_gravity="bottom"
android:orientation="horizontal">
<Button
android:id="@+id/left"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@color/colorPrimary"
android:text="左边"
android:textColor="@color/colorWhite"/>
<Button
android:id="@+id/right"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@color/colorAccent"
android:text="右边"
android:textColor="@color/colorWhite"/>
LinearLayout>
FrameLayout>
两个fragment的布局就不列了,就是一个Textview展示。
例子果断放弃了V4包的引用,因为最低兼容版本是14,所以这里都是用的FragmentManager。
activity代码如下:
public class ActivityB extends BaseActivity {
private FragmentManager fragmentManager;
private Button left, right;
private FragmentB fragmentB;
private FragmentC fragmentC;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_b);
fragmentManager = getFragmentManager();
setTabSelection(0);
initView();
}
private void setTabSelection(int index) {
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
if (fragmentB != null) {
fragmentTransaction.hide(fragmentB);
}
if (fragmentC != null) {
fragmentTransaction.hide(fragmentB);
}
switch (index) {
case 0:
if (fragmentB == null) {
fragmentB = new FragmentB();
fragmentTransaction.add(R.id.fragment_layout, fragmentB);
} else {
fragmentTransaction.show(fragmentB);
}
break;
case 1:
if (fragmentC == null) {
fragmentC = new FragmentC();
fragmentTransaction.add(R.id.fragment_layout, fragmentC);
} else {
fragmentTransaction.show(fragmentC);
}
break;
}
fragmentTransaction.commit();
}
private void initView() {
left = (Button) findViewById(R.id.left);
right = (Button) findViewById(R.id.right);
left.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
setTabSelection(0);
}
});
right.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
setTabSelection(1);
}
});
}
}
这里主要说setTabSelection方法吧~
通过FragmentManager开启事务FragmentTransaction,由该事务对fragment的添加、显示和隐藏工作做处理。
这种选项卡形式的界面,切换页面一般是需要缓存的,所以用的是show和hide方式。
FragmentTransaction transaction = fm.benginTransatcion();//开启一个事务
transaction.add()
往Activity中添加一个Fragment
transaction.remove()
从Activity中移除一个Fragment,如果被移除的Fragment没有添加到回退栈(回退栈后面会详细说),这个Fragment实例将会被销毁。
transaction.replace()
使用另一个Fragment替换当前的,实际上就是remove()然后add()的合体~
transaction.hide()
隐藏当前的Fragment,仅仅是设为不可见,并不会销毁
transaction.show()
显示之前隐藏的Fragment
detach()
会将view从UI中移除,和remove()不同,此时fragment的状态依然由FragmentManager维护。
attach()
重建view视图,附加到UI上并显示。
transatcion.commit()//提交一个事务
以上各个方法根据其功能的不同,并结合适合业务场景去运用。
fragmentB的代码(另一个fragment也类似):
public class FragmentB extends BaseFragment {
private final static String TAG = "FragmentB";
@Nullable
@Override
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_one_layout,null);
return view;
}
}
BaseFragment可以做些通用的初始化操作,比如进度dialog显示和隐藏等。
以上是对fragment的初步运用和分析,接下来会逐步深入的分析~