安卓中fragment的使用全解

来源:互联网 发布:potplayermini优化版 编辑:程序博客网 时间:2024/06/05 15:24

全栈工程师开发手册 (作者:栾鹏)

安卓教程全解

安卓中Fragment可以没有UI,不需要manifest中注册,只能嵌套在一个activity存在。

在Fragment基础上,系统派生处理另外几种fragment

1、DialogFragment:一个fragment可以在fragment的父activity上显示一个浮动的对话框,而且可以自定义对话框的UI

2、ListFragment:可以通过绑定数据源呈现一个Listview作为它主要的UI展示方式

3、WebViewFragment:封装了WebView,当Fragment被暂停或恢复时,子WebView同样会被暂停和恢复

fragment布局在activity的方式

在activity中设置fragment有2种方式。

1、在xml中设置一个FrameLayout的容器,使用java为其添加一个fragment。

2、在xml中直接引用自定义的fragment。

我们设置activity的UI如下:一个空的fragment容器:FrameLayout,一个自定义Fragment,一个自定义ListFragment。

activity_frament.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  android:orientation="vertical"  android:layout_width="match_parent"  android:layout_height="match_parent">  <!-- 作为自定义fragment的父容器,在java中去填充这个容器 -->  <FrameLayout    android:id="@+id/activity_fragment_container"    android:layout_width="match_parent"     android:layout_height="wrap_content"     android:layout_weight="1"    android:background="@color/red"  />   <!-- 直接引用java中自定义的Fagment,必须为该fragment设置id或tag -->  <fragment android:name="com.lp.app.Fragment1"    android:id="@+id/activity_fragment_item"    android:layout_width="match_parent"     android:layout_height="wrap_content"     android:layout_weight="3"    android:background="@color/green"  />   <!-- 直接引用java中自定义的ListFragment,必须为该fragment设置id或tag  -->   <fragment android:name="com.lp.app.Fragment_list"    android:id="@+id/activity_fragment_list"    android:layout_width="match_parent"     android:layout_height="wrap_content"    android:layout_weight="3"    android:background="@color/blue"  /> </LinearLayout> 

在activity中使用java操作Fragment、ListFragment

对于在UI 的xml文件中设置的fragment容器FrameLayout,和直接引用的自定义Fragment、ListFragment,我们分别进行操作示例。

1、在activity的java中操作Fragment

包括向容器中添加fragment(add),查找fragment(findFragmentById、findFragmentByTag),fragment的隐藏(hide),显示(show)、删除(remove),替换容器中的fragment(replace),fragment入栈(addToBackStack),事务提交动画(setTransition),事务提交(commit),事务立即执行(executePendingTransactions)。

 public void fragmentmanagerfun(){         FragmentManager fragmentmanager=getFragmentManager();  //每个activity都包含一个Fragment Manager来管理它所包含的Fragment         FragmentTransaction fragmentTransaction =fragmentmanager.beginTransaction();  //         //添加fragment         fragmentTransaction.add(R.id.activity_fragment_container, Fragment1.newInstance("这是第1个fragment"),"tag1");  //将fragment的实例添加到容器view中(若fragment没有UI,则不需要容器),同时可以为fragment添加tag名称         fragmentTransaction.add(R.id.activity_fragment_container, new Fragment1(),"tag2");  //一个FrameLayout可以添加多层fragment         fragmentTransaction.add(new Fragment1(),"tag3");  //可以添加没有ui的fragment         fragmentTransaction.commit();   //保存修改,一个fragmentTransaction只能使用一次commit,方法并不会立即执行事务         fragmentmanager.executePendingTransactions();  //立即执行上面的事务。         FragmentTransaction fragmentTransaction1 =fragmentmanager.beginTransaction();   //使用保存后,需要重新创建一个才能再次使用保存         //查询fragment,获取引用         Fragment fragment1=fragmentmanager.findFragmentById(R.id.activity_fragment_item);  //只能查找布局文件中的fragment         Fragment fragment2=fragmentmanager.findFragmentByTag("tag2");  //通过tag查找java文件中添加的fragment,没保存前无法找到         //判断是否被添加到了容器中         if(fragment2.isAdded())         {             //隐藏当前的Fragment,仅仅是设为不可见,并不会销毁             fragmentTransaction1.hide(fragment2);             //显示之前隐藏的Fragment             fragmentTransaction1.show(fragment2);             //删除fragment             fragmentTransaction1.remove(fragment2);  //去除fragment,跟add是相反操作(无法移除在xml中添加的)         }         //替换fragment         fragmentTransaction1.replace(R.id.activity_fragment_container, Fragment1.newInstance("这是第2个fragment"),"tag3");  //替换fragment,先remove容器下层的一个fragment,再加入一个fragment,同时可以为fragment添加tag名称         String tag=null;         fragmentTransaction1.addToBackStack(tag);  //在提交前将当前fragment视图保存到由宿主 Activity管辖的后退栈中(通过点击back按钮更换的视图)         //调用 addOnBackStackChangedListener() 方法注册监听器,用于监听后退栈的变化。         fragmentTransaction1.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);  //使事务变化动起来,使用系统过渡动画         fragmentTransaction1.setCustomAnimations(R.animator.anim1, R.animator.anim1);  //使用自定义动画,前者应用到添加的fragment中,后者应用到删除的fragment中         fragmentTransaction1.commit();   //保存修改,只能使用一次commit     }

2、在父activity的java中操作ListFragment(设置更改ListFragment的绑定数据)

 private ArrayAdapter<String> aa=null; private ArrayList<String> items = new ArrayList<String>(); //在activity中设置listfragment的数据 public void listfragmentfun()  {        FragmentManager fragmentmanager=getFragmentManager();         Fragment_list fragment_list=(Fragment_list)fragmentmanager.findFragmentById(R.id.activity_fragment_list);        items.clear();        for (int i = 0; i < 5; i++) {            items.add("新选项" + i);        }        aa=new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,items);        fragment_list.setListAdapter(aa);}

Fragment的生命周期

这里写图片描述

可以看到Fragment比Activity多了几个额外的生命周期回调方法:

onAttach(Activity)
当Fragment与Activity发生关联时调用。

onCreateView(LayoutInflater, ViewGroup,Bundle)
创建该Fragment的视图

onActivityCreated(Bundle)
当Activity的onCreate方法返回时调用

onDestoryView()
与onCreateView想对应,当该Fragment的视图被移除时调用

onDetach()
与onAttach相对应,当Fragment与Activity关联被取消时调用

注意:除了onCreateView,其他的所有方法如果你重写了,必须调用父类对于该方法的实现,

通过自定义fragment文件Fragment1 .java来实现fragment的全部生命周期函数

import com.lp.app.R;  import android.app.Activity;import android.app.Fragment;import android.content.Context;import android.os.Bundle;import android.util.Log;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.TextView;public class Fragment1 extends Fragment{       Context context;   //指向父activity      //activity在构造时向fragment传递参数。不使用构造函数,使用为activity重新创建,下属fragment的字段会丢失,bundle会保留      private static final String ARG = "arg";      public static Fragment1 newInstance(String arg)      {          Fragment1 fragment = new Fragment1();          Bundle bundle = new Bundle();          bundle.putString(ARG, arg);          fragment.setArguments(bundle);  //在fragment内通过getArguments读取参数          return fragment;       }      //在fragment内部调用获取参数      public String getArg()      {          String arg = "这是一个fragment";  //默认参数值          if(getArguments()!=null)              arg = getArguments().getString(ARG);          return arg;      }      //调用该方法时Fragment会被连接到它的父activity上      @Override      public void onAttach(Activity activity) {        super.onAttach(activity);        Log.v("frament生命周期", "fragment连接到activity");      }      //调用该方法来进行Fragment的初始创建      @Override      public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        context = getActivity();   //获得对父activity的引用        //初始化fragment        Log.v("frament生命周期", "fragment初始化");      }      //一但Fragment已被创建,要创建它自己的用户界面时调用该方法。填充UI,获取控件引用,设置函数,创建service和timer。没有界面时不需要此函数      //可以直接控制fragment中的控件,并可以调用接口函数,实现调用父activity中函数      @Override      public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {            //创建或者填充Fragment的UI,并返回它,如果这个Fragment没有UI,那么返回null            View view = inflater.inflate(R.layout.mylinearlayout, container, false);            final TextView myTextView = (TextView)view.findViewById(R.id.mylinearlayout_text1);            myTextView.setText(getArg());  //设置控件属性,或事件函数,这里读取了存储在fragment中的参数            Log.v("frament生命周期", "fragment创建UI");            return view;      }      //一旦父activity和Fragment的UI已被创建,则调用该方法      @Override      public void onActivityCreated(Bundle savedInstanceState) {          super.onActivityCreated(savedInstanceState);          //完成Fragment的初始化,尤其是那些父activity被初始化完成后或者Fragment的view被完全填充后才能做的事情          Log.v("frament生命周期", "fragment的ui已创建");      }      // 在可见生命周期的开始时被调用      @Override      public void onStart(){          super.onStart();          // 应用所有需要的UI变化,现在Fragment是可见的          Log.v("frament生命周期", "fragment可见周期开始");      }      //在活动生命周期开始时被调用      @Override      public void onResume(){          super.onResume();          //恢复所有暂停的Fragment需要的UI更新,线程或进程,但在非活动状态它是暂停的          Log.v("frament生命周期", "fragment活动周期恢复");      }      // 在活动生命周期结束时被调用      @Override      public void onPause(){        // 当activity不是活动的前台activity时,需要暂停UI的更新、挂起线程或者暂停那些不需要更新的CPU的集中处理。由于调用这个方法后,进程可能被终止,所以要保存所有的编辑和状态改变信息          super.onPause();          Log.v("frament生命周期", "fragment活动周期暂停");      }      //在活动生命周期结束时,调用该方法保存UI的状态变化      @Override      public void onSaveInstanceState(Bundle savedInstanceState) {          // 将UI的状态改变信息保存在savedInstanceState中          //这个Bundle会被传递到oncreate、oncreateview和onactivitycreate(如果它的父activity被终止并且重新启动)方法中          super.onSaveInstanceState(savedInstanceState);          Log.v("frament生命周期", "fragment保存ui");      }      //在可见生命周期结束时调用该方法      @Override      public void onStop(){        // 当fragment不可见时,暂停其余的UI更新、挂起线程或暂停不再需要的处理          super.onStop();          Log.v("frament生命周期", "fragment可见周期结束");      }      // 当fragment的view被分离时,调用该方法      @Override      public void onDestroyView() {        //清除资源相关view          super.onDestroyView();          Log.v("frament生命周期", "fragment中view分离");      }      //在整个生命周期结束时调用该方法      @Override      public void onDestroy(){        // 清除所有的资源,包括结束线程和关闭数据库连接等          super.onDestroy();          Log.v("frament生命周期", "fragment结束");      }      // 当fragment从它的父activity上分离时,调用该方法      @Override      public void onDetach() {          super.onDetach();          Log.v("frament生命周期", "fragment脱离activity");      }}

自定义fragment的布局文件使用一个简单的ViewGroup文件mylinearlayout.xml来实现。

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  android:layout_width="fill_parent"  android:layout_height="fill_parent"  android:orientation="vertical" >  <TextView    android:id="@+id/mylinearlayout_text1"    android:layout_width="fill_parent"    android:layout_height="wrap_content"    android:text="一个linearlayout中的textview" /></LinearLayout>

ListFragment的生命周期

在自定义的ListFragment中,我们主要需要注意的是onCreate启动函数、onCreateView布局UI函数、onListItemClick选项点击函数。

使用自定义ListFragment文件Fragment_list.java实现基本的函数

import com.lp.app.R; import android.app.ListFragment;import android.content.Context;import android.os.Bundle;import android.util.Log;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.ArrayAdapter;import android.widget.ListView;public class Fragment_list extends ListFragment{        Context context;  //指向父activity     Interface1 interface1;   //使用接口实现fragment和activity之间共享事件    private ArrayAdapter<String> adapter;      //可以在ListFragment内绑定数据源(也可以在activity中为ListFragment绑定数据源)      @Override      public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        context = getActivity();   //获得对父activity的引用        //获取对父Activity的引用,进而获取父activity中的函数(接口)和变量,        interface1 = (Interface1)context;        //定义一个数组        List<String> data = new ArrayList<String>();        for (int i = 0; i < 30; i++) {              data.add("listfragment选项" + i);        }        //将数组加到ArrayAdapter当中        adapter = new ArrayAdapter<String>(context,R.layout.mytextview, data);  //使用一个系统布局,当做list每个项的布局        //绑定适配器时,必须通过ListFragment.setListAdapter()接口,而不是ListView.setAdapter()或其它方法        setListAdapter(adapter);        Log.v("ListFragment", "listfragment启动绑定数据源");      }      //创建或者填充Fragment的UI,并返回它,如果这个Fragment没有UI,那么返回null      @Override      public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {            View view = inflater.inflate(R.layout.fragment_list, container, false);            Log.v("ListFragment", "listfragment布局整体UI");            return view;      }      //列表每一项的点击事件      @Override      public void onListItemClick(ListView listview, View v, int position, long id) {          super.onListItemClick(listview, v, position, id);          interface1.callback("点击了选项"+String.valueOf(position));   //通过接口调用activity中函数          Log.v("ListFragment", "点击了选项"+String.valueOf(position));      }}

自定义ListFragment的布局文件要使用一个包含listview的ViewGroup来实现。

这里使用fragment_list.xml来实现

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  android:layout_width="fill_parent"  android:layout_height="fill_parent"  android:orientation="vertical" >  <ListView          android:id="@+id/android:list"          android:layout_width="fill_parent"          android:layout_height="wrap_content"     />  </LinearLayout>

自定义ListFragment文件中的listview的每一项的布局文件,可以选用自定义的view或ViewGroup或系统自带的布局文件(android.R.layout.simple_list_item_1)。

这里使用仅有一个textview的布局文件mytextview.xml来实现

<?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android"   android:layout_width="fill_parent"   android:layout_height="wrap_content"   android:text="一个textview"   android:id="@+id/mytext1"/>

构建fragment时传递参数。

一般在创建对象时,赋予参数,使用构造函数,但是在fragment创建时,我们一般使用Bundle存储数据。是因为activity重新创建,下属fragment的字段会丢失,但是bundle数据会保留。

所以在自定义fragment中使用以下代码创建构造fragment,并读取fragment绑定的参数

private static final String ARG = "arg";      public static Fragment1 newInstance(String arg)      {          Fragment1 fragment = new Fragment1();          Bundle bundle = new Bundle();          bundle.putString(ARG, arg);          fragment.setArguments(bundle);  //在fragment内通过getArguments读取参数          return fragment;       }      //获取fragment绑定的参数      public String getArg()      {          String arg = "这是一个fragment";  //默认参数值          if(getArguments()!=null)              arg = getArguments().getString(ARG);          return arg;      }

在activity中可以使用下面两种方式构建自定义的fragment

Fragment1 fragmenttemp1 =Fragment1.newInstance("这是第1个fragment");   //构建一个绑定了参数的fragmentFragment1 fragmenttemp2 =new Fragment1(); //构建一个没有绑定参数的fragment

activity与fragment的相互引用

在activity中可以使用findFragmentById、findFragmentByTag获取对子fragment的引用

Fragment fragment1=getFragmentManager().findFragmentById(R.id.activity_fragment_item);  //只能查找布局文件中的fragmentFragment fragment2=getFragmentManager().findFragmentByTag("tag2");  //通过tag查找java文件中添加的fragment,没保存前无法找到

在fragment中可以通过getActivity获得对父activity的引用。

Context context;   //指向父activity//调用该方法时Fragment会被连接到它的父activity上 @Override public void onAttach(Activity activity) {       super.onAttach(activity);       context = getActivity();   //获得对父activity的引用       Log.v("frament生命周期", "fragment连接到activity"); }

fragment向activity传递数据

一个activity下往往包含多个fragment,多个fragment以及activity之间需要相互共享数据,一个有效的实现方法,是在fragment定义声明接口,并调用这个接口函数,而在activity中实现这个接口函数。

1、首先你要自定义一个接口文件。这里设置一个简单的接口Interface1.java

//在fragment中声明接口,调用接口函数,在activity中定义接口函数public interface Interface1{    public void callback(Object object);   //声明接口函数}

2、在自定义fragment中定义一个接口变量

Interface1 interface1;   //使用接口实现fragment和activity之间共享事件@Overridepublic void onCreate(Bundle savedInstanceState) {      super.onCreate(savedInstanceState);      context = getActivity();   //获得对父activity的引用      //获取对父Activity的引用,进而获取父activity中的函数(接口)和变量,      interface1 = (Interface1)context;}

3、在这个fragment中边可以调用接口函数。也就是向activity传递数据

 public void returndata(Object object) {      interface1.callback(object);   //通过接口 }

4、在activity中实现这个接口,并接受fragment传递的数据

public class Activity_fragment extends Activity implements Interface1{       //activity和fragment之间的事件共享,通过接口,activity接收fragment传来的数据,以便在自身或其他fragment中应用    @Override    public void callback(Object object) {        Log.v("fragment的主窗口", object.toString());        //控制UI或调用其他fragment中的函数    }}
原创粉丝点击