Fragment概述

Fragment是activity的界面中的一部分或一种行为。你可以把多个Fragment们组合到一个activity中来创建一个多面界面并且你可以在多个activity中重用一个Fragment。你可以把Fragment认为模块化的一段activity,它具有自己的生命周期,接收它自己的事件,并可以在activity运行时被添加或删除。

Fragment不能独立存在,它必须嵌入到activity中,而且Fragment的生命周期直接受所在的activity的影响。

设计哲学

Android从3.0开始引入fragment,主要是为了支持更动态更灵活的界面设计,比如在平板上的应用。平板机上拥有比手机更大的屏幕空间来组合和交互界面组件们。Fragment使你在做那样的设计时,不需应付view树中复杂的变化。通过把activity的layout分成fragment,你可以在activity运行时改变它的样子,并且可以在activity的后退栈中保存这些改变。

例如:写一个读新闻的程序,可以用一个fragment显示标题列表,另一个fragment显示选中标题的内容,这两个fragment都在一个activity上,并排显示。那么这两个fragment都有自己的生命周期并响应自己感兴趣的事件。于是,不需再像手机上那样用一个activity显示标题列表,用另一个activity显示新闻内容;现在可以把两者放在一个activity上同时显示出来。如下图:

创建Fragment

要创建fragment,必须从Fragment或Fragment的派生类派生出一个类。Fragment的代码写起来有些像activity。它具有跟activity一样的回调方法,比如 onCreate(),onStart(),onPause()和onStop()。实际上,如果你想把老的程序改为使用fragment,基本上只需要把activity的回调方法的代码移到fragment中对应的方法即可。

通常需要实现以上生命周期函数:

onCreate():

当创建fragment时系统调用此方法。在其中你必须初始化fragment的基础组件们。可参考activity的说明。

onCreateView():

 当第一次绘制Fragment的UI时系统调用这个方法,必须返回一个View,如果Fragment不提供UI也可以返回null。

  注意,如果继承自ListFragment,onCreateView()默认的实现会返回一个ListView,所以不用自己实现。

onPause():

当用户离开Fragment时第一个调用这个方法,需要提交一些变化,因为用户很可能不再返回来。

大多数程序应最少对fragment实现这三个方法。当然还有其它几个回调方法可应该按情况实现之。所有的生命周期回调函数在“操控fragment的生命周期”一节中有详细讨论。

下图为fragment的生命周期(它所在的activity处于运行状态)。

为fragment添加用户界面
 
  fragment一般作为activity的用户界面的一部分,把它自己的layout嵌入到activity的layout中。   有两种方法将一个fragment添加到activity中:

要为fragment提供layout,你必须实现onCreateView()回调方法,然后在这个方法中返回一个View对象,这个对象是fragment的layout的根。 

注:如果你的fragment是从ListFragment中派生的,就不需要实现onCreateView()方法了,因为默认的实现已经为你返回了ListView控件对象。
要从onCreateView()方法中返回layout对象,你可以从layoutxml中生成layout对象。为了帮助你这样做,onCreateView()提供了一个LayoutInflater对象。
举例:以下代码展示了一个Fragment的子类如何从layoutxml文件example_fragment.xml中生成对象。

publicstaticclassExampleFragmentextendsFragment{@OverridepublicViewonCreateView(LayoutInflaterinflater,ViewGroupcontainer,BundlesavedInstanceState){//Inflate the layout for this fragmentreturninflater.inflate(R.layout.example_fragment,container,false);}
} 

onCreateView()参数中的container是存放fragment的layout的ViewGroup对象。savedInstanceState参数是一个Bundle,跟activity的onCreate()中Bundle差不多,用于状态恢复。但是fragment的onCreate()中也有Bundle参数,所以此处的Bundle中存放的数据与onCreate()中存放的数据还是不同的。至于详细信息,请参考“操控fragment的生命周期”一节。

Inflate()方法有三个参数:

1.layout的资源ID。

2.存放fragment的layout的ViewGroup。

3.布尔型数据表示是否在创建fragment的layout期间,把layout附加到container上(在这个例子中,因为系统已经把layout插入到container中了,所以值为false,如果为true会导至在最终的layout中创建多余的ViewGroup(这句我看不明白,但我翻译的应该没错))。

现在你看到如何为fragment创建layout了,下面讲述如何把它添加到activity中。

把fragment添加到activity

一般情况下,fragment把它的layout作为activitiy的loyout的一部分合并到activity中,有两种方法将一个fragment添加到activity中:

方法一:在activity的layoutxml文件中声明fragment(静态使用Fragment)

如下代码,一个activity中包含两个fragment:

<?xmlversion="1.0"encoding="utf-8"?>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:orientation="horizontal"android:layout_width="match_parent"android:layout_height="match_parent"><fragmentandroid:name="com.example.news.ArticleListFragment"android:id="@+id/list"android:layout_weight="1"android:layout_width="0dp"android:layout_height="match_parent"/><fragmentandroid:name="com.example.news.ArticleReaderFragment"android:id="@+id/viewer"android:layout_weight="2"android:layout_width="0dp"android:layout_height="match_parent"/>
</LinearLayout> 

<fragment>中声明一个fragment。

其中android:name属性填上你自己创建的fragment的完整类名。

当系统创建上例中的layout时,它实例化每一个fragment,然后调用它们的onCreateView()方法,以获取每个fragment的layout。系统把fragment返回的view对象插入到<fragment>元素的位置,直接代替<fragment>元素。

注:每个fragment都需要提供一个ID,系统在activity重新创建时用它来恢复fragment们,你也可以用它来操作fragment进行其它的事物,比如删除它。有三种方法给fragment提供ID:

1 为android:id属性赋一个数字。

2 为android:tag属性赋一个字符串。

3如果你没有使用上述任何一种方法,系统将使用fragment的容器的ID。

方法二:在代码中添加fragment到一个ViewGroup  (动态的使用Fragment)

这种方法可以在运行时,把fragment添加到activity的layout中。你只需指定一个要包含fragment的ViewGroup。

为了完成fragment的事务(比如添加,删除,替换等),你必须使用FragmentTransaction的方法。你可以从activity获取到FragmentTransaction,如下:

   FragmentManager fragmentManager =getFragmentManager()FragmentTransaction fragmentTransaction =fragmentManager.beginTransaction();

然后你可以用add()方法添加一个fragment,它有参数用于指定容纳fragment的ViewGroup。如下:

    ExampleFragmentfragment = new ExampleFragment();fragmentTransaction.add(R.id.fragment_container,fragment);fragmentTransaction.commit(); 

Add()的第一个参数是容器ViewGroup,第二个是要添加的fragment。一旦你通过FragmentTransaction对fragment做出了改变,你必须调用方法commit()提交这些改变。

不仅在无界面的fragment中,在有界面的fragment中也可以使用tag来作为为一标志,这样在需要获取fragment对象时,要调用findFragmentTag()。

fragment实例:

  写一个类继承自Fragment类,并且写好其布局文件,在Fragment类的onCreateView()方法中加入该布局。

  之后用两种方法在Activity中加入这个fragment:

第一种是在Activity的布局文件中加入<fragment>标签:

自己定义的fragment类:

import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;/*** Created by jcli on 2015/11/27.*/
public class TestFragment extends Fragment {@Overridepublic void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);System.out.println("TestFragment--onCreate");}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState){System.out.println("TestFragment--onCreateView");return inflater.inflate(R.layout.fragment_test, container, false);}@Overridepublic void onPause(){super.onPause();System.out.println("TestFragment--onPause");}
}

Fragment 布局文件:

<FrameLayout 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"tools:context="com.jcdh.jcli.activitydemo.BlankFragment"><!-- TODO: Update blank fragment layout --><TextViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:textSize="30sp"android:gravity="center"android:text="我是一个 Fragment" /></FrameLayout>

加载Fragment的Activity:

public class MainActivity extends Activity {@Override
    protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

加载Fragment的Activity的布局:

<?xml version="1.0" encoding="utf-8"?>
<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"
    tools:context="com.jcdh.jcli.activitydemo.MainActivity">
 
    <fragment
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:name="com.jcdh.jcli.activitydemo.TestFragment"
        android:id="@+id/fragment"
   />
</RelativeLayout>

效果图片:

第二种在Activity的代码中使用FragmentTransaction的add()方法加入fragment(动态使用Fragment):

Actvity的布局文件,有两个按钮用来切换:

<?xml version="1.0" encoding="utf-8"?>
<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"tools:context="com.jcdh.jcli.myapplication.MainActivity"><Buttonandroid:id="@+id/first_btn"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentTop="true"android:onClick="moveToFragment"android:text="第一个Fragment" /><Buttonandroid:id="@+id/second_btn"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_toRightOf="@id/first_btn"android:onClick="moveToFragment"android:layout_alignParentTop="true"android:text="第二个Fragment" /><fragmentandroid:id="@+id/first_fragment"android:name="com.jcdh.jcli.myapplication.FirstFragment"android:layout_width="match_parent"android:layout_height="100dp"android:layout_below="@+id/first_btn"></fragment>
</RelativeLayout>

下面看一下集成fragment的Activity类

import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;public class MainActivity extends  Activity {private FirstFragment fristFragment;private SecondFragment secondFragment;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initView();}private void initView(){FragmentManager fm = this.getFragmentManager();android.app.FragmentTransaction transaction = fm.beginTransaction();fristFragment = new FirstFragment();transaction.replace(R.id.first_fragment, fristFragment);transaction.commit();}public void moveToFragment(View view){// 开启Fragment事务FragmentManager fm = getFragmentManager();FragmentTransaction transaction = fm.beginTransaction();switch (view.getId()){case R.id.first_btn:if(fristFragment !=fm.findFragmentByTag("fragmentTag")){// 使用当前Fragment的布局替代first_fragment的控件transaction.replace(R.id.first_fragment,fristFragment);}break;case R.id.second_btn:if(secondFragment==null){secondFragment = new SecondFragment();}if(secondFragment !=fm.findFragmentByTag("fragmentTag")){transaction.replace(R.id.first_fragment,secondFragment);}break;}transaction.commit();}
}

可以看到我们使用FragmentManager对Fragment进行了动态的加载,这里使用的是replace方法~~下一节我会详细介绍FragmentManager的常用API。

注:如果使用Android3.0以下的版本,需要引入v4的包,然后Activity继承FragmentActivity,然后通过getSupportFragmentManager获得FragmentManager。不过还是建议版Menifest文件的uses-sdk的minSdkVersion和targetSdkVersion都改为11以上,这样就不必引入v4包了。

代码中间还有两个Fragment的子类:

FirstFragment 代码:

import android.os.Bundle;
import android.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;public class FirstFragment extends Fragment {@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {// Inflate the layout for this fragmentreturn inflater.inflate(R.layout.fragment_first, container, false);}
}

布局:

<FrameLayout 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"tools:context="com.jcdh.jcli.myapplication.FirstFragment"><!-- TODO: Update blank fragment layout --><TextViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:textSize="20sp"android:gravity="center"android:background="@android:color/black"android:textColor="@android:color/white"android:text="我是第一个Fragment" /></FrameLayout>

SecondFragment代码:

import android.os.Bundle;
import android.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;public class SecondFragment extends Fragment {@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {// Inflate the layout for this fragmentreturn inflater.inflate(R.layout.fragment_second, container, false);}
}

布局:

<FrameLayout 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"
    tools:context="com.jcdh.jcli.myapplication.FirstFragment">

    <!-- TODO: Update blank fragment layout -->
    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:textSize="30sp"
        android:gravity="center"
        android:background="@android:color/darker_gray"
        android:text="我是第二个Fragment" />

</FrameLayout>

效果图片:

点击第二个按钮切换;

Fragment家族常用的API

Fragment常用的三个类:

android.app.Fragment 主要用于定义Fragment

android.app.FragmentManager 主要用于在Activity中操作Fragment

android.app.FragmentTransaction 保证一些列Fragment操作的原子性,熟悉事务这个词,一定能明白~

a、获取FragmentManage的方式:

getFragmentManager() // v4中,getSupportFragmentManager

b、主要的操作都是FragmentTransaction的方法

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()//提交一个事务

注意:常用Fragment的哥们,可能会经常遇到这样Activity状态不一致:State loss这样的错误。主要是因为:commit方法一定要在Activity.onSaveInstance()之前调用。

上述,基本是操作Fragment的所有的方式了,在一个事务开启到提交可以进行多个的添加、移除、替换等操作。

值得注意的是:如果你喜欢使用Fragment,一定要清楚这些方法,哪个会销毁视图,哪个会销毁实例,哪个仅仅只是隐藏,这样才能更好的使用它们。

见http://blog.csdn.net/q610098308/article/details/50098971

此文档参考了其它文档,现在也共享出来和大家分享,如有问题可以留言给我

转载于:https://www.cnblogs.com/sharecenter/p/5621025.html

Android 进阶 Fragment 介绍和使用 (一)相关推荐

  1. Android的Fragment介绍

    前言 fragment是从android3.0开始提出来的,用来支持大屏幕设备的ui设计.通过将activity划分为多个fragment,不仅提高了设计的灵活性,而且可以在程序运行时改变它们的特征, ...

  2. Android之Fragment的详细介绍和使用方法

    一.Fragment的基础知识介绍 1.1概述 1.1.1 特性 Fragment是activity的界面中的一部分或一种行为.可以把多个Fragment组合到一个activity中来创建一个多界面 ...

  3. Android复习系列④之《Android进阶》

    Android进阶 1 Okhttp OkHttpClient相当于配置中心, 所有的请求都会共享这些配置(例如出错是否重试.共享的连接池) . 1.OkHttpCLient中的配置主要有: Disp ...

  4. Android 进阶之路(我的博客文章目录)

    原文地址:http://blog.csdn.net/u011240877 为了方便读者阅读以及自己回顾,总结写过的文章和一些想要写的文章目录如下: #1.Java Java 解惑:Comparable ...

  5. 【26】Android - 初识Fragment

    目录 目录 前言 相关库包 简单使用 静态加载 动态添加 Fragment 与Activity 通讯 组件获取 消息传递 生命周期 基本状态 回调 测试 进阶使用 如何在 Fragment 中增加 M ...

  6. Android 进阶第一篇——善用工具

    笔者本身从事的是和系统相关性比较大的系统应用的开发,在这里我总结了一下自身的经验,将工作中经常用到的一些工具做了简要罗列,我之所以将其作为进阶第一篇,是因为工欲善其事必先利其器,只有善用工具才能提升效 ...

  7. android preference属性,Android进阶——Preference详解之Preference系的基本应用和管理(二)...

    并非我们第一次打开相应界面之后就会自动创建对应的SharedPreferences文件,而是在我们改变了原有状态时候喎�"/kf/ware/vc/" target="_b ...

  8. Android进阶之旅 - 项目实战篇

    ├─01.Android进阶之路与你同行 │      01.Android进阶之路与你同行-(内涵段子的项目介绍) │      02.Android进阶之路与你同行-(Android应用开发的三个 ...

  9. android碎片按钮,Android 碎片(Fragment)

    Android 碎片(Fragment) 碎片是活动的一部分,使得活动更加的模块化设计.我们可以认为碎片是一种子活动. 下面是关于碎片的重要知识点 - 碎片拥有自己的布局,自己的行为及自己的生命周期回 ...

最新文章

  1. 当前linux环境做出镜像,把当前ubuntu系统做成镜像
  2. tcpip测试工具软件,TCP Test Tool(TCP测试工具) V2.3 官方版
  3. oracle创建表语句_利用FME去拼接SQL语句并创建表
  4. java 打地鼠 源代码_Java实现的打地鼠小游戏完整示例【附源码下载】
  5. java 调用远程服务_java调用(请求)远程服务地址
  6. POJ 2135 Farm Tour (费用流)
  7. oracledatabase11gr2怎么打开_win10 安装oracle 11gR2_database(内附下载地址)
  8. 只有汇编能告诉你为什么
  9. 史上最全面,清晰的SharedPreferences解析
  10. 计算获取最小值和最大值
  11. Java实现视频网站的视频上传、视频转码、视频关键帧抽图, 及视频播放功能
  12. 【python】*与** 参数问题
  13. YIi 数据操作备注
  14. Kafka 0.10.1.1 特点
  15. UE4【C++】子弹伤害系统使用
  16. 号码卡JAVA算法---猜车牌号
  17. 计算机专业的学生怎样练习编程才能把编程学精通?
  18. android+设置运行内存大小,怎样增大安卓手机的虚拟运行内存RAM ,手机的ram太小....
  19. 通信原理_画出数字基带传输系统的基本系统框图,并说明数字序列如何转化为合适在信道中传输的波形
  20. 【博学谷学习记录】超强总结,用心分享 | 【Lunux】Manjaro手动升级icu依赖库安装MySQL以及Navicat

热门文章

  1. 敏捷测试2015新看点
  2. Android 混淆打包
  3. 实验8-SPSS交叉表分析
  4. SpringBoot 修改banner信息
  5. 吴恩达:现在很多所谓的AI公司,其实都不是AI公司
  6. 安全警报:Oracle 2018一月号安全补丁修复由来已久安全漏洞
  7. 操作系统级虚拟化概述
  8. 无法访问xxx指向的web服务器,请检查网络设置
  9. 转载-ubuntu搭建Git 服务器
  10. 一本通1655数三角形