Android开发——Fragment知识整理(一)

0.  前言

Fragment,顾名思义是片段的意思,可以把Fragment当成Activity的一个组成部分,甚至Activity的界面可以完全有不同的Fragment组成。Fragment需要被嵌套到Activity上面才能起作用,Fragment可以充分利用屏幕面积,而且也可以更方便用户进行交互操作。Fragment是在Android3.0API level 11引入的,如果你要适配之前的系统,需要先导入Android-support-v4jar包,继承FragmentActivity并通过getSupportFragmentManager获得FragmentManager

 

1.  Fragment声明周期

Fragment的生命周期和Activity很像,只是多了几个方法如下所示。需要注意的是,因为Fragment是依附于Activity的,所以Activity的生命周期会影响到Fragment的生命周期,如下onActivityCreated()的调用时机就说明了这一点。还有比如,如果Activity是暂停状态,其中所有的Fragment都是暂停状态。如果Activity被销毁,那么它其中的所有Fragment都会被销毁。

//当Fragment被绑定到Activity时被调用
onAttach()
//创建该Fragment的视图,最常用,除了这个方法其余方法调用都需要super
onCreateView()
//当Activity的onCreate方法返回时调用
onActivityCreated()
//移除Fragment的布局时被调用,跟onCreateView()对应
onDestroyView()
//当Fragment跟Activity解除关联时被调用,跟onAttach()对应
onDetach()

2.  Fragment的使用方式

2.1  静态方式

静态方式是把Fragment当成普通的控件,直接把<fragment>写在activity_main.xml布中。

(需要注意指定andorid:name="<packageName>.MyFragment",这时Activity中只需setContentView即可。)

(1)首先写一个MyFragment类继承Fragment,重写onCreateView,使用inflate决定Fragemnt的布局。点击事件也可以处理。

public class MyFragment extends Fragment    {      
    @Override    
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){    
        View view = inflater.inflate(R.layout.myfragment, container, false);            
        return view;    
    }    
}    

(2)最后直接在Activity中布局文件中声明此Fragment,就当和普通的View一样使用即可。

<RelativeLayout 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" >    
    <fragment    
        android:id="@+id/myfragment"    
        android:name="com.example.seucalvin.MyFragment"    
        android:layout_width="match_parent"    
        android:layout_height="match_parent" />      
</RelativeLayout> 

2.2  动态方式

动态方式可以灵活地添加、更新、以及删除Fragment。

(1)首先将Activity的布局设置为空。

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/id_content ">
</FrameLayout>

(2)接着将Fragment1加载到Activity的FrameLayout中,这里使用add()对Fragment进行了动态的加载。具体API功能可以参考下文的总结。

//在Activity的onCreate()中先默认加载Fragment1到FrameLayou中
FragmentTransaction ft= getFragmentManager().beginTransaction();  
ft.add(R.id.id_content, new FragmentOne(),"ONE");  //最后一个参数为tag
ft.commit(); 

(3)接下来是第二个Fragment2,我们这里选择在Fragment1的某个按钮中加点击事件完成跳转。

public class FragmentOne extends Fragment implements OnClickListener {  
    private Button mBtn;  
    @Override  
    public View onCreateView(LayoutInflater inflater, ViewGroup container,  Bundle savedInstanceState)  {  
        View view = inflater.inflate(R.layout.fragment_one, container, false);  
        mBtn = (Button) view.findViewById(R.id.fragment_one_btn);  
        mBtn.setOnClickListener(this);  
        return view;  
    }  
    @Override  
    public void onClick(View v)  {  
        FragmentTwo two = new FragmentTwo();  
        FragmentTransaction  ft = getFragmentManager().beginTransaction();  
        ft.replace(R.id.id_content, two, "TWO");  
        ft.addToBackStack(null);  
        ft.commit();  
    }  
}

有时候,我们可能有这样的需求,比如京东商城APP导航栏每个按钮对应一个fragment,当用户按下BACK键,会先判断若不是首页的fragment则回到首页的fragment,再按下BACK才会退出应用,达到了比较好的用户体验效果。这就需要用到Fragment的回退栈

在上面代码的14行使用了replace()方法,replaceremoveadd的合体,如果Fragment1没有被添加到回退栈,跳转时Fragment1实例会被销毁。上面源码中15行我们调用了ft.addToBackStack(null)将Fragment1添加到了回退栈,所以Fragment1实例不会被销毁,但是视图层次依然会被销毁,即会调用onDestoryViewonCreateView,即当我们按下BACK键回到Fragment1时,Fragment1上诸如EditText上曾经编辑的文字会消失。那么如何保证曾经的输入还在呢?可以如下这样写点击逻辑。

 public void onClick(View v)  {  
        FragmentTwo two = new FragmentTwo();  
        FragmentTransaction  ft = getFragmentManager().beginTransaction();  
        ft.hide(this);  
        ft.add(R.id.id_content, fTwo, "TWO");  
        ft.addToBackStack(null);  
        ft.commit();  
    }  

这里没有使用replace,而是先hide当前Fragment,再添加Fragment2实例,最后Fragment1添加到回退栈,这样即可实现文字的保留。

(4)Back操作。

无论接下来Fragment2在进入Fragment3、4、5...,用户只要点击Back键,直接回到Fragment1,如果直接在主界面Fragment1则直接退出的逻辑:

public boolean onKeyDown(int keyCode, KeyEvent event) {
     if (keyCode == KeyEvent.KEYCODE_BACK) {
     // 获取当前回退栈中的Fragment个数
     int backStackEntryCount = fragmentManager.getBackStackEntryCount();
        if (backStackEntryCount > 1) {
        // 如果回退栈中Fragment个数大于1则一直退出
         while (fragmentManager.getBackStackEntryCount() > 1) {
             fragmentManager.popBackStackImmediate();//退出一层
            }
         } else {
              finish();
          }
      }
        return true;
}

3  API介绍

这一小节介绍Fragment相关的API。这些常用API的作用还是要熟悉的。

//获取FragmentManage的方式,v4包中为getSupportFragmentManager
getFragmentManager()
//开启一个事务,并添加/删除一个Fragment
//从Activity中remove一个Fragment时,如果被移除的Fragment没有添加到回退栈,这个Fragment实例将会被销毁,而后面的detach则不会销毁实例,只是销毁其视图结构
FragmentTransaction transaction = fm.benginTransatcion();
transaction.add() 
transaction.remove() 
transatcion.commit()//提交一个事务,一定要在Activity.onSaveInstance()之前调用
//使用另一个Fragment替换当前的,实际上就是remove()然后add()的合体
transaction.replace()
//隐藏/显示当前的Fragment,隐藏仅仅是设为不可见,并不会销毁
transaction.hide()
transaction.show()
//会将view从UI中移除,fragment的状态依然由FragmentManager维护
detach()
//重建view视图,附加到UI上并显示
attach()

下面的API是关于回退栈的,均为fm所调用。

//将Fragment添加到回退栈中
addToBackStack(tag) 
//如果i=0,则回退到该tag所对应的Fragment层
//如果i=FragmentManager.POP_BACK_STACK_INCLUSIVE,则回退到该tag所对应的Fragment的上一层
popBackStack(String tag, int i)
//立即清除栈顶Fragment,即回退一步
popBackStackImmediate()
//获取回退栈中Fragment的个数
getBackStackEntryCount()
//获取回退栈中该索引值下的Fragment
//index若为fragmentManager.getBackStackEntryCount() – 1即获取当前回退栈节点,该节点的getName()返回tag标记
getBackStackEntryAt(int index)

下一篇Android开发——Fragment知识整理(二)将着重于介绍Fragment和Activity之间的通信以及使用Fragment保存Activity销毁时数据的一些知识。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值