【问题标题】:Fragment Container in Jetpack ComposeJetpack Compose 中的片段容器
【发布时间】:2020-03-04 06:22:34
【问题描述】:

我想使用 Jetpack Compose 开发单个 Activity 多片段应用程序。 对于 recyclerView,我们有 Vertical 和 Horizo​​ntalScroller。但是,对于片段我应该使用什么。

fun loadFragment(fragment: Fragment) {
            val transaction:FragmentTransaction = supportFragmentManager.beginTransaction()
            transaction.replace(R.id.f_container, fragment)
            transaction.addToBackStack(null)
            transaction.commit()
        }

在这种情况下,我没有 R.id.f_container,因为我只使用 compose 创建 UI。

<FrameLayout
    android:id="@+id/f_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"`enter code here`
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    app:layout_constraintEnd_toEndOf="parent"
    tools:layout_editor_absoluteY="-56dp">
</FrameLayout>

【问题讨论】:

  • 片段需要一个ViewGroup 容器。这不太可能改变。因此,如果您想继续使用 Fragment,则需要在适当的位置添加 ViewGroup。现在,由于 Compose/view 互操作性非常“正在进行中”,这可能意味着您的片段将需要进入传统布局。
  • @Thaw De Zin 如果您找到了问题的解决方案,请告诉我

标签: android kotlin android-fragments android-jetpack-compose


【解决方案1】:

我不建议您重用现有的片段,而是尝试回收其内部视图来创建新的可组合。

无论如何,如果您想在这里玩得开心,这是一个可能的解决方案:

AndroidView(
modifier = Modifier
    .fillMaxHeight()
    .fillMaxWidth(),
factory = { context ->
    FrameLayout(context).apply {
        FragmentBlankBinding.inflate(LayoutInflater.from(context), this, true).root
    }
})

享受吧!

【讨论】:

    【解决方案2】:

    您可以创建自己的@Composable FragmentContainer 函数

    @Composable
    fun FragmentContainer(
        modifier: Modifier = Modifier,
        fragmentManager: FragmentManager,
        commit: FragmentTransaction.(containerId: Int) -> Unit
    ) {
        val containerId by rememberSaveable { mutableStateOf(View.generateViewId()) }
        var initialized by rememberSaveable { mutableStateOf(false) }
        AndroidView(
            modifier = modifier,
            factory = { context ->
                FragmentContainerView(context)
                    .apply { id = containerId }
            },
            update = { view ->
                if (!initialized) {
                    fragmentManager.commit { commit(view.id) }
                    initialized = true
                } else {
                    fragmentManager.onContainerAvailable(view)
                }
            }
        )
    }
    
    /** Access to package-private method in FragmentManager through reflection */
    private fun FragmentManager.onContainerAvailable(view: FragmentContainerView) {
        val method = FragmentManager::class.java.getDeclaredMethod(
            "onContainerAvailable",
            FragmentContainerView::class.java
        )
        method.isAccessible = true
        method.invoke(this, view)
    }
    

    然后在活动中使用它

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            FragmentContainer(
                modifier = Modifier.fillMaxSize(),
                fragmentManager = supportFragmentManager,
                commit = { add(it, YourFragment()) }
            )
        }
    }
    

    或在片段中

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View = ComposeView(requireContext()).apply {
        setContent {
            FragmentContainer(
                modifier = Modifier.fillMaxSize(),
                fragmentManager = parentFragmentManager,
                commit = { add(it, YourNestedFragment()) }
            )
        }
    }
    

    【讨论】:

      【解决方案3】:

      如果您正在创建一个新应用,您可以完全跳过使用 Fragments,而只使用可组合的函数来表示您的屏幕。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-12-18
        • 1970-01-01
        • 1970-01-01
        • 2023-01-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多