Activity->Activity中动态添加Fragment->add和replace方式添加的区别

XML文件

  • Activity布局文件R.layout.activity_main
xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/root_ll"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <LinearLayout
        android:id="@+id/add_child_ll"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:background="@android:color/holo_green_light"
        android:gravity="center"
        android:orientation="vertical">
    </LinearLayout>
    <LinearLayout
        android:id="@+id/replace_child_ll"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:background="@android:color/holo_red_light"
        android:gravity="center"
        android:orientation="vertical">
    </LinearLayout>
</LinearLayout>
  • 第一次添加的MyFragmentA布局R.layout.inflate_layout_a
xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<TextView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/inflate_tv_a"
    android:layout_width="match_parent"
    android:layout_height="100dp"
    android:background="@android:color/holo_blue_light" />
  • 第二次添加的MyFragmentB布局R.layout.inflate_layout_b
xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<TextView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/inflate_tv_b"
    android:layout_width="match_parent"
    android:layout_height="100dp"
    android:background="@android:color/holo_orange_light"/>

Activtiy代码和Fragment代码

-MyFragmentA代码

kotlin 复制代码
class MyFragmentA : Fragment() {
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.inflate_layout_a, container, false)
    }
}

-MyFragmentB代码

kotlin 复制代码
class MyFragmentB : Fragment() {
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.inflate_layout_b, container, false)
    }
}
  • Activity代码
kotlin 复制代码
const val TAG = "Yang"
class MainActivity : AppCompatActivity() {
    var addLl : LinearLayout? = null
    var replaceLl : LinearLayout? = null
    var mMainHandler = Handler(Looper.getMainLooper())
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        addLl = findViewById(R.id.add_child_ll) as? LinearLayout
        replaceLl = findViewById(R.id.replace_child_ll) as? LinearLayout
        mMainHandler.postDelayed({
            val firstFragment1 = MyFragmentA()
            val firstFragment2 = MyFragmentA()
            addLl?.let {
                replaceFragment(firstFragment1, it)
            }
            replaceLl?.let {
                replaceFragment(firstFragment2, it)
            }
        }, 3000)

        mMainHandler.postDelayed({
            val secondFragment1 = MyFragmentB()
            val secondFragment2 = MyFragmentB()
            addLl?.let {
                addFragment(secondFragment1, it)
            }
            replaceLl?.let {
                replaceFragment(secondFragment2, it)
            }
        }, 6000)
    }

    private fun addFragment(fragment: Fragment, targetView: View) {
        val transaction = supportFragmentManager.beginTransaction()
        transaction?.add(targetView.id, fragment)?.commitNowAllowingStateLoss()
    }

    private fun replaceFragment(fragment: Fragment, targetView: View) {
        val transaction = supportFragmentManager.beginTransaction()
        transaction?.replace(targetView.id, fragment)?.commitNowAllowingStateLoss()
    }
}
  • 3s后通过replace()方法在两个LinearLayout中以居中方式添加蓝色背景的MyFragmentAMyFragmentAbackground不会覆盖掉原有Activitybackground
  • 6s后通过add()方法在R.id.add_child_llLinearLayout中以居中方式添加橘色背景的MyFragmentBadd()方法添加并不会移除覆盖掉第一次添加的MyFragmentAbackground。因为不会移除,所以橘色背景的MyFragmentB在第一次添加的MyFragmentAbackground下方继续布局绘制
  • 6s后通过replace()方法在R.id.replace_child_llLinearLayout中以居中方式添加橘色背景的MyFragmentBadd()方法添加会移除覆盖掉第一次添加的MyFragmentAbackground。因为会移除,所以橘色背景的MyFragmentB直接在原有R.id.replace_child_llLinearLayout中直接居中布局绘制
  • 如果只是将新的Fragment添加到Activity,而不关心或者不需要移除已存在的Fragment,使用add()方法。但是如果希望替换container中已存在的Fragment,使用replace()方法

获取当前Fragment的数量

  • 获取ActivityFragment的数量
kotlin 复制代码
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Log.i(TAG, "onCreate")
        setContentView(R.layout.activity_main)
        addLl = findViewById(R.id.add_child_ll) as? LinearLayout
        replaceLl = findViewById(R.id.replace_child_ll) as? LinearLayout
        mMainHandler.postDelayed({
            val firstFragment1 = MyFragmentA()
            val firstFragment2 = MyFragmentA()
            addLl?.let {
                replaceFragment(firstFragment1, it)
            }
            replaceLl?.let {
                replaceFragment(firstFragment2, it)
            }
            Log.i(TAG, "3000ms Number of fragments: ${supportFragmentManager.fragments.size}")
            Log.i(TAG, "addLl active fragment count = ${addLl?.let { getActiveFragmentCount(it) }} ")
            Log.i(TAG, "replaceLl active fragment count = ${replaceLl?.let { getActiveFragmentCount(it) }} ")
        }, 3000)

        mMainHandler.postDelayed({
            val secondFragment1 = MyFragmentB()
            val secondFragment2 = MyFragmentB()
            addLl?.let {
                addFragment(secondFragment1, it)
            }
            replaceLl?.let {
                replaceFragment(secondFragment2, it)
            }
            Log.i(TAG, "6000ms Number of fragments: ${supportFragmentManager.fragments.size}")
            Log.i(TAG, "addLl active fragment count = ${addLl?.let { getActiveFragmentCount(it) }} ")
            Log.i(TAG, "replaceLl active fragment count = ${replaceLl?.let { getActiveFragmentCount(it) }} ")
        }, 6000)
    }

// log result
// 3s添加了两个MyFragmentA,数量为2
// 6s添加两个MyFragmentB,移除一个MyFragmentA,数量为3
2024-06-06 11:11:31.427 24538-24538 Yang       I  3000ms Number of fragments: 2
2024-06-06 11:11:34.423 24538-24538 Yang       I  6000ms Number of fragments: 3
  • 获取ViewFragment的数量
kotlin 复制代码
fun getActiveFragmentCount(view : View): Int {
    var count = 0
    supportFragmentManager.fragments.forEach {
        if(it.view?.parent == view){
            count++
        }
    }
    return count
}

// log result
// 3s添加了两个LinearLayout各自添加一个Fragment
2024-06-06 12:57:55.747 24983-24983 Yang        I  3000ms Number of fragments: 2
2024-06-06 12:57:55.747 24983-24983 Yang        I  addLl active fragment count = 1 
2024-06-06 12:57:55.747 24983-24983 Yang        I  replaceLl active fragment count = 1 
// 6s第一个LinearLayout通过add方式添加,
2024-06-06 12:57:58.739 24983-24983 Yang        I  6000ms Number of fragments: 3
2024-06-06 12:57:58.740 24983-24983 Yang        I  addLl active fragment count = 2 
2024-06-06 12:57:58.740 24983-24983 Yang        I  replaceLl active fragment count = 1 

效果图

相关推荐
Scott9999HH1 小时前
【IIoT流量实战】蒸汽管道阀门全关却仍有流量?用 Python 实现涡街信号 FFT 频谱分析与温压全补偿积算网关,深度拆解靠谱的涡街流量计厂家硬核技术标准
开发语言·python
码智社2 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
AI云海3 小时前
python 列表、元组、集合和字典
开发语言·python
萧瑟余晖3 小时前
JDK 26 新特性详解
java·开发语言
马优晨4 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
人邮异步社区6 小时前
怎么把C语言学到精通?
c语言·开发语言
心平气和量大福大6 小时前
C#-WPF-控件-TextBox 数据绑定
开发语言·c#·wpf
ttwuai7 小时前
Cursor 生成 CRUD 后,Go 后台接口别只测 200:JWT、RBAC 和 tenant_id 怎么验
开发语言·后端·golang
এ慕ོ冬℘゜7 小时前
前端基础:什么是时间戳?JS获取时间戳三种方法与实战用途
开发语言·前端·javascript
执明wa7 小时前
LayoutInflater详解: XML是如何变成View的?
android·xml·开发语言·android studio