今天学习下 Android中的 Fragment 和 FragmentActivity,因为没有4.0手机,平台是2.3.3 所以我是使用 v4 support 包来进行学习。
要想用Fragment 功能必须先让activity继承FragmentActivity,其原因是里面包含了Fragment运作的FragmentManager接口的实现类 FragmentManagerImpl ,由这个类管理所有Fragment的显示、隐藏
1.使用最简单的Fragment,我们只要继承Fragment就可以
-
publicclassTextFragmentextendsFragment{
-
-
privateStringmMsg;
-
-
publicvoidsetMessage(Stringmessage){
-
this.mMsg=message;
-
}
-
-
@Override
-
publicViewonCreateView(LayoutInflaterinflater,ViewGroupcontainer,
-
BundlesavedInstanceState){
-
-
finalContextcontext=getActivity();
-
FrameLayoutroot=newFrameLayout(context);
-
root.setBackgroundColor(Color.YELLOW);
-
TextViewtv=newTextView(context);
-
tv.setText(mMsg);
-
tv.setGravity(Gravity.CENTER);
-
root.addView(tv,newFrameLayout.LayoutParams(
-
ViewGroup.LayoutParams.FILL_PARENT,ViewGroup.LayoutParams.FILL_PARENT));
-
returnroot;
-
}
-
-
}
首先Fragment 就可以把它当作一个view , 只不过这个view 与 activity一样有了生命周期函数
Fragment.onCreateView() 函数就是用于生成这个Fragment布局的view的,类似baseadapter.getView()
这样一个包含一个TextView的简单布局就完成了。
2.重写我们自己的FragmentActivity.
这里面主要要通过FragmentManager 来进行Fragment的添加和删除:
-
publicclassDoorFragmentActivityextendsFragmentActivity{
-
-
publicstaticfinalStringFRAG_SMS="sms_list_frag";
-
publicstaticfinalStringFRAG_TEXT="text_frag";
-
-
privateFragmentmSMSFragment;
-
privateFragmentmTextFragment;
-
privateFragmentManagermFragMgr;
-
-
privateButtonmMenuBtn;
-
-
@Override
-
protectedvoidonCreate(BundlesavedInstanceState){
-
-
super.onCreate(savedInstanceState);
-
setContentView(R.layout.door_fragment_activity_layout);
-
mFragMgr=getSupportFragmentManager();
-
mMenuBtn=(Button)findViewById(R.id.door_menu_btn);
-
mMenuBtn.setOnClickListener(newOnClickListener(){
-
-
@Override
-
publicvoidonClick(Viewv){
-
-
showFragments(FRAG_TEXT,true);
-
}
-
});
-
mMenuBtn.setOnLongClickListener(newOnLongClickListener(){
-
-
@Override
-
publicbooleanonLongClick(Viewv){
-
-
-
returnfalse;
-
}
-
});
-
initFragments();
-
showFragments(FRAG_SMS,false);
-
}
-
-
privatevoidinitFragments(){
-
mSMSFragment=newSMSListFragment();
-
TextFragmenttextfrag=newTextFragment();
-
textfrag.setMessage("这是菜单界面");
-
mTextFragment=textfrag;
-
-
}
-
-
privatevoidshowFragments(Stringtag,booleanneedback){
-
FragmentTransactiontrans=mFragMgr.beginTransaction();
-
if(needback){
-
trans.setCustomAnimations(R.anim.frag_enter,
-
R.anim.frag_exit);
-
trans.add(R.id.door_root_content_fl,getFragmentByTag(tag),tag);
-
trans.addToBackStack(tag);
-
}else{
-
trans.replace(R.id.door_contents_fl,getFragmentByTag(tag),tag);
-
}
-
trans.commit();
-
}
-
-
privateFragmentgetFragmentByTag(Stringtag){
-
if(FRAG_SMS.equals(tag)){
-
returnmSMSFragment;
-
}
-
if(FRAG_TEXT.equals(tag)){
-
returnmTextFragment;
-
}
-
returnnull;
-
}
-
}
- 首先我们获取FragmentManager实现:直接调用 FragmentActivity.getSupportFragmentManager(),看源码可以知道这返回的是FragmentManager内部定义的实现类FragmentManagerImpl。
- 我们获取了FragmentManagerImpl后我们其实不咋操作这个类,只调用FragmentManager.beginTransation(),这个获取FragmentTransation接口的实现类(里面具体是BackStackRecord类的实例),我们关于Fragment的所有操作都是通过它来完成的,因为没仔细研究,我只了解直接自己在代码里面定义Fragment而没有在xml里面写(xml写觉得有点别扭)
我们主要通过 FragmentTransation的一些方法来处理Fragment的:
1)trans.add(fragment, tag); 这个实际是 containerViewId = 0 调用的3)
2)trans.add(containerViewId, fragment); 这个实际是 tag = null 调用的 3)
3)trans.add(containerViewId, fragment, tag); 如果containerViewId != 0实际上调用的是获取到
fragment的 onCreateView方法返回的view 并加入到containerViewId这个viewgroup中去即 viewgroup.addView(fragment.onCreateView());
未解决问题:containerViewId = 0 的时候代表什么??
4) trans.replace(containerViewId, fragment) 一样是null tag调用 5)
5)trans.replace(containerViewId, fragment, tag) 这个一样是添加一个fragment到对应的container中去,只不过比add多了一步对相同containerViewId中已有的fragment检索,进行removeFragment操作,再去添加这个新来的fragment
6) trans.addToBackStack(tag); 如果你的fragment对于back键有类似activity的回退响应,就要记得把它加入到里面去,trans里面模拟了栈,但是我的回退没有响应我设置的exit anim 这个无语还没解决
3.再使用下ListFragment,我这里写的是SMSListFragment继承了ListFragment:
-
publicclassSMSListFragmentextendsListFragment{
-
-
privateConversationListAdaptermAdapter;
-
privateConversationQuerymQuery;
-
privatelongstartTime;
-
-
@Override
-
publicvoidonCreate(BundlesavedInstanceState){
-
-
super.onCreate(savedInstanceState);
-
mAdapter=newConversationListAdapter(getActivity());
-
mQuery=newConversationQuery(getActivity().getContentResolver());
-
}
-
-
@Override
-
publicvoidonActivityCreated(BundlesavedInstanceState){
-
-
super.onActivityCreated(savedInstanceState);
-
setListAdapter(mAdapter);
-
}
-
-
@Override
-
publicvoidonStart(){
-
-
super.onStart();
-
startAsyncQuery();
-
}
-
-
@Override
-
publicvoidonStop(){
-
-
super.onStop();
-
mAdapter.getCursor().close();
-
mAdapter.changeCursor(null);
-
}
-
-
publicvoidstartAsyncQuery(){
-
startTime=System.currentTimeMillis();
-
mQuery.startQuery(1,null,Conversation.sAllThreadsUri,
-
Conversation.ALL_THREADS_PROJECTION,null,null,
-
Conversation.CONVERSATION_ORDER);
-
}
-
-
privatefinalclassConversationQueryextendsAsyncQueryHandler{
-
-
publicConversationQuery(ContentResolvercr){
-
super(cr);
-
-
}
-
-
@Override
-
protectedvoidonQueryComplete(inttoken,Objectcookie,Cursorcursor){
-
-
System.out.println("conversationcursorsize:"
-
+cursor.getCount());
-
mAdapter.changeCursor(cursor);
-
Toast.makeText(
-
getActivity(),
-
"查询短信会话个数:"+cursor.getCount()+",花费"
-
+(System.currentTimeMillis()-startTime)+"ms",
-
Toast.LENGTH_LONG).show();
-
}
-
-
}
-
-
}
代码中可以知道和使用普通的ListActivity完全没区别,
onCreate()中完成自己要一次性初始的东西,我在里面主要是初始化一个adapter和一个对sms数据库的查询
在onActivityCreated()中将adapter设置给listview,这个不确定有没有更好的位置,
然后进入我们熟悉的生命周期方法:
onStart()中,开启查询
onStop()中,我们界面已经不在显示了,所以我们不关心数据库变化了,close cursor
4.主页面的布局文件:
-
<?xmlversion="1.0"encoding="utf-8"?>
-
<FrameLayoutxmlns:android="http://schemas.android.com/apk/res/android"
-
android:id="@+id/door_root_content_fl"
-
android:layout_width="match_parent"
-
android:layout_height="match_parent">
-
-
<LinearLayout
-
android:layout_width="match_parent"
-
android:layout_height="match_parent"
-
android:orientation="vertical">
-
-
<FrameLayout
-
android:id="@+id/door_contents_fl"
-
android:layout_width="match_parent"
-
android:layout_height="0dp"
-
android:layout_weight="1"/>
-
-
<LinearLayout
-
android:layout_width="match_parent"
-
android:layout_height="55dp"
-
android:orientation="horizontal">
-
-
<Button
-
android:id="@+id/door_menu_btn"
-
android:layout_width="match_parent"
-
android:layout_height="match_parent"
-
android:gravity="center"
-
android:text="菜单"/>
-
</LinearLayout>
-
</LinearLayout>
-
-
</FrameLayout>
5.运行效果图:
分享到:
相关推荐
Fragment和Activity双向交互
fragment 与 fragment 通信 fragment 向 activity 传值 activity 向 fragment 传值 代码是自己手敲的
这里简单介绍了Fragment和Activity使用Handler方式进行交互。
FragmentActivity源码下载
Fragment和Activity交互,能改变彼此的UI和传递数据,经典,实用
Fragment和Activity通信以及Fragment之间通信的方式(二) http://blog.csdn.net/yalinfendou博客中有详细介绍……
Activity通知Fragment采用观察者模式,fragment之间通讯另建Function接口
activity与fragment的传递和fragment与Fragment的传递
这里简单介绍了如何使用接口,来使fragment发送消息给activity
问题解决:Fragment not attached to Activity的相关代码,更多详细内容请参考:http://blog.csdn.net/u012939909/article/details/53355836
Fragment和Activity交互(Handler方式),可互相改变彼此UI
Fragment使用方法的介绍,以及Fragment与Activity之间的通信。
Activity与Activity、Activity与Fragment、Fragment与Fragment的数据交互
Android 笔记-Fragment 与 Activity之间传递数据,使用setArgument方法的例子
这里简单描述了以下Activity使用Bundle向Fragment传递数据
在Activity如何改变Fragment的UI,如按返回键改变fragment里面textview的内容
笔者近期看官方training,发现了很多有用又好玩的知识。其中,fragment与Activity通信就是一个。 fragment与Activity通信主要是两...此点主要是通过fragment的getArgument()和setArgument()两个函数传递bundle来传递。
Android下的Activity和Fragment的生命周期,详细的说明了Activity的状态保存,并说明Activity在屏幕旋转等特定的情况下的生命周期的变化
笔者近期看官方training,发现了很多有用又好玩的知识。其中,fragment与Activity通信就是一个。 fragment与Activity通信主要是两...此点主要是通过fragment的getArgument()和setArgument()两个函数传递bundle来传递。
fragment之间的切换,fragment和activity之间的切换,