Android Fragment 基本了解(图文介绍)
程序员文章站
2023-12-14 08:23:16
fragment android是在android 3.0 (api level 11)开始引入fragment的。 可以把fragment想成activity中的模块,这...
fragment
android是在android 3.0 (api level 11)开始引入fragment的。
可以把fragment想成activity中的模块,这个模块有自己的布局,有自己的生命周期,单独处理自己的输入,在activity运行的时候可以加载或者移除fragment模块。
可以把fragment设计成可以在多个activity中复用的模块。
当开发的应用程序同时适用于平板电脑和手机时,可以利用fragment实现灵活的布局,改善用户体验。
如图:
fragment的生命周期
因为fragment必须嵌入在acitivity中使用,所以fragment的生命周期和它所在的activity是密切相关的。
如果activity是暂停状态,其中所有的fragment都是暂停状态;如果activity是stopped状态,这个activity中所有的fragment都不能被启动;如果activity被销毁,那么它其中的所有fragment都会被销毁。
但是,当activity在活动状态,可以独立控制fragment的状态,比如加上或者移除fragment。
当这样进行fragment transaction(转换)的时候,可以把fragment放入activity的back stack中,这样用户就可以进行返回操作。
fragment的使用相关
使用fragment时,需要继承fragment或者fragment的子类(dialogfragment, listfragment, preferencefragment, webviewfragment),所以fragment的代码看起来和activity的类似。
使用support library
support library是一个提供了api库函数的jar文件,这样就可以在旧版本的android上使用一些新版本的apis。
比如android-support-v4.jar.它的完整路径是:
<sdk>/extras/android/support/v4/android-support-v4.jar.
它就提供了fragment的apis,使得在android 1.6 (api level 4)以上的系统都可以使用fragment。
为了确定没有在旧版本系统上使用新版本的apis,需要如下导入语句:
import android.support.v4.app.fragment;
import android.support.v4.app.fragmentmanager;
同时应该将上述的包拷入libs项目下的libs文件夹,然后在项目的properties中添加:右键单击项目,选properties,左边选java build path,然后add external jars…,添加android-support-v4.jar.
当创建包含fragment的activity时,如果用的是support library,那么继承的就应该是fragmentactivity而不是activity。
必须实现的三个回调函数
oncreate()
系统在创建fragment的时候调用这个方法,这里应该初始化相关的组件,一些即便是被暂停或者被停止时依然需要保留的东西。
oncreateview()
当第一次绘制fragment的ui时系统调用这个方法,必须返回一个view,如果fragment不提供ui也可以返回null。
注意,如果继承自listfragment,oncreateview()默认的实现会返回一个listview,所以不用自己实现。
onpause()
当用户离开fragment时第一个调用这个方法,需要提交一些变化,因为用户很可能不再返回来。
实现fragment的ui
提供fragment的ui,必须实现oncreateview()方法。
假设fragment的布局设置写在example_fragment.xml资源文件中,那么oncreateview()方法可以如下写:
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);
}
}
oncreateview()中container参数代表该fragment在activity中的父控件;savedinstancestate提供了上一个实例的数据。
inflate()方法的三个参数:
第一个是resource id,指明了当前的fragment对应的资源文件;
第二个参数是父容器控件;
第三个布尔值参数表明是否连接该布局和其父容器控件,在这里的情况设置为false,因为系统已经插入了这个布局到父控件,设置为true将会产生多余的一个view group。
把fragment加入activity
当fragment被加入activity中时,它会处在对应的view group中。
fragment有两种加载方式:一种是在activity的layout中使用标签<fragment>声明;另一种方法是在代码中把它加入到一个指定的viewgroup中。
另外,fragment它可以并不是activity布局中的任何一部分,它可以是一个不可见的部分。这部分内容先略过。
加载方式1:通过activity的布局文件将fragment加入activity
在activity的布局文件中,将fragment作为一个子标签加入即可。
如:
<?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的完整类名。
当系统创建这个activity的布局文件时,系统会实例化每一个fragment,并且调用它们的oncreateview()方法,来获得相应fragment的布局,并将返回值插入fragment标签所在的地方。
有三种方法为fragment提供id:
android:id属性:唯一的id
android:tag属性:唯一的字符串
如果上面两个都没提供,系统使用容器view的id。
加载方式2:通过编程的方式将fragment加入到一个viewgroup中
当activity处于running状态下的时候,可以在activity的布局中动态地加入fragment,只需要指定加入这个fragment的父view group即可。
首先,需要一个fragmenttransaction实例:
fragmentmanager fragmentmanager = getfragmentmanager()
fragmenttransaction fragmenttransaction = fragmentmanager.begintransaction();(注,如果import android.support.v4.app.fragmentmanager;那么使用的是:fragmentmanager fragmentmanager = getsupportfragmentmanager();)
之后,用add()方法加上fragment的对象:
examplefragment fragment = new examplefragment();
fragmenttransaction.add(r.id.fragment_container, fragment);
fragmenttransaction.commit();
其中第一个参数是这个fragment的容器,即父控件组。
最后需要调用commit()方法使得fragmenttransaction实例的改变生效。
实例
练习的例子:
写一个类继承自fragment类,并且写好其布局文件(本例中是两个textview),在fragment类的oncreateview()方法中加入该布局。
之后用两种方法在activity中加入这个fragment:
第一种是在activity的布局文件中加入<fragment>标签;
第二种是在activity的代码中使用fragmenttransaction的add()方法加入fragment。
贴出代码:
自己定义的fragment类:
examplefragment.java
package com.example.learningfragment;
import android.os.bundle;
import android.support.v4.app.fragment;
import android.view.layoutinflater;
import android.view.view;
import android.view.viewgroup;
public class examplefragment extends fragment
{
//三个一般必须重载的方法
@override
public void oncreate(bundle savedinstancestate)
{
// todo auto-generated method stub
super.oncreate(savedinstancestate);
system.out.println("examplefragment--oncreate");
}
@override
public view oncreateview(layoutinflater inflater, viewgroup container,
bundle savedinstancestate)
{
system.out.println("examplefragment--oncreateview");
return inflater.inflate(r.layout.example_fragment_layout, container, false);
}
@override
public void onpause()
{
// todo auto-generated method stub
super.onpause();
system.out.println("examplefragment--onpause");
}
@override
public void onresume()
{
// todo auto-generated method stub
super.onresume();
system.out.println("examplefragment--onresume");
}
@override
public void onstop()
{
// todo auto-generated method stub
super.onstop();
system.out.println("examplefragment--onstop");
}
}
fragment的布局文件:
example_fragment_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<textview
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/num1"
/>
<textview
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/num2"
/>
</linearlayout>
主activity:
learnfragment.java
package com.example.learningfragment;
import android.os.bundle;
import android.support.v4.app.fragmentactivity;
import android.support.v4.app.fragmentmanager;
import android.support.v4.app.fragmenttransaction;
public class learnfragment extends fragmentactivity
{
@override
public void oncreate(bundle savedinstancestate)
{
super.oncreate(savedinstancestate);
setcontentview(r.layout.activity_learn_fragment);
//在程序中加入fragment
fragmentmanager fragmentmanager = getsupportfragmentmanager();
fragmenttransaction fragmenttransaction = fragmentmanager.begintransaction();
examplefragment fragment = new examplefragment();
fragmenttransaction.add(r.id.linear, fragment);
fragmenttransaction.commit();
}
}
activity的布局文件:
activity_learn_fragment.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"
>
<button
android:id="@+id/btn1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/btn1"
/>
<fragment
android:name="com.example.learningfragment.examplefragment"
android:id="@+id/fragment1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<button
android:id="@+id/btn2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/btn2"
/>
<linearlayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/linear"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<button
android:id="@+id/btn3"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/btn3"
/>
</linearlayout>
</linearlayout>
运行结果如下:
可以看到第二种方式加入fragment的时候,指定了父容器(一个线性布局)的id,其中已经有一个button 3,所以fragment加在其后。
参考资源
fragment类文档:
http://developer.android.com/reference/android/app/fragment.html
training:building a dynamic ui with fragments
http://developer.android.com/training/basics/fragments/index.html
fragments develop guide:
http://developer.android.com/guide/components/fragments.html
android是在android 3.0 (api level 11)开始引入fragment的。
可以把fragment想成activity中的模块,这个模块有自己的布局,有自己的生命周期,单独处理自己的输入,在activity运行的时候可以加载或者移除fragment模块。
可以把fragment设计成可以在多个activity中复用的模块。
当开发的应用程序同时适用于平板电脑和手机时,可以利用fragment实现灵活的布局,改善用户体验。
如图:
fragment的生命周期
因为fragment必须嵌入在acitivity中使用,所以fragment的生命周期和它所在的activity是密切相关的。
如果activity是暂停状态,其中所有的fragment都是暂停状态;如果activity是stopped状态,这个activity中所有的fragment都不能被启动;如果activity被销毁,那么它其中的所有fragment都会被销毁。
但是,当activity在活动状态,可以独立控制fragment的状态,比如加上或者移除fragment。
当这样进行fragment transaction(转换)的时候,可以把fragment放入activity的back stack中,这样用户就可以进行返回操作。
fragment的使用相关
使用fragment时,需要继承fragment或者fragment的子类(dialogfragment, listfragment, preferencefragment, webviewfragment),所以fragment的代码看起来和activity的类似。
使用support library
support library是一个提供了api库函数的jar文件,这样就可以在旧版本的android上使用一些新版本的apis。
比如android-support-v4.jar.它的完整路径是:
<sdk>/extras/android/support/v4/android-support-v4.jar.
它就提供了fragment的apis,使得在android 1.6 (api level 4)以上的系统都可以使用fragment。
为了确定没有在旧版本系统上使用新版本的apis,需要如下导入语句:
复制代码 代码如下:
import android.support.v4.app.fragment;
import android.support.v4.app.fragmentmanager;
同时应该将上述的包拷入libs项目下的libs文件夹,然后在项目的properties中添加:右键单击项目,选properties,左边选java build path,然后add external jars…,添加android-support-v4.jar.
当创建包含fragment的activity时,如果用的是support library,那么继承的就应该是fragmentactivity而不是activity。
必须实现的三个回调函数
oncreate()
系统在创建fragment的时候调用这个方法,这里应该初始化相关的组件,一些即便是被暂停或者被停止时依然需要保留的东西。
oncreateview()
当第一次绘制fragment的ui时系统调用这个方法,必须返回一个view,如果fragment不提供ui也可以返回null。
注意,如果继承自listfragment,oncreateview()默认的实现会返回一个listview,所以不用自己实现。
onpause()
当用户离开fragment时第一个调用这个方法,需要提交一些变化,因为用户很可能不再返回来。
实现fragment的ui
提供fragment的ui,必须实现oncreateview()方法。
假设fragment的布局设置写在example_fragment.xml资源文件中,那么oncreateview()方法可以如下写:
复制代码 代码如下:
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);
}
}
oncreateview()中container参数代表该fragment在activity中的父控件;savedinstancestate提供了上一个实例的数据。
inflate()方法的三个参数:
第一个是resource id,指明了当前的fragment对应的资源文件;
第二个参数是父容器控件;
第三个布尔值参数表明是否连接该布局和其父容器控件,在这里的情况设置为false,因为系统已经插入了这个布局到父控件,设置为true将会产生多余的一个view group。
把fragment加入activity
当fragment被加入activity中时,它会处在对应的view group中。
fragment有两种加载方式:一种是在activity的layout中使用标签<fragment>声明;另一种方法是在代码中把它加入到一个指定的viewgroup中。
另外,fragment它可以并不是activity布局中的任何一部分,它可以是一个不可见的部分。这部分内容先略过。
加载方式1:通过activity的布局文件将fragment加入activity
在activity的布局文件中,将fragment作为一个子标签加入即可。
如:
复制代码 代码如下:
<?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的完整类名。
当系统创建这个activity的布局文件时,系统会实例化每一个fragment,并且调用它们的oncreateview()方法,来获得相应fragment的布局,并将返回值插入fragment标签所在的地方。
有三种方法为fragment提供id:
android:id属性:唯一的id
android:tag属性:唯一的字符串
如果上面两个都没提供,系统使用容器view的id。
加载方式2:通过编程的方式将fragment加入到一个viewgroup中
当activity处于running状态下的时候,可以在activity的布局中动态地加入fragment,只需要指定加入这个fragment的父view group即可。
首先,需要一个fragmenttransaction实例:
fragmentmanager fragmentmanager = getfragmentmanager()
fragmenttransaction fragmenttransaction = fragmentmanager.begintransaction();(注,如果import android.support.v4.app.fragmentmanager;那么使用的是:fragmentmanager fragmentmanager = getsupportfragmentmanager();)
之后,用add()方法加上fragment的对象:
examplefragment fragment = new examplefragment();
fragmenttransaction.add(r.id.fragment_container, fragment);
fragmenttransaction.commit();
其中第一个参数是这个fragment的容器,即父控件组。
最后需要调用commit()方法使得fragmenttransaction实例的改变生效。
实例
练习的例子:
写一个类继承自fragment类,并且写好其布局文件(本例中是两个textview),在fragment类的oncreateview()方法中加入该布局。
之后用两种方法在activity中加入这个fragment:
第一种是在activity的布局文件中加入<fragment>标签;
第二种是在activity的代码中使用fragmenttransaction的add()方法加入fragment。
贴出代码:
自己定义的fragment类:
复制代码 代码如下:
examplefragment.java
package com.example.learningfragment;
import android.os.bundle;
import android.support.v4.app.fragment;
import android.view.layoutinflater;
import android.view.view;
import android.view.viewgroup;
public class examplefragment extends fragment
{
//三个一般必须重载的方法
@override
public void oncreate(bundle savedinstancestate)
{
// todo auto-generated method stub
super.oncreate(savedinstancestate);
system.out.println("examplefragment--oncreate");
}
@override
public view oncreateview(layoutinflater inflater, viewgroup container,
bundle savedinstancestate)
{
system.out.println("examplefragment--oncreateview");
return inflater.inflate(r.layout.example_fragment_layout, container, false);
}
@override
public void onpause()
{
// todo auto-generated method stub
super.onpause();
system.out.println("examplefragment--onpause");
}
@override
public void onresume()
{
// todo auto-generated method stub
super.onresume();
system.out.println("examplefragment--onresume");
}
@override
public void onstop()
{
// todo auto-generated method stub
super.onstop();
system.out.println("examplefragment--onstop");
}
}
fragment的布局文件:
复制代码 代码如下:
example_fragment_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<textview
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/num1"
/>
<textview
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/num2"
/>
</linearlayout>
主activity:
复制代码 代码如下:
learnfragment.java
package com.example.learningfragment;
import android.os.bundle;
import android.support.v4.app.fragmentactivity;
import android.support.v4.app.fragmentmanager;
import android.support.v4.app.fragmenttransaction;
public class learnfragment extends fragmentactivity
{
@override
public void oncreate(bundle savedinstancestate)
{
super.oncreate(savedinstancestate);
setcontentview(r.layout.activity_learn_fragment);
//在程序中加入fragment
fragmentmanager fragmentmanager = getsupportfragmentmanager();
fragmenttransaction fragmenttransaction = fragmentmanager.begintransaction();
examplefragment fragment = new examplefragment();
fragmenttransaction.add(r.id.linear, fragment);
fragmenttransaction.commit();
}
}
activity的布局文件:
复制代码 代码如下:
activity_learn_fragment.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"
>
<button
android:id="@+id/btn1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/btn1"
/>
<fragment
android:name="com.example.learningfragment.examplefragment"
android:id="@+id/fragment1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<button
android:id="@+id/btn2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/btn2"
/>
<linearlayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/linear"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<button
android:id="@+id/btn3"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/btn3"
/>
</linearlayout>
</linearlayout>
运行结果如下:
可以看到第二种方式加入fragment的时候,指定了父容器(一个线性布局)的id,其中已经有一个button 3,所以fragment加在其后。
参考资源
fragment类文档:
http://developer.android.com/reference/android/app/fragment.html
training:building a dynamic ui with fragments
http://developer.android.com/training/basics/fragments/index.html
fragments develop guide:
http://developer.android.com/guide/components/fragments.html