Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 251|回复: 0

[默认分类] Fragment 和 FragmentActivity的使用

[复制链接]
  • TA的每日心情
    开心
    2021-12-13 21:45
  • 签到天数: 15 天

    [LV.4]偶尔看看III

    发表于 2018-5-28 11:50:23 | 显示全部楼层 |阅读模式


    今天学习下 Android中的 Fragment 和 FragmentActivity,因为没有4.0手机,平台是2.3.3 所以我是使用 v4 support 包来进行学习。
    要想用Fragment 功能必须先让activity继承FragmentActivity,其原因是里面包含了Fragment运作的FragmentManager接口的实现类 FragmentManagerImpl ,由这个类管理所有Fragment的显示、隐藏


    1.使用最简单的Fragment,我们只要继承Fragment就可以
      
    1. public class TextFragment extends Fragment{
    2.        
    3.         private String mMsg;
    4.        
    5.         public void setMessage(String message){
    6.                 this.mMsg = message;
    7.         }
    8.        
    9.         @Override
    10.         public View onCreateView(LayoutInflater inflater, ViewGroup container,
    11.                         Bundle savedInstanceState) {
    12.                 // TODO Auto-generated method stub
    13.                 final Context context = getActivity();
    14.                 FrameLayout root = new FrameLayout(context);
    15.                 root.setBackgroundColor(Color.YELLOW);
    16.                 TextView tv = new TextView(context);
    17.                 tv.setText(mMsg);
    18.                 tv.setGravity(Gravity.CENTER);
    19.                 root.addView(tv, new FrameLayout.LayoutParams(
    20.                 ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT));
    21.                 return root;
    22.         }
    23. }
    复制代码

    首先Fragment 就可以把它当作一个view , 只不过这个view 与 activity一样有了生命周期函数




      










































    Fragment.onCreateView() 函数就是用于生成这个Fragment布局的view的,类似baseadapter.getView()
    这样一个包含一个TextView的简单布局就完成了。
    2.重写我们自己的FragmentActivity.
    这里面主要要通过FragmentManager 来进行Fragment的添加和删除:
      
    1. public class DoorFragmentActivity extends FragmentActivity{
    2.         public static final String FRAG_SMS = "sms_list_frag";
    3.         public static final String FRAG_TEXT = "text_frag";
    4.        
    5.         private Fragment mSMSFragment;
    6.         private Fragment mTextFragment;
    7.         private FragmentManager mFragMgr;
    8.        
    9.         private Button mMenuBtn;
    10.        
    11.         @Override
    12.         protected void onCreate(Bundle savedInstanceState) {
    13.                 // TODO Auto-generated method stub
    14.                 super.onCreate(savedInstanceState);
    15.                 setContentView(R.layout.door_fragment_activity_layout);
    16.                 mFragMgr = getSupportFragmentManager();
    17.                 mMenuBtn = (Button) findViewById(R.id.door_menu_btn);
    18.                 mMenuBtn.setOnClickListener(new OnClickListener() {
    19.                        
    20.                         @Override
    21.                         public void onClick(View v) {
    22.                                 // TODO Auto-generated method stub
    23.                                 showFragments(FRAG_TEXT, true);
    24.                         }
    25.                 });
    26.                 mMenuBtn.setOnLongClickListener(new OnLongClickListener() {
    27.                        
    28.                         @Override
    29.                         public boolean onLongClick(View v) {
    30.                                 // TODO Auto-generated method stub
    31.                                
    32.                                 return false;
    33.                         }
    34.                 });
    35.                 initFragments();
    36.                 showFragments(FRAG_SMS, false);
    37.         }
    38.        
    39.         private void initFragments(){
    40.                 mSMSFragment = new SMSListFragment();
    41.                 TextFragment textfrag = new TextFragment();
    42.                 textfrag.setMessage("这是 菜单界面");
    43.                 mTextFragment = textfrag;
    44.                
    45.         }
    46.        
    47.         private void showFragments(String tag, boolean needback){
    48.                 FragmentTransaction trans = mFragMgr.beginTransaction();
    49.                 if(needback){
    50.                         trans.setCustomAnimations(R.anim.frag_enter,  
    51.                                         R.anim.frag_exit);
    52.                         trans.add(R.id.door_root_content_fl, getFragmentByTag(tag), tag);
    53.                         trans.addToBackStack(tag);
    54.                 }else{
    55.                         trans.replace(R.id.door_contents_fl, getFragmentByTag(tag), tag);
    56.                 }
    57.                 trans.commit();
    58.         }
    59.        
    60.         private Fragment getFragmentByTag(String tag){
    61.                 if(FRAG_SMS.equals(tag)){
    62.                         return mSMSFragment;
    63.                 }
    64.                 if(FRAG_TEXT.equals(tag)){
    65.                         return mTextFragment;
    66.                 }
    67.                 return null;
    68.         }
    69. }
    复制代码

      

      首先我们获取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:
      
    1. public class SMSListFragment extends ListFragment{
    2.        
    3.         private ConversationListAdapter mAdapter;
    4.         private ConversationQuery mQuery;
    5.         private long startTime;
    6.        
    7.         @Override
    8.         public void onCreate(Bundle savedInstanceState) {
    9.                 // TODO Auto-generated method stub
    10.                 super.onCreate(savedInstanceState);
    11.                 mAdapter = new ConversationListAdapter(getActivity());
    12.                 mQuery = new ConversationQuery(getActivity().getContentResolver());
    13.         }
    14.        
    15.         @Override
    16.         public void onActivityCreated(Bundle savedInstanceState) {
    17.                 // TODO Auto-generated method stub
    18.                 super.onActivityCreated(savedInstanceState);
    19.                 setListAdapter(mAdapter);
    20.         }
    21.        
    22.         @Override
    23.         public void onStart() {
    24.                 // TODO Auto-generated method stub
    25.                 super.onStart();
    26.                 startAsyncQuery();
    27.         }
    28.        
    29.         @Override
    30.         public void onStop() {
    31.                 // TODO Auto-generated method stub
    32.                 super.onStop();
    33.                 mAdapter.getCursor().close();
    34.                 mAdapter.changeCursor(null);
    35.         }
    36.        
    37.         public void startAsyncQuery() {
    38.                 startTime = System.currentTimeMillis();
    39.                 mQuery.startQuery(1, null, Conversation.sAllThreadsUri,
    40.                                 Conversation.ALL_THREADS_PROJECTION, null, null,
    41.                                 Conversation.CONVERSATION_ORDER);
    42.         }
    43.        
    44.         private final class ConversationQuery extends AsyncQueryHandler {
    45.                 public ConversationQuery(ContentResolver cr) {
    46.                         super(cr);
    47.                         // TODO Auto-generated constructor stub
    48.                 }
    49.                 @Override
    50.                 protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
    51.                         // TODO Auto-generated method stub
    52.                         System.out.println("conversation cursor size : "
    53.                                         + cursor.getCount());
    54.                         mAdapter.changeCursor(cursor);
    55.                         Toast.makeText(
    56.                                         getActivity(),
    57.                                         "查询短信会话个数:" + cursor.getCount() + ",花费"
    58.                                                         + (System.currentTimeMillis() - startTime) + " ms",
    59.                                         Toast.LENGTH_LONG).show();
    60.                 }
    61.         }
    62. }
    复制代码
    代码中可以知道和使用普通的ListActivity完全没区别,
      
    onCreate()中完成自己要一次性初始的东西,我在里面主要是初始化一个adapter和一个对sms数据库的查询
    在onActivityCreated()中将adapter设置给listview,这个不确定有没有更好的位置,
    然后进入我们熟悉的生命周期方法:
    onStart()中,开启查询
    onStop()中,我们界面已经不在显示了,所以我们不关心数据库变化了,close cursor
    4.主页面的布局文件:
      
    1. <?xml version="1.0" encoding="utf-8"?>
    2. <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    3.     android:id="@+id/door_root_content_fl"
    4.     android:layout_width="match_parent"
    5.     android:layout_height="match_parent" >
    6.     <LinearLayout
    7.         android:layout_width="match_parent"
    8.         android:layout_height="match_parent"
    9.         android:orientation="vertical" >
    10.         <FrameLayout
    11.             android:id="@+id/door_contents_fl"
    12.             android:layout_width="match_parent"
    13.             android:layout_height="0dp"
    14.             android:layout_weight="1" />
    15.         <LinearLayout
    16.             android:layout_width="match_parent"
    17.             android:layout_height="55dp"
    18.             android:orientation="horizontal" >
    19.             <Button
    20.                 android:id="@+id/door_menu_btn"
    21.                 android:layout_width="match_parent"
    22.                 android:layout_height="match_parent"
    23.                 android:gravity="center"
    24.                 android:text="菜单" />
    25.         </LinearLayout>
    26.     </LinearLayout>
    27. </FrameLayout>
    复制代码
    5.运行效果图:
      



    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-6-1 12:51 , Processed in 0.368240 second(s), 46 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表