Fragment添加、删除、替换

时间:2022-04-26
本文章向大家介绍Fragment添加、删除、替换,主要内容包括01FragmentManager、02FragmentTransaction、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。

前面一起学习了Fragment的创建和加载,以及其生命周期方法,那么接下来进一步来学习Fragment的具体使用,本期先来学习Fragment添加、删除、替换。

一、概述

在前面的学习中,特别是动态加载的时候,有提到FragmentManager和FragmentTransaction类,这里先来详细了解一下其到底为何物。

01FragmentManager

要管理Activity中的Fragments,就需要使用FragmentManager类。通过getFragmentManager()或getSupportFragmentManager()获得 。

FragmentManager类常用的方法有以下几个:

  • findFragmentById(int id):根据ID来找到对应的Fragment实例,主要用在静态添加Fragment的布局中,因为静态添加的Fragment才会有ID 。
  • findFragmentByTag(String tag):根据TAG找到对应的Fragment实例,主要用于在动态添加的Fragment中,根据TAG来找到Fragment实例 。
  • getFragments():获取所有被add进Activity中的Fragment 实例。
  • benginTransatcion():开启一个事物。

02FragmentTransaction

如果需要添加、删除、替换Fragment,则需要借助于FragmentTransaction对象,FragmentTransaction 代表 Activity 对 Fragment 执行的多个改变。

FragmentTransaction类常用的方法有以下几个:

  • add(int containerViewId, Fragment fragment, String tag):将一个Fragment实例添加到Activity的最上层 。
  • remove(Fragment fragment):将一个Fragment实例从Activity的Fragment队列中删除。
  • replace(int containerViewId, Fragment fragment):替换containerViewId中的Fragment实例。注意,它首先把containerViewId中所有Fagment删除,然后再add进去当前的Fragment 实例。
  • hide(Fragment fragment):隐藏当前的Fragment,仅仅是设为不可见,并不会销毁。
  • show(Fragment fragment):显示之前隐藏的Fragment。
  • detach(Fragment fragment):会将view从UI中移除,和remove()不同,此时Fragment的状态依然由FragmentManager维护。
  • attach(Fragment fragment):重建view视图,附加到UI上并显示。
  • commit():提交一个事务。

二、示例

前面了解了Fragment管理和事物,为了更好的理解和掌握,用一个示例来进一步深度学习。

该示例非常简单,界面包含3个按钮和3个Fragment容器,其中第一个容器静态加载FirstFragment,后面两个通过动态加载的方式来完成,也是本示例主要需要学习的地方。

首先创建第一个容器的FirstFragment对应布局文件fragment_first.xml,布局代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"            
  android:layout_width="match_parent"              
  android:layout_height="match_parent"              
  android:background="#af520b"              
  android:orientation="vertical">    
  <TextView       
     android:layout_width="wrap_content"      
     android:layout_height="wrap_content"        
     android:text="这是我的第一个Fragment"        
     android:textColor="#0c1ff1"        
     android:textSize="18sp"/>
</LinearLayout>

接着创建第一个容器的FirstFragment文件,代码如下:

public class FirstFragment extends Fragment {   
 @Nullable    
 @Override    
 public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,Bundle savedInstanceState) {     
    View view = inflater.inflate(R.layout.fragment_first, container, false);        
    return view;   
}}

同理创建fragment_second.xml和fragment_third.xml文件,唯一的区别就是显示的提示文字和颜色不同,创建SecondFragment和ThirdFragment加载对应的布局文件,这里不在给出代码。

然后是修改activity_main.xml文件,修改后的代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"   
 android:layout_width="match_parent"    
 android:layout_height="match_parent"    
 android:orientation="vertical">  
   <LinearLayout      
     android:layout_width="match_parent"        
     android:layout_height="wrap_content"        
     android:orientation="horizontal">        
        <Button          
          android:id="@+id/add_btn"            
          android:layout_width="wrap_content"            
          android:layout_height="wrap_content"            
          android:text="add" />        
   <Button          
     android:id="@+id/remove_btn"            
     android:layout_width="wrap_content"            
     android:layout_height="wrap_content"            
     android:text="remove" />       
   <Button           
     android:id="@+id/replace_btn"            
     android:layout_width="wrap_content"            
     android:layout_height="wrap_content"            
     android:text="replace" />    
</LinearLayout>  
  <fragment      
    android:id="@+id/fragment_one"        
    android:name="com.cqkxzsxy.jinyu.android.fragmentbasemanager.FirstFragment"        
    android:layout_width="match_parent"        
    android:layout_height="wrap_content" />   
  <FrameLayout      
    android:id="@+id/fragment_container1"        
    android:layout_width="match_parent"        
    android:layout_height="wrap_content" />    
  <FrameLayout      
    android:id="@+id/fragment_container2"        
    android:layout_width="match_parent"        
    android:layout_height="wrap_content" />
</LinearLayout>

最后是修改MainActivity的代码,如下所示:

package com.cqkxzsxy.jinyu.android.fragmentbasemanager;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {  
  private Button mAddBtn = null;    
  private Button mRemoveBtn = null;    
  private Button mReplaceBtn = null;    
  private Fragment mSecondFragment = null;    
  private Fragment mThirdFragment = null;    
  @Override   
   protected void onCreate(Bundle savedInstanceState) {      
     super.onCreate(savedInstanceState);        
     setContentView(R.layout.activity_main);        
     mAddBtn = (Button) findViewById(R.id.add_btn);        
     mRemoveBtn = (Button) findViewById(R.id.remove_btn);        
     mReplaceBtn = (Button) findViewById(R.id.replace_btn);        // 创建和获取Fragment实例        
     mSecondFragment = new SecondFragment();        
     mThirdFragment = new ThirdFragment();        // 设置监听事件        
     mAddBtn.setOnClickListener(this);        
     mRemoveBtn.setOnClickListener(this);        
     mReplaceBtn.setOnClickListener(this);    }   
      @Override    
      public void onClick(View v) {        // 获取到FragmentManager对象      
        FragmentManager fragmentManager = getFragmentManager();        // 开启一个事务        
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();        // Fragment操作        
        switch (v.getId()) {        
            case R.id.add_btn:                // 向容器内加入Fragment                
            if (!mSecondFragment.isAdded()) {                
                fragmentTransaction.add(R.id.fragment_container1, mSecondFragment);        
               }              
           if (!mThirdFragment.isAdded()) {                
               fragmentTransaction.add(R.id.fragment_container2, mThirdFragment);        
                       }             
           break;          
           case R.id.remove_btn:                // 从容器类移除Fragment                
           fragmentTransaction.remove(mSecondFragment);                
           break;            
           case R.id.replace_btn:               
            if (!mSecondFragment.isAdded()) {                   
             fragmentTransaction.replace(R.id.fragment_container2, mSecondFragment);        
                     }                
                     break;            
                     default:                
                     break;        }        // 提交事务     
                        fragmentTransaction.commit(); 
      }}

主要就是为3个按钮设置监听事件,其中第一个按钮为后2个容器添加Fragment,第二个按钮移除第一个容器的Fragment,第三个按钮将容器2里面的Fragment替换。

运行程序可以看到下图所示界面,首先点击“ADD”按钮,将SecondFragment和ThirdFragment动态添加到相应容器。

然后点击“REMOVE”将SecondFragment移除,可以看到SecondFragment被移除,ThirdFragment的位置上移;再点击“REPLACE”按钮将本来加载了ThirdFragment的第二个容器替换为SecondFragment,可以看到替换效果;最后再点击“REMOVE”重新将SecondFragment移除,可以看到最后只剩下FirstFragment。

通过上面的操作相信你应该简单知道如何添加、移除和替换Fragment了。这里有个值得注意的问题是很多同学分不清add操作和replace操作,接下来继续在上面的案例基础上进行修改验证。

在SecondFragment和ThirdFragment中加入Fragment的生命周期方法,同时加入Logcat日志,然后重新运行程序。首先点击“ADD”按钮,将SecondFragment和ThirdFragment动态添加到相应容器。打开Logcat日志可以看到:

然后点击“REMOVE”将SecondFragment移除,再点击“REPLACE”按钮将本来加载了ThirdFragment的第二个容器替换为SecondFragment。打开Logcat日志可以看到:

从上面的2个日志信息可以论证前面所讲的,replace是首先把containerViewId中所有Fagment删除,然后再add进去当前的Fragment 实例。

本期先学到这里,下期再继续学习其他操作。