Fragment 和 FragmentActivity的使用
2014-10-16 10:18
246 查看
今天学习下 Android中的 Fragment 和 FragmentActivity,因为没有4.0手机,平台是2.3.3 所以我是使用 v4 support 包来进行学习。
要想用Fragment 功能必须先让activity继承FragmentActivity,其原因是里面包含了Fragment运作的FragmentManager接口的实现类 FragmentManagerImpl ,由这个类管理所有Fragment的显示、隐藏。
1.使用最简单的Fragment,我们只要继承Fragment就可以。
[java]
view plaincopy
public class TextFragment extends Fragment{
private String mMsg;
public void setMessage(String message){
this.mMsg = message;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
final Context context = getActivity();
FrameLayout root = new FrameLayout(context);
root.setBackgroundColor(Color.YELLOW);
TextView tv = new TextView(context);
tv.setText(mMsg);
tv.setGravity(Gravity.CENTER);
root.addView(tv, new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT));
return root;
}
}
首先Fragment 就可以把它当作一个view , 只不过这个view 与 activity一样有了生命周期函数。
Fragment.onCreateView() 函数就是用于生成这个Fragment布局的view的,类似baseadapter.getView(),这样一个包含一个TextView的简单布局就完成了。
2.重写我们自己的FragmentActivity.
这里面主要要通过FragmentManager 来进行Fragment的添加和删除:
[java]
view plaincopy
public class DoorFragmentActivity extends FragmentActivity{
public static final String FRAG_SMS = "sms_list_frag";
public static final String FRAG_TEXT = "text_frag";
private Fragment mSMSFragment;
private Fragment mTextFragment;
private FragmentManager mFragMgr;
private Button mMenuBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.door_fragment_activity_layout);
mFragMgr = getSupportFragmentManager();
mMenuBtn = (Button) findViewById(R.id.door_menu_btn);
mMenuBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
showFragments(FRAG_TEXT, true);
}
});
mMenuBtn.setOnLongClickListener(new OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
// TODO Auto-generated method stub
return false;
}
});
initFragments();
showFragments(FRAG_SMS, false);
}
private void initFragments(){
mSMSFragment = new SMSListFragment();
TextFragment textfrag = new TextFragment();
textfrag.setMessage("这是 菜单界面");
mTextFragment = textfrag;
}
private void showFragments(String tag, boolean needback){
FragmentTransaction trans = 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();
}
private Fragment getFragmentByTag(String tag){
if(FRAG_SMS.equals(tag)){
return mSMSFragment;
}
if(FRAG_TEXT.equals(tag)){
return mTextFragment;
}
return null;
}
}
首先我们获取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:
[java]
view plaincopy
public class SMSListFragment extends ListFragment{
private ConversationListAdapter mAdapter;
private ConversationQuery mQuery;
private long startTime;
@Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
mAdapter = new ConversationListAdapter(getActivity());
mQuery = new ConversationQuery(getActivity().getContentResolver());
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
setListAdapter(mAdapter);
}
@Override
public void onStart() {
// TODO Auto-generated method stub
super.onStart();
startAsyncQuery();
}
@Override
public void onStop() {
// TODO Auto-generated method stub
super.onStop();
mAdapter.getCursor().close();
mAdapter.changeCursor(null);
}
public void startAsyncQuery() {
startTime = System.currentTimeMillis();
mQuery.startQuery(1, null, Conversation.sAllThreadsUri,
Conversation.ALL_THREADS_PROJECTION, null, null,
Conversation.CONVERSATION_ORDER);
}
private final class ConversationQuery extends AsyncQueryHandler {
public ConversationQuery(ContentResolver cr) {
super(cr);
// TODO Auto-generated constructor stub
}
@Override
protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
// TODO Auto-generated method stub
System.out.println("conversation cursor size : "
+ 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.主页面的布局文件:
[html]
view plaincopy
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns: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继承FragmentActivity,其原因是里面包含了Fragment运作的FragmentManager接口的实现类 FragmentManagerImpl ,由这个类管理所有Fragment的显示、隐藏。
1.使用最简单的Fragment,我们只要继承Fragment就可以。
[java]
view plaincopy
public class TextFragment extends Fragment{
private String mMsg;
public void setMessage(String message){
this.mMsg = message;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
final Context context = getActivity();
FrameLayout root = new FrameLayout(context);
root.setBackgroundColor(Color.YELLOW);
TextView tv = new TextView(context);
tv.setText(mMsg);
tv.setGravity(Gravity.CENTER);
root.addView(tv, new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT));
return root;
}
}
首先Fragment 就可以把它当作一个view , 只不过这个view 与 activity一样有了生命周期函数。
Fragment.onCreateView() 函数就是用于生成这个Fragment布局的view的,类似baseadapter.getView(),这样一个包含一个TextView的简单布局就完成了。
2.重写我们自己的FragmentActivity.
这里面主要要通过FragmentManager 来进行Fragment的添加和删除:
[java]
view plaincopy
public class DoorFragmentActivity extends FragmentActivity{
public static final String FRAG_SMS = "sms_list_frag";
public static final String FRAG_TEXT = "text_frag";
private Fragment mSMSFragment;
private Fragment mTextFragment;
private FragmentManager mFragMgr;
private Button mMenuBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.door_fragment_activity_layout);
mFragMgr = getSupportFragmentManager();
mMenuBtn = (Button) findViewById(R.id.door_menu_btn);
mMenuBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
showFragments(FRAG_TEXT, true);
}
});
mMenuBtn.setOnLongClickListener(new OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
// TODO Auto-generated method stub
return false;
}
});
initFragments();
showFragments(FRAG_SMS, false);
}
private void initFragments(){
mSMSFragment = new SMSListFragment();
TextFragment textfrag = new TextFragment();
textfrag.setMessage("这是 菜单界面");
mTextFragment = textfrag;
}
private void showFragments(String tag, boolean needback){
FragmentTransaction trans = 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();
}
private Fragment getFragmentByTag(String tag){
if(FRAG_SMS.equals(tag)){
return mSMSFragment;
}
if(FRAG_TEXT.equals(tag)){
return mTextFragment;
}
return null;
}
}
首先我们获取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:
[java]
view plaincopy
public class SMSListFragment extends ListFragment{
private ConversationListAdapter mAdapter;
private ConversationQuery mQuery;
private long startTime;
@Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
mAdapter = new ConversationListAdapter(getActivity());
mQuery = new ConversationQuery(getActivity().getContentResolver());
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
setListAdapter(mAdapter);
}
@Override
public void onStart() {
// TODO Auto-generated method stub
super.onStart();
startAsyncQuery();
}
@Override
public void onStop() {
// TODO Auto-generated method stub
super.onStop();
mAdapter.getCursor().close();
mAdapter.changeCursor(null);
}
public void startAsyncQuery() {
startTime = System.currentTimeMillis();
mQuery.startQuery(1, null, Conversation.sAllThreadsUri,
Conversation.ALL_THREADS_PROJECTION, null, null,
Conversation.CONVERSATION_ORDER);
}
private final class ConversationQuery extends AsyncQueryHandler {
public ConversationQuery(ContentResolver cr) {
super(cr);
// TODO Auto-generated constructor stub
}
@Override
protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
// TODO Auto-generated method stub
System.out.println("conversation cursor size : "
+ 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.主页面的布局文件:
[html]
view plaincopy
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns: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.运行效果图:
相关文章推荐
- Android开发:使用Fragment改造TabActivity
- (转自红黑联盟)Android开发:使用Fragment改造TabActivity
- 在使用fragment的activity双击点击退出程序
- 深入分析:Fragment与Activity交互的几种方式(三,使用接口)
- 深入分析:Fragment与Activity交互的几种方式(二,使用Bundle)
- 【android】使用TabHost+Fragment(替换TabActivity,LocalActivityManager等deprecation类)
- Android应用开发:LoaderManager在Activity/Fragment中的使用分析
- 使用ViewPager+Fragment来实现带滚动条的多屏滑动-IndicatorFragmentActivity
- Android开发:使用Fragment改造TabActivity
- Android Activity中嵌套多个Fragment的使用
- Fragment 和 FragmentActivity的使用
- android中使用fragment时出现如下错误 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.fra
- 关于Loader,activity,Fragment之间的一个使用
- 使用ViewPager+Fragment来实现带滚动条的多屏滑动-IndicatorFragmentActivity
- FragmentActivity和Activity的区别及何时使用两者
- 如何使用Fragment建立TabActivity之一
- 使用ViewPager+Fragment来实现带滚动条的多屏滑动-IndicatorFragmentActivity
- 使用ViewPager+Fragment来实现带滚动条的多屏滑动-IndicatorFragmentActivity
- 深入分析:Fragment与Activity交互的几种方式(一,使用Handler)
- android基础内容介绍(XXXDrawable、Android动画、Android资源使用、Fragment与Activity)