【转】 Pro Android学习笔记(三九):Fragment(4):基础小例子-续
Step 3:实现简介显示类DetailFragment
在Activity的布局xml中,对DetailFragment并没有指定class属性,故在setContentView()中不会自动调用该类,而是通过编写showDetail(int index)来调用,该函数的具体编码以后在描述,我们先来看看DetailFragment类的实现。
创建实例
在TitleFragment中,通过在xml中指定class属性来调用fragment。而对于右边部分,则是定义了FrameLayout容器,因此需要通过代码来创建实例。下面是通用的建议代码,通过静态函数来创建实例,并设置参数。当fragment被保存并重构时,系统回调用缺省的构造函数,并接着重新获取初始化参数。
public class DetailFragment extends Fragment{
//以静态函数的方式,通过指定书名序号,来获取实例,并将书名序号通过setArguments()方式设为给fragment的参数
public static DetailFragment newInstance (int index){
//1、创建fragment实例
DetailFragment df = new DetailFragment();
//2、设置fragment的参数,在fragment中可以通过getArguments()来获取
Bundle args = new Bundle();
args.putInt("index", index);
df.setArguments(args);
return df;
}
//通过bundle方式携带书名序号,来获取实例
public static DetailFragment newInstance (Bundle bundle){
int index = bundle.getInt("index");
return newInstance(index);
}
… 略 …
}
可以通过setArguments()来设置参数,对于fragment的生命周期而言,必须在fragment完成与activity关联之前设置参数。即必须在onAttach(之前进行,即在构造阶段或者onInflate。不是每个fragment都有onInflate状态,例如DetailFragment,不是通过xml的<fragment>进行构造,故没有onInflate状态。
编写所需的生命周期代码
实际上并不需要对每个生命周期都进行代码编写。由于在xml中没有指定class,不是activity中通过setContentView()来调用,因此没有经历onInflate()状态,而是从onAttach()开始。我们需要的是为fragment创建view布局,并具体填入信息,可以在onCreateView()和onActivityCreated()中实现。
public class DetailFragment extends Fragment{
private int mIndex = 0;
... 略 …
@Override //在生命周期的早期onCreate(),获取参数(书名序号)
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mIndex = getArguments().getInt("index",0); //在创建实例过程中将index设置为参数,可以在任何生命周期中获取,此处只为了使用方面进行提取。为何我们不直接newInstance()中将mIndex=index,而是设置成为参数,我们需要考虑到fragment recreate的情况,例如屏幕转向。此时,系统将调用缺省的构造函数,不会执行newInstance()代码,但在onCreate()我们仍可从参数中获取index。
}
public int getShowIndex(){
return mIndex;
}
@Override //在onCreateView中创建view层级,并返回。LayoutInflater可用于inflate布局。如果ViewGroup非空,则可以通过infalte()来获取布局,如果为null,说明没有viewGroup容器可以关联,在此所设置的,不会在UI中真正显示。
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
if(container == null)
return null;
//1、根据xml的布局文件创建view层级并将之返回。注意:第3个参数为false,不要将view和viewGroup进行关联,系统会自动进行,否则会出现异常。
View v = inflater.inflate(R.layout.details, container,false);
//2、设置层级中的view
TextView tv = (TextView)v.findViewById(R.id.text1);
tv.setText(BooksInfo.DIALOGUE[mIndex]);
return v;
}
}
在onCreateView中,返回的是View hierarchy,这和参数ViewGroup contianer是什么关系。其实这两者都是容器。一个表示fragment所占的空间的parent容器,就是XML文件中的FrameLayout;一个表示填充这个空间的child容器,图示如下:

这个用于填充FrameLayout的子容器布局很简单,下面为details.xml文件。注意,我们并不需要在代码中将子容器放入FrameLayout中,系统会自动完成,如果我们将两者关联,反而会出现异常。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout …. >
<ScrollView android:id="@+id/scroller" android:layout_width… >
<TextView android:id="@+id/text1" android:layout_width… />
</ScrollView>
</LinearLayout>
Step 4:实现showDetail(int index),如何管理fragment
fragment的切换
右边的fragment在用户点击不同书目时进行切换。一个fragment必须在某个view容器中,即onCreateView中的ViewGroup。在XML中,我们设置了FrameLayout作为fragment的容器,因为FrameLayout比其他的简单。在容器中可以进行fragment的切换。通过FragmentTranscation可以替换当前UI。FragmentTransaction是Fragment操作的API接口集合。相关代码如下:
public class FragmentBasicTest extends Activity{
... 略 …
public void showDetails(int index){
//【1】、获取当前与FrameLayout相关的fragment的对象。对fragment进行处理需要通过fragment管理器,FragmentManager可以通过 Activity的getFragmentManager()和Fragment的getFragmentManager()来获取,通过管理器,可以获得fragement transaction,根据id,tag获取fragment。
DetailFragment detail = (DetailFragment)getFragmentManager().findFragmentById(R.id.details);
//【2】、如果fragment对象不存在(第一次创建)或者书目变更,将进行切换
if(detail == null || detail.getShowIndex() != index ){
// 2.1)创建先的fragemnt对象
detail = DetailFragment.newInstance(index);
// 2.2)beginTransaction()有点词不达意,并不是说要获取第一个Transaction,Transaction没有分第几个,它是进行Fragment操作的API接口集合。beginTransaction()是说明要通过Fragment管理器对fragment进行编辑,编辑完后通过commit()进行确认。
FragmentTransaction ft = getFragmentManager().beginTransaction();
// 编辑的内容是replace():在FrameLayout中替换现有的UI。具体为replace(int containerId, Fragment fragment<, String tag>); tag是fragment的可选属性,不设置即为null。
ft.replace(R.id.details, detail);
ft.commit();
}
}
}
到此,我们已经完成了对fragment的基础小例子。
回退堆栈back stack
我们点击返回键,将退出activity。但是有时我们会希望,右边的fragment能退回到上一次点击的书目简介。在编写相关代码之前,我们跟踪一下小例子目前右边fragment的生命周期。

利用FragmentTrasaction,将新的fragment对象加入back stack中,当用户按回退键时,从back stack中pop出fragment对象,实现回退效果。back stack由fragment管理器管理,代码如下:
public void showDetails(int index){
DetailFragment detail = (DetailFragment)getFragmentManager().findFragmentById(R.id.details);
if(detail == null){
addFirstFragment(index);
}else if(detail.getShowIndex() != index ){
addFragmentToStack(index);
}
}
private void addFirstFragment(int index){
DetailFragment detail = DetailFragment.newInstance(index);
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.details, detail);
ft.commit();
}
private void addFragmentToStack(int index){
DetailFragment detail = DetailFragment.newInstance(index);
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.details, detail);
ft.addToBackStack(null); //加入回退堆栈,将原有(准备被替换)的fragment加入堆栈。经过跟踪,貌似也将新的fragment进行保存,但是并不会进行回退显示,回退时进行Destroy,除非下一次,作为原有fragment加入堆栈。(这里的说法有些罗嗦和含混,如果我们考虑每次到加入回退堆栈可以处理,但是如果某次加入,某次不加入,跟踪状态,就很清楚)
ft.commit();
}
我们同样跟踪一下现在小例子的运行情况。

如果我们不区分是否第一次,均使用addFragmentToStack,即在第一次,也执行ft.addToBackStack(null)。将原有的(准备被替换)的fragment加入堆栈,即将null加入堆栈,在回退时,最后增加回退一步,回退到一个空白的fragment,非吾等所期。
按返回键,fragment回退,仍然在同一个activity中,直至回退堆栈为空。
本博文涉及的例子代码,可以在Pro Android学习:Fragment中下载。
相关链接: 我的Android开发相关文章
【转】 Pro Android学习笔记(三九):Fragment(4):基础小例子-续的更多相关文章
- 【转】 Pro Android学习笔记(四二):Fragment(7):切换效果
目录(?)[-] 利用setTransition 利用setCustomAnimations 通过ObjectAnimator自定义动态效果 程序代码的编写 利用fragment transactio ...
- 【转】 Pro Android学习笔记(四十):Fragment(5):适应不同屏幕或排版
目录(?)[-] 设置横排和竖排的不同排版风格 改写代码 对于fragment,经常涉及不同屏幕尺寸和不同的排版风格.我们在基础小例子上做一下改动,在横排的时候,仍是现实左右两个fragment,在竖 ...
- 【转】 Pro Android学习笔记(五六):配置变化
目录(?)[-] Activity的destorycreate过程 Fragment的destorycreate过程 onSaveInstanceState saveFragmentInstanceS ...
- Pro Android学习笔记 ActionBar(1):Home图标区
Pro Android学习笔记(四八):ActionBar(1):Home图标区 2013年03月10日 ⁄ 综合 ⁄ 共 3256字 ⁄ 字号 小 中 大 ⁄ 评论关闭 ActionBar在A ...
- 【转】 Pro Android学习笔记(八二):了解Package(1):包和进程
文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://blog.csdn.net/flowingflying/ 在之前,我们已经学习了如何签发apk,见P ...
- 【转】 Pro Android学习笔记(六七):HTTP服务(1):HTTP GET
目录(?)[-] HTTP GET小例子 简单小例子 出现异常NetworkOnMainThreadException 通过StrictMode进行处理 URL带键值对 Andriod应用可利用ser ...
- 【转】 Pro Android学习笔记(五五):调试和分析(3):adb命令、模拟器控制台和StrictMode
目录(?)[-] adb命令 模拟器Console StrictMode adb命令 我们在学习SQLite的使用,介绍过部分adb命令的使用,见Pro Android学习笔记(五):了解Conten ...
- 【转】 Pro Android学习笔记(五二):ActionBar(5):list模式
可以在action bar中加入spinner的下来菜单,有关spinner,可以参考Pro Android学习笔记(二十):用户界面和控制(8):GridView和Spinner. list的样式和 ...
- 【转】 Pro Android学习笔记(三五):Menu(6):XML方式 & PopUp菜单
目录(?)[-] 利用XML创建菜单 XML的有关属性 onClick事件 Pop-up菜单 利用XML创建菜单 在代码中对每个菜单项进行设置,繁琐且修改不灵活,不能适配多国语言的要求,可以利用资源进 ...
随机推荐
- python字典中包含列表时:查找字典中某个元素及赋值
直接上代码: 运行效果:
- saltStack 证书管理
SaltStack 使用 SSL 签证的方式进行安全认证,我们可以在 Master 端看到 Minion 端的整数签证请求 1.查看当前证书签证情况 [root@SaltStack-Master ~] ...
- centos 安装 jdk PostgreSQL
1.下载: anzhuang jDK http://blog.csdn.net/youzhouliu/article/details/51183115 ----------------------- ...
- 4G U盘版64位bitcoin专用挖矿操作系统
这个操作系统是基于linux的操作系统,采用的ubuntu平台打造,所有的软件都已经安装齐备,是一个bitcoin专用挖矿操作系统,是64位的,对于显卡数量基本上没有限制,前提是你的主板支持足够多的显 ...
- php函数指定默认值的方法
发布:JB02 来源:脚本学堂 [大 中 小] 本文介绍下,在php编程中,指定函数的默认值的方法,分享二个例子,供大家学习参考下.本文转自:http://www.jbxue.com/ar ...
- JavaWeb:前端开发基础
JavaWeb:前端开发基础 内联元素和块级元素 说明: 联元素和块级元素都是html中的范畴,块元素和内联元素的主要差异是块元素是从新的一行开始.而内联元素一般显示在一行上.但是可以通过css的di ...
- rails 注释
view -# js.erb <%# xxxx %> 单行注释
- PAT 天梯赛 L2-007. 家庭房产 【并查集】
题目链接 https://www.patest.cn/contests/gplt/L2-007 思路 将一个家庭里的所有人都并进去 然后最后查找的时候 找到所有同一个家庭的人,计算出人数,人均房产套数 ...
- 每天一个Linux命令(23)chmod命令
chmod命令用来变更文件或目录的权限. 在UNIX系统家族里,文件或目录权限的控制分别以读取.写入.执行3种一般权限来区分,另有3种特殊权限可供运用.用户可以使用chmod指令去变更文件与目 ...
- 事件监听机制——鼠标事件MouseEvent
鼠标事件 鼠标事件包括鼠标的双击.左击.右击.中间键等等,本文进行事件加载进行简单介绍,具体可以参考键盘事件. import java.awt.*; import java.awt.event.*; ...