惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 聂微东
博客园 - 叶小钗
爱范儿
爱范儿
罗磊的独立博客
Hugging Face - Blog
Hugging Face - Blog
阮一峰的网络日志
阮一峰的网络日志
S
SegmentFault 最新的问题
Apple Machine Learning Research
Apple Machine Learning Research
美团技术团队
T
Tailwind CSS Blog
博客园 - 司徒正美
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
宝玉的分享
宝玉的分享
量子位
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
The Cloudflare Blog
人人都是产品经理
人人都是产品经理
小众软件
小众软件
博客园 - 【当耐特】
博客园 - 三生石上(FineUI控件)
V
Visual Studio Blog
雷峰网
雷峰网
酷 壳 – CoolShell
酷 壳 – CoolShell

博客园 - y丶innocence

临时111 RecyclerView 数据多时无法滑动:ConstraintLayout 约束高度修复笔记 Android Kotlin OkHttp3 WebSocket 长连接与 Gson 数据解析系统笔记 Android + Kotlin + OkHttp WebSocket 相关概念与使用流程笔记(TLS/证书 + 鉴权/会话) AI对话导出markdown格式流程 代理转发 分享文件 面向全球的app的excel导出和kotlin IO原理 安卓导出笔记(未整理) java&kotlin listener 0.7 动画 0.4 View 工作流程 0.3 view 滑动冲突 13. Jetpack 0. 安卓开发艺术探索参考资料 12. Material Design 7. 持久化技术 java 基础 4. UI 开发 3. Activity 2.2 Kotlin 面向对象 2.3 Kotlin高级 2.1 Kotlin基础 1. Android简介 [OpenJudge] 反正切函数的应用 (枚举)(数学) [OpenJudge] 摘花生 (模拟)
5. Fragment
y丶innocence · 2026-01-14 · via 博客园 - y丶innocence

5. Fragment

1. Fragment 和 Fragment 的生命周期

1. Fragment

  • Fragment 是一种可以嵌入在 Activity 当中的 UI 片段
  • 应用
    • 使用 RecyclerView 展示一组新闻标题,点开新闻标题后有新闻详情
    • 手机中,新闻标题列表放在一个 Activity 中,将新闻的详细内容放在另一个 Activity 中,即两个 Activity
    • 平板中,将新闻标题列表界面和新闻详细内容界面分别放在两个 Fragment 中, 然后在同一个 Activity 里引入这两个 Fragment

2. 生命周期

  • Fragment 生命周期与 Activity 几乎类似

    • 相似点,与 Activity 关联的 Fragment,如果 Activity 处于某一状态,则该 Fragment 也处于该状态
      • 运行状态
      • 暂停状态
      • 停止状态
      • 销毁状态
    • 区别
      • 将 Fragment 从 Activity 中移除
        • 如果调用了 addToBackStack,则进入停止状态
        • 如果没调用 addToBackStack,则进入销毁状态
          • 即将 Fragment 添加进返回栈后再移除,处于运行但是不可见的状态(停止状态)
  • onAttach():当 Fragment 和 Activity 建立关联时调用。

  • onCreateView():为 Fragment 创建视图(加载布局)时调用。

  • onActivityCreated():确保与 Fragment 相关联的 Activity 已经创建完毕时调用。

  • onDestroyView():当与 Fragment 关联的视图被移除时调用。

  • onDetach():当 Fragment 和 Activity 解除关联时调用。

  1. 启动 Activity 和 Fragment
    • onAttach()、 onCreate()、onCreateView()、onActivityCreated()、onStart() 和 onResume()
  2. 切换为另一个 Fragment (使用addToBackStack)
    • onPause()、onStop() 和 onDestroyView()
  3. 返回之前的 Fragment
    • onCreateView()、onActivityCreated()、onStart() 和 onResume()
  4. 退出程序
    • onPause()、onStop()、onDestroyView()、onDestroy() 和 onDetach()

2. 动态加载布局

  • 在不同文件夹下,建立相同的 layout 文件,就能自动选择对应的布局
    • 限定符
      • 【截图】
    • 最小宽度限定符(smallest-width qualifier)
      • layout-sw600sp
        • 单位为 dp
        • 宽度大于等于 600 dp 的设备加载 layout-sw600dp/xxx 的布局
        • 小于的加载 layout/xxx 的布局

3. 代码

  • Fragment

    • 可以直接存放 Fragment
  • FrameLayout

    • 可以动态加载 Fragment
  • 修改代码

    • MainActivity2

      • package com.example.helloworld
        
        import android.content.Context
        import android.content.Intent
        import android.os.Bundle
        import android.util.Log
        import android.widget.ArrayAdapter
        import android.widget.Button
        import android.widget.ListView
        import androidx.appcompat.app.AppCompatActivity
        import androidx.appcompat.widget.Toolbar
        
        
        class MainActivity2 : BaseActivity() {
        
            override fun onCreate(savedInstanceState: Bundle?) {
                super.onCreate(savedInstanceState)
                setContentView(R.layout.second_layout)
        
                // toolbar 部分
                val toolbar: Toolbar = findViewById(R.id.toolbar2)
                setSupportActionBar(toolbar)
                supportActionBar?.setDisplayHomeAsUpEnabled(true)            // 设置返回按钮
                toolbar.setNavigationOnClickListener { finish() }             // 设置结束 act2
        
                ActivityCollector.addActivity(this)
        
                // 从前一个 Activity 接收数据
                val extraData1 = intent.getStringExtra("param1")
                val extraData2 = intent.getStringExtra("param2")
                Log.d("Activity2", "param1 is $extraData1, param2 is $extraData2")
        
        
                // 返回数据(但是未实现)
                val button2: Button = findViewById(R.id.button2)        // 通过 id 找到 view, 并指明类型为 button
                button2.setOnClickListener {
                    val intent = Intent().apply { putExtra("data_return", "Hello Activity1") }
                    setResult(RESULT_OK, intent)
                    finish()
                }
        
                // 关闭所有 Activity
                val button3: Button = findViewById(R.id.button3)
                button3.setOnClickListener {
                    ActivityCollector.finishAll()
                }
        
                val button4: Button = findViewById(R.id.button4)
                button4.setOnClickListener {
                    startNewActivity(this, MainActivity3::class.java)
                }
        
                val button5: Button = findViewById(R.id.button5)
                button5.setOnClickListener {
                    startNewActivity(this, MainActivity4::class.java)
                }
        
                val button7: Button = findViewById(R.id.button7)
                button7.setOnClickListener {
                    startNewActivity(this, FragmentActivity::class.java)
                }
        
            }
        
        
        }
        
        
        
    • second_layout

      • <?xml version="1.0" encoding="utf-8"?>
        <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:orientation="vertical"
            android:layout_width="match_parent"
          android:layout_height="match_parent">
        
            <androidx.appcompat.widget.Toolbar
                android:id="@+id/toolbar2"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="?attr/colorPrimary"
                android:minHeight="?attr/actionBarSize"
                android:theme="?attr/actionBarTheme" />
        
            <Button
                android:id="@+id/button2"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="Back" />
        
            <Button
                android:id="@+id/button3"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="Quit App" />
        
            <Button
                android:id="@+id/button4"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="Go third" />
        
            <Button
                android:id="@+id/button5"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="Go forth" />
        
            <Button
                android:id="@+id/button7"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="Go Fragment" />
        
        </LinearLayout>
        
  • 新增代码

    • FragmentActivity

      • package com.example.helloworld
        
        import android.os.Bundle
        import android.util.Log
        import android.widget.Button
        import androidx.activity.ComponentActivity
        import androidx.activity.compose.setContent
        import androidx.activity.enableEdgeToEdge
        import androidx.appcompat.app.AppCompatActivity
        import androidx.appcompat.widget.Toolbar
        import androidx.compose.foundation.layout.fillMaxSize
        import androidx.compose.foundation.layout.padding
        import androidx.compose.material3.Scaffold
        import androidx.compose.material3.Text
        import androidx.compose.runtime.Composable
        import androidx.compose.ui.Modifier
        import androidx.compose.ui.tooling.preview.Preview
        import androidx.fragment.app.Fragment
        import com.example.helloworld.AnotherRightFragment.Companion
        import com.example.helloworld.ui.theme.HelloWorldTheme
        
        class FragmentActivity : BaseActivity() {
            override fun onCreate(savedInstanceState: Bundle?) {
                super.onCreate(savedInstanceState)
                setContentView(R.layout.fragment_layout)
                ActivityCollector.addActivity(this)
        
                val button6: Button = findViewById(R.id.button6)        // button6 在 Fragmentlayout 里面的 Fragment 中,但是会报错
                button6.setOnClickListener {
                    replaceFragment(AnotherRightFragment())
                }
                replaceFragment(RightFragment())
        
        
                // 交互
                val leftFragment = LeftFragment.newInstance("a","")
                leftFragment.fragmentLog()
                val leftFragment2 = supportFragmentManager.findFragmentById(R.id.leftFrag) as? LeftFragment
                leftFragment2?.fragmentLog()
                val anotherFragment = AnotherRightFragment.newInstance("a","")
                anotherFragment.fragmentLog()
                val rightFragment = supportFragmentManager.findFragmentById(R.id.rightLayout) as? RightFragment
                rightFragment?.fragmentLog() // 没有打印
        
            }
        
            // 动态添加 Fragment
            private fun replaceFragment(fragment: Fragment) {
                val fragmentManager = supportFragmentManager
                val transaction = fragmentManager.beginTransaction()                    // 开启一个事务
                transaction.replace(R.id.rightLayout, fragment)      // 向对应 FrameLayout 添加 fragment 对象
                transaction.addToBackStack(null)
                transaction.commit()                                                    // 提交事务
            }
            fun fragmentLog() {
                Log.d("FragmentActivity", "call activity from fragment")
            }
        }
        
        
        
    • LeftFragment

      • package com.example.helloworld
        
        import android.os.Bundle
        import android.util.Log
        import androidx.fragment.app.Fragment
        import android.view.LayoutInflater
        import android.view.View
        import android.view.ViewGroup
        
        // TODO: Rename parameter arguments, choose names that match
        // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
        private const val ARG_PARAM1 = "param1"
        private const val ARG_PARAM2 = "param2"
        
        /**
         * A simple [Fragment] subclass.
         * Use the [LeftFragment.newInstance] factory method to
         * create an instance of this fragment.
         */
        class LeftFragment : Fragment() {
            // TODO: Rename and change types of parameters
            private var param1: String? = null
            private var param2: String? = null
        
            override fun onCreate(savedInstanceState: Bundle?) {
                super.onCreate(savedInstanceState)
                arguments?.let {
                    param1 = it.getString(ARG_PARAM1)
                    param2 = it.getString(ARG_PARAM2)
                }
        
                val fragActivity = activity as? FragmentActivity     // fragment 调用 activity
                fragActivity?.fragmentLog()
            }
        
            override fun onCreateView(
                inflater: LayoutInflater, container: ViewGroup?,
                savedInstanceState: Bundle?
            ): View? {
                // Inflate the layout for this fragment
                return inflater.inflate(R.layout.fragment_left, container, false)
            }
        
            fun fragmentLog() {
                Log.d("LeftFragment", "call fragment from activity")
            }
        
            companion object {
                /**
                 * Use this factory method to create a new instance of
                 * this fragment using the provided parameters.
                 *
                 * @param param1 Parameter 1.
                 * @param param2 Parameter 2.
                 * @return A new instance of fragment LeftFragment.
                 */
                // TODO: Rename and change types and number of parameters
                @JvmStatic
                fun newInstance(param1: String, param2: String) =
                    LeftFragment().apply {
                        arguments = Bundle().apply {
                            putString(ARG_PARAM1, param1)
                            putString(ARG_PARAM2, param2)
                        }
                    }
            }
        }
        
    • RightFragment

      • package com.example.helloworld
        
        import android.os.Bundle
        import android.util.Log
        import androidx.fragment.app.Fragment
        import android.view.LayoutInflater
        import android.view.View
        import android.view.ViewGroup
        
        // TODO: Rename parameter arguments, choose names that match
        // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
        private const val ARG_PARAM1 = "param1"
        private const val ARG_PARAM2 = "param2"
        
        /**
         * A simple [Fragment] subclass.
         * Use the [RightFragment.newInstance] factory method to
         * create an instance of this fragment.
         */
        class RightFragment : Fragment() {
            // TODO: Rename and change types of parameters
            private var param1: String? = null
            private var param2: String? = null
        
            override fun onCreate(savedInstanceState: Bundle?) {
                super.onCreate(savedInstanceState)
                arguments?.let {
                    param1 = it.getString(ARG_PARAM1)
                    param2 = it.getString(ARG_PARAM2)
                }
        
        
            }
        
            override fun onCreateView(
                inflater: LayoutInflater, container: ViewGroup?,
                savedInstanceState: Bundle?
            ): View? {
                // Inflate the layout for this fragment
                return inflater.inflate(R.layout.fragment_right, container, false)
            }
        
            fun fragmentLog() {
                Log.d("RightFragment", "call fragment from activity")
            }
        
            companion object {
                /**
                 * Use this factory method to create a new instance of
                 * this fragment using the provided parameters.
                 *
                 * @param param1 Parameter 1.
                 * @param param2 Parameter 2.
                 * @return A new instance of fragment RightFragment.
                 */
                // TODO: Rename and change types and number of parameters
                @JvmStatic
                fun newInstance(param1: String, param2: String) =
                    RightFragment().apply {
                        arguments = Bundle().apply {
                            putString(ARG_PARAM1, param1)
                            putString(ARG_PARAM2, param2)
                        }
                    }
            }
        }
        
    • AnotherRightFragment

      • package com.example.helloworld
        
        import android.os.Bundle
        import android.util.Log
        import androidx.fragment.app.Fragment
        import android.view.LayoutInflater
        import android.view.View
        import android.view.ViewGroup
        
        // TODO: Rename parameter arguments, choose names that match
        // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
        private const val ARG_PARAM1 = "param1"
        private const val ARG_PARAM2 = "param2"
        
        /**
         * A simple [Fragment] subclass.
         * Use the [AnotherRightFragment.newInstance] factory method to
         * create an instance of this fragment.
         */
        class AnotherRightFragment : Fragment() {
            // TODO: Rename and change types of parameters
            private var param1: String? = null
            private var param2: String? = null
        
            override fun onCreate(savedInstanceState: Bundle?) {
                super.onCreate(savedInstanceState)
                arguments?.let {
                    param1 = it.getString(ARG_PARAM1)
                    param2 = it.getString(ARG_PARAM2)
                }
            }
        
            override fun onCreateView(
                inflater: LayoutInflater, container: ViewGroup?,
                savedInstanceState: Bundle?
            ): View? {
                // Inflate the layout for this fragment
                return inflater.inflate(R.layout.fragment_another_right, container, false)
            }
        
            fun fragmentLog() {
                Log.d("AnotherRightFragment", "call fragment from activity")
            }
        
            companion object {
                /**
                 * Use this factory method to create a new instance of
                 * this fragment using the provided parameters.
                 *
                 * @param param1 Parameter 1.
                 * @param param2 Parameter 2.
                 * @return A new instance of fragment AnotherRightFragment.
                 */
                // TODO: Rename and change types and number of parameters
                @JvmStatic
                fun newInstance(param1: String, param2: String) =
                    AnotherRightFragment().apply {
                        arguments = Bundle().apply {
                            putString(ARG_PARAM1, param1)
                            putString(ARG_PARAM2, param2)
                        }
                    }
            }
        }
        
    • fragment_layout

      • <?xml version="1.0" encoding="utf-8"?>
        <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:orientation="horizontal"
            android:layout_width="match_parent"
            android:layout_height="match_parent" >
        
            <fragment
                android:id="@+id/leftFrag"
                android:name="com.example.helloworld.LeftFragment"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1" />
        
            <FrameLayout
                android:id="@+id/rightLayout"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="3" >
            </FrameLayout>
        
        </LinearLayout>
        
    • fragment_left

      • <?xml version="1.0" encoding="utf-8"?>
        <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:tools="http://schemas.android.com/tools"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            tools:context=".LeftFragment">
        
            <Button
                android:id="@+id/button6"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:text="Button" />
        </FrameLayout>
        
    • fragment_right

      • <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:orientation="vertical"
            android:background="#00ff00"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
        
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:textSize="24sp"
                android:text="This is right fragment"
                />
        
        </LinearLayout>
        
    • fragment_another_right

      • <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:orientation="vertical"
            android:background="#ffff00"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
        
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:textSize="24sp"
                android:text="This is another right fragment"
                />
        
        </LinearLayout>
        

【最佳实践和Kotlin知识】

posted @ 2026-01-14 16:10  y丶innocence  阅读(10)  评论()    收藏  举报