Android Fragment总结

概述

Fragment 是一种可以嵌入到 Activity 中的 UI 组件,它具有自己的布局和生命周期。Fragment 代表 Activity 中的行为或用户界面部分,一个 Activity 可以包含多个 Fragment。

生命周期

在这里插入图片描述

生命周期方法 调用时机 作用
onAttach() Fragment 与 Activity 关联时 获取 Activity 引用
onCreate() Fragment 创建时 初始化非UI资源
onCreateView() 创建 Fragment 视图时 加载布局文件
onViewCreated() 视图创建完后 初始化视图组件
onStart() Fragment 可见时 准备与用户交互
onResume() Fragment 可交互时 开始与用户交互
onPuase() Fragment 不可交互时 保存关键数据
onStop() Fragment 不可见时 释放不重要资源
onDestroyView() 视图被销毁时 清理视图相关资源
onDestroy() Fragment 被销毁时 清理所有资源
onDetach() 与 Activity 解除关联时 清理与 Activity 的引用

创建Fragment

静态创建

创建Fragment:

class MyFragment : Fragment() {
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_my, container, false)
    }
}

静态添加Fragment:

<fragment
          android:name="com.test.myapplication.MyFragment"
          android:layout_width="match_parent"
          android:layout_height="match_parent" />

动态创建

定义布局容器(传统方式使用FrameLayout):

<FrameLayout
    android:id="@+id/fragment_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

定义布局容器(推荐使用FrameLayout):

<androidx.fragment.app.FragmentContainerView
    android:id="@+id/fragment_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

动态添加Fragment:

class MainActivity : AppCompatActivity() {
    private lateinit var myFragment: MyFragment

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        if (savedInstanceState == null) {
            myFragment = MyFragment()
            supportFragmentManager.beginTransaction()
                .add(R.id.fragment_container, myFragment)
                .commit()
        } else {
            myFragment = supportFragmentManager.findFragmentById(R.id.fragment_container) as MyFragment
        }
    }
}

事务操作

  • add():添加 Fragment
  • replace():替换 Fragment
  • remove():移除 Fragment
  • show():显示之前隐藏的 Fragment
  • hide():隐藏 Fragment
// 添加Fragment
supportFragmentManager.beginTransaction()
    .add(R.id.fragment_container, myFragment)
    .commit()

// 替换Fragment
supportFragmentManager.beginTransaction()
    .replace(R.id.fragment_container, myFragment)
    .commit()

// 移除Fragment
supportFragmentManager.beginTransaction()
    .remove(myFragment)
    .commit()

Fragment之间通信

通过Activity

定义接口:

interface OnDataChangeListener {
    fun onDataChange(data: String)
}

定义发送方Fragment:

class OneFragment : Fragment() {
    private lateinit var listener: OnDataChangeListener

    override fun onAttach(context: Context) {
        super.onAttach(context)
        if (context is OnDataChangeListener) {
            listener = context
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_one, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val btn = view.findViewById<Button>(R.id.btn)
        btn.setOnClickListener {
            sendData("hello world")
        }
    }

    // 发送数据
    private fun sendData(data: String) {
        listener.onDataChange(data)
    } 
}

定义接收方Fragment:

class TwoFragment : Fragment() {
    private lateinit var textView: TextView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_two, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        textView = view.findViewById<TextView>(R.id.textView)
    }

    fun receiveData(data: String) {
        textView.text = data
    }
}

Activity实现接口:

class MainActivity : AppCompatActivity(), OnDataChangeListener {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        supportFragmentManager.beginTransaction()
            .add(R.id.fragment_container1, OneFragment())
            .add(R.id.fragment_container2, TwoFragment())
            .commit()
    }

    override fun onDataChange(data: String) {
        val fragment = supportFragmentManager.findFragmentById(R.id.fragment_container2) as TwoFragment
        fragment.receiveData(data)
    }
}

通过ViewModel

定义共享的ViewModel:

class SharedViewModel : ViewModel() {
    private val _data = MutableLiveData<String>()
    val data = _data

    fun sendData(data: String) {
        _data.value = data
    }
}

定义发送方Fragment:

class OneFragment : Fragment() {
    private val sharedViewModel by activityViewModels<SharedViewModel>()

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_one, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val btn = view.findViewById<Button>(R.id.btn)
        btn.setOnClickListener {
            sendData("hello world")
        }
    }

    private fun sendData(data: String) {
        sharedViewModel.sendData(data)
    }
}

定义接收方Fragment:

class TwoFragment : Fragment() {
    private val sharedViewModel by activityViewModels<SharedViewModel>()
    private lateinit var textView: TextView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_two, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        textView = view.findViewById<TextView>(R.id.textView)
        sharedViewModel.data.observe(viewLifecycleOwner) { data ->
            receiveData(data)
        }
    }

    fun receiveData(data: String) {
        textView.text = data
    }
}

setMaxLifecyle()

setMaxLifecycle() 是 FragmentTransaction 中的一个方法,用于控制 Fragment 的最大生命周期状态。更加精准的控制生命周期,实现对加载资源和释放资源的管理。

class MainActivity : AppCompatActivity() {
    private lateinit var oneFragment: OneFragment
    private lateinit var twoFragment: TwoFragment
    private lateinit var btn: Button
    private var currentFragment: Fragment? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        btn = findViewById<Button>(R.id.btn)

        oneFragment = OneFragment()
        twoFragment = TwoFragment()

        supportFragmentManager.beginTransaction()
            .add(R.id.fragment_container1, oneFragment)
            .setMaxLifecycle(oneFragment, Lifecycle.State.RESUMED)
            .add(R.id.fragment_container1, twoFragment)
            .setMaxLifecycle(twoFragment, Lifecycle.State.STARTED)
            .hide(twoFragment)
            .commit()

        currentFragment = oneFragment

        btn.setOnClickListener {
            switchFragment()
        }
    }

    private fun switchFragment() {
        val transaction = supportFragmentManager.beginTransaction()
        if (currentFragment == oneFragment) {
            transaction.show(twoFragment)
                .setMaxLifecycle(twoFragment, Lifecycle.State.RESUMED)
                .hide(oneFragment)
                .setMaxLifecycle(oneFragment, Lifecycle.State.STARTED)
            currentFragment = twoFragment
        } else if (currentFragment == twoFragment) {
            transaction.show(oneFragment)
                .setMaxLifecycle(oneFragment, Lifecycle.State.RESUMED)
                .hide(twoFragment)
                .setMaxLifecycle(twoFragment, Lifecycle.State.STARTED)
            currentFragment = oneFragment
        }
        transaction.commit()
    }
}

转场动画

传统动画资源

在 anim 目录下定义动画资源:

// enter_from_left.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000">
    <translate
        android:fromXDelta="-100%"
        android:toXDelta="0%" />
    <alpha
        android:fromAlpha="0"
        android:toAlpha="1.0" />
</set>
// enter_from_right
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000">
    <translate
        android:fromXDelta="100%"
        android:toXDelta="0%" />
    <alpha
        android:fromAlpha="0.0"
        android:toAlpha="1.0" />
</set>
// exit_to_left.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000">
    <translate
        android:fromXDelta="0%"
        android:toXDelta="-100%" />

    <alpha
        android:fromAlpha="1.0"
        android:toAlpha="0" />
</set>
// exit_to_right.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000">
    <translate
        android:fromXDelta="0%"
        android:toXDelta="100%" />
    <alpha
        android:fromAlpha="1.0"
        android:toAlpha="0" />
</set>

使用动画:

supportFragmentManager.beginTransaction()
    .setCustomAnimations(
        R.anim.enter_from_right,
        R.anim.exit_to_left,
        R.anim.enter_from_left,
        R.anim.exit_to_right
    )
    .replace(R.id.fragment_container, twoFragment)
    .addToBackStack(null)
    .commit()

现代转场API

class OneFragment : Fragment() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            // 设置退出动画:向左滑出
            exitTransition = Slide(Gravity.START).apply {
                duration = 300
            }
        }
    }
}
class TwoFragment : Fragment() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            // 设置进入动画:从右侧向左滑入
            enterTransition = Slide(Gravity.END).apply {
                duration = 300
            }
        }
    }
}
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐