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中以居中方式添加蓝色背景的MyFragmentA,MyFragmentA的background不会覆盖掉原有Activity的background
  • 6s后通过add()方法在R.id.add_child_ll的LinearLayout中以居中方式添加橘色背景的MyFragmentB,add()方法添加并不会移除覆盖掉第一次添加的MyFragmentA的background。因为不会移除,所以橘色背景的MyFragmentB在第一次添加的MyFragmentA的background下方继续布局绘制
  • 6s后通过replace()方法在R.id.replace_child_ll的LinearLayout中以居中方式添加橘色背景的MyFragmentB,add()方法添加会移除覆盖掉第一次添加的MyFragmentA的background。因为会移除,所以橘色背景的MyFragmentB直接在原有R.id.replace_child_ll的LinearLayout中直接居中布局绘制
  • 如果只是将新的Fragment添加到Activity,而不关心或者不需要移除已存在的Fragment,使用add()方法。但是如果希望替换container中已存在的Fragment,使用replace()方法

获取当前Fragment的数量

  • 获取Activity中Fragment的数量
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
  • 获取View中Fragment的数量
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 

效果图

相关推荐
星夜离尘5612 小时前
MATLAB 工程实验:不等间隔流量积分,先把缺口与覆盖率说清楚
开发语言·matlab·时间戳·数据质量·数值积分
Ai-_Man12 小时前
Meta Muse还是不可以导出左侧所有对话,只能点进去单条内容导出,方法不对吗?
开发语言·人工智能·ai·小程序·c#·1024程序员节
梓豪csd12 小时前
消息订阅中心:谁该收到哪条通知
java·开发语言·人工智能·低代码·自动化·1024程序员节
学逆向的13 小时前
C 枚举变量
c语言·开发语言·网络安全
Sakura_j_h_13 小时前
Python 在定时任务里输出 emoji,UnicodeEncodeError 从哪来
开发语言·字符编码·windows·python·定时任务
美狐美颜SDK开放平台14 小时前
准备开发直播APP?视频美颜SDK接入前的十项检查清单
android·ios·音视频·直播美颜sdk·视频美颜sdk
传奇开心果编程14 小时前
【Jetpack Compose娓娓道来】第26课:Repository模式与数据层设计——数据的唯一入口
android·移动开发·1024程序员节·jetpack compose·编程语言理论·编程框架·声明式ui
传奇开心果编程16 小时前
从替代到粒度:Compose Multiplatform 的决策模式重构已开启跨平台新时代
kotlin·移动开发·跨平台·cmp·编程语言理论·编程框架·声明式ui
小成2023032026518 小时前
C++~07补充
开发语言·c++