Android----Fragments详解
Fragments 概念是在Android3.0版本就已经有了,3.0版本是Tab(平板)专用,后来在4.0以上的版本继续沿
用Fragments,改善了Activity的灵活性。
在没有Fragments之前,一个屏幕就只能放一个Activity,有了Fragments之后,一个屏幕也只能放一个Anticity,但Activity里可以包含多个Fragments,Fragments因此也被成为子Activity,但是Fragments不是Activity的subClass,Fragments直属Object子类。
下面例子一个Activity包含两个Fragments 左边一个现实Title 右边一个现实相应的content。
Fragments 必须寄生在Activity里面,不能脱离Activity而存在,与Activity一样,Fragments同样具有自己的生命周期,其生命周期比Activity更复杂,但是Fragments的生命周期受Activity影响,随着Activity结束而结束。
1.onAttach(Activity) 在Fragments和Activity关联时候回调,可以进行一些限制条件的判定。
2. onCreate(Bundle) 和Activity一样
3. onCreateView(LayoutInflater, ViewGroup, Bundle) View在这里初始化,并返回给Fragments
4. onActivityCreated(Bundle) 在Activity.onCreate().也就是Activity初始化后,会会掉Fragments这个函数
5. onStart()
6. onResume()
1. onPause()
2. onStop()
4. onDestroy()
5. onDetach()
Demo示例:
主Activity
package com.example.fragmenttest; import com.example.fragmenttest.FragmentTitle.OnTtileClickListener; import android.os.Bundle; import android.app.Activity; import android.app.FragmentTransaction; import android.database.sqlite.SQLiteDatabase; import android.view.Menu; /** * 主Activity * @author ccf * */ public class MainActivity extends Activity implements OnTtileClickListener { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Override public void onTtitleClick(String content) { FragmentContent content2 = FragmentContent.getInstance(content); getFragmentManager().beginTransaction() .replace(R.id.mContent, content2).commit(); } @Override public void onBackPressed() { // TODO Auto-generated method stub super.onBackPressed(); } }
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" > <fragment class="com.example.fragmenttest.FragmentTitle" android:id="@+id/titleList" android:layout_width="0dip" android:layout_height="fill_parent" android:layout_weight="1" /> <FrameLayout android:id="@+id/mContent" android:layout_width="0dip" android:layout_height="fill_parent" android:layout_weight="2" /> </LinearLayout>
fragment 只是一个占位符,class属性,标志该占位符代表哪个Fragments.
FrameLayout 作为父容器,放用来置Fragments。
FragmentTitle Activity左边的Title列表,继承了ListFragment。 ,ListFragment持有一个ListView
package com.example.fragmenttest; import android.annotation.SuppressLint; import android.app.FragmentTransaction; import android.app.ListFragment; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.ListView; @SuppressLint("NewApi") public class FragmentTitle extends ListFragment { private final static String title[] = { "龙骑士", "死灵骑士", "死神来了", "第一滴血" }; private final static String content[] = { " 曾经和平富饶的国度阿拉盖西亚,如今陷在邪恶国王(约翰·马尔科维奇 John Malkovich 饰)的暴政统治下,期待神灵解救敢怒不敢言的人民。一日,农家少年伊拉贡(艾德·斯皮尔斯 Ed Speleers 饰)在林中拾获一枚奇石,不想竟是一枚龙卵,孵出一只蓝色飞龙。伊拉贡为小龙取名“萨菲拉”,遇到先知布鲁姆(杰瑞米·艾恩斯 Jeremy Irons 饰)后,才明白这是一场怎样的机缘——曾经守护这片土地的龙骑士应该回来了,带领人民找回自由。在布鲁姆的指导下,伊拉贡开始学习剑术和驭龙技巧,慢慢从一个普通少年成长为担当重任的龙骑士,前路危险重重,前路通向光明…… ", "莫罗(伊德瑞斯·艾尔巴 Idris Elba 饰)请求布雷斯把小孩丹尼带来神殿以避免恶魔夺取他的灵魂,作为回报他将驱除布雷斯身上的诅咒。丹尼是魔鬼罗尔科的儿子,罗尔科为了把自己的魔力植入儿子体内正派卡里跟追踪逃跑途中的母子两人。正当母子俩被困在采石场的时候,布雷斯到来,他体内的天使爆发了出来,压制住了卡里根。他变成了恶灵骑士,毫不手软的把对手撕成碎片。当战争结束时,三人前往神殿,同时,罗尔科也救醒了死亡边缘的卡里根,并赋予他更可怕的摧毁力,让他再去把丹尼找回来。 在神殿里,莫罗履行协议把布雷斯体内的扎萨罗斯驱赶了出来。但正当他做法时,神殿的牧师试图杀死丹尼——他认为丹尼就是恶魔。还没等他们行动,卡里根就到了。把丹尼带去见了", "某公司组织一次远游,虽然员工们各怀心事,不过他们还是踏上了欢乐的旅途。在经过一座巨大的吊桥时,年轻人山姆(Nicholas D'Agosto 饰)突然看到幻象,幻象中大桥开始垮塌,包括他、同事、朋友在内无数人在这起事故中遇难。当他从幻象中醒来时,周边的种种迹象表明那场灾难即将到来。慌乱之中,他和朱莉(艾玛·贝尔 Emma Bell 饰)、皮特(Miles Fisher 饰)、坎蒂丝(Ellen Wroe 饰)、奥利维亚(Jacqueline MacInnes Wood 饰)等8个人下了车。灾难随即发生,山姆等人成为车上仅有的幸存者。 但是命运并未偏袒这几名幸运儿,死神仍时刻逡巡在他们的周围。死神来了,无论逃到天涯海角也没有用…", " 退伍军人兰博(西尔维斯特•史泰龙Sylvester Stallone 饰)从越南回国,他回到已显得陌生的原居小镇,当地警长(布莱恩•丹内利 Brian Dennehy 饰)看到这个退伍军人的第一眼起,就开始对兰博百般挑剔,甚至将他带回警局肆意侮辱,不堪忍受责打的兰博袭警之后逃跑。警长召集大批警察展开对兰博的追捕,兰博逃至荒山野林之中,不断用自己在越战中掌握的游击战术对警察展开反击,他了一辆武器运输车返回小镇烧毁了商店,法律和武器都不能阻止兰博了。兰博在越战时的长官上校(理查德•克里纳 Richard Crenna 饰)出现,劝说兰博放下枪械,愤懑已久的兰博吼出了自己的困惑与不甘…… " }; @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); getListView().setBackgroundColor( getResources().getColor(android.R.color.darker_gray)); setListAdapter(new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, title)); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return super.onCreateView(inflater, container, savedInstanceState); } @Override public void onListItemClick(ListView l, View v, int position, long id) { // TODO Auto-generated method stub super.onListItemClick(l, v, position, id); OnTtileClickListener listener = (OnTtileClickListener) (getActivity()); listener.onTtitleClick(content[position]); } @Override public void onPause() { super.onPause(); } public interface OnTtileClickListener { public void onTtitleClick(String content); } }
FragmentContent是右边详细内容显示区域。
package com.example.fragmenttest; import android.annotation.SuppressLint; import android.app.Fragment; import android.app.ListFragment; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ListView; import android.widget.ScrollView; import android.widget.TextView; @SuppressLint("NewApi") public class FragmentContent extends Fragment { private String strContent; public static FragmentContent getInstance(String strContent) { FragmentContent content = new FragmentContent(); content.strContent = strContent; return content; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { super.onCreateView(inflater, container, savedInstanceState); ScrollView scrollView = new ScrollView(getActivity()); TextView mTextView = new TextView(getActivity()); mTextView.setPadding(5, 5, 5, 5); mTextView.setTextSize(15); mTextView.setText(strContent); scrollView.addView(mTextView); scrollView.setBackgroundColor(getResources().getColor(android.R.color.holo_blue_light)); return scrollView; } @Override public void onPause() { // TODO Auto-generated method stub super.onPause(); } }
MainActivity类很简单。 onCreate(Bundle savedInstanceState)函数只是简单调用setContentView().,加上实现了FragmentTitle 中自定义的 OnTitleClickListener接口外,并未做什么其他初始化,FragmentTitle的初始化是在他自己的 onActivityCreated(Bundle savedInstanceState) 中进行的。
当Activity 调用onCreate()后,就会调用FragmentTitle onActivityCreated(Bundle savedInstanceState) 来完成左边标题列表的初始化。
@Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); getListView().setBackgroundColor( getResources().getColor(android.R.color.darker_gray));//设置背景颜色 setListAdapter(new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, title));//调用该方法初始化列表 }
mainActivity 实现FragmentTitle 中自定义的 OnTitleClickListener 接口,FragmentTitle就可以可以在
onListItemClick(ListView l, View v, int position, long id)
@Override public void onTitleClick(String content) { FragmentContent content2 = FragmentContent.getInstance(content); getFragmentManager().beginTransaction() .replace(R.id.mContent, content2).commit(); }
@Override public void onListItemClick(ListView l, View v, int position, long id) { // TODO Auto-generated method stub super.onListItemClick(l, v, position, id); OnTitleClickListener listener = (OnTitleClickListener) (getActivity()); listener.onTitleClick(content[position]); }
如何对Activity中的Fragment进行操作呢?
在onTitleClick(String content)回调函数中,调用getFragmentManager()函数,获取FragmentManager实例,再通过FragmentManager 的beginTransaction()函数获得FragmentTransaction实例。
利用FragmentTransaction实例 就可以对Fragments实例进行操作,有以下几个基本操作
add() 把Fragments实例和Activity关联起来
hide() 把Activity中存在的Fragments影藏起来,对应盈利个函数show() 把已经被影藏的Fragments显示出来
remove() 把Activity中的Fragments移除掉。
replace() 用指定Fragments的替换另一个Fragments 相当于remove()+add()
commit() 以上操作并需经过commit() 条件该transaction(事务)后才生效。
当
Fragments和Activity之间的通讯:
1.在Activity中可以通过FragmentManager 两个方式获取到相应的Fragments
findFragmentById(int id) 通过xml布局文件中注册的id获取该实例,这种Fragments必须在布局文件正声明其id
findFragmentByTag(String tag) 通过tag找到实例 ,tag是改Fragments实例在被 FragmentTransaction#add(int containerViewId, Fragment fragment, String tag) 作为最后一个参数传入,tag要保持其唯一性,因为他是对应Fragments实例的唯一标识。
2. Fragments中可以通过getActivity()获取到对应的Activity实例