互操作配方

此配方演示了如何在 Navigation3 应用中使用 AndroidFragmentAndroidView

功能

  • AndroidFragment:展示了如何在可组合目的地中嵌入 Fragment。
  • AndroidView:展示了如何在可组合项目的地中嵌入经典 Android View。

关键组件

  • InteropActivity:托管导航的主 activity。
  • MyCustomFragment:示例中使用的简单 Fragment。
  • AndroidFragment<T>:用于托管 Fragment 的可组合项。
  • AndroidView:用于托管 Android View 的可组合项。

用法

  1. 运行 InteropActivity
  2. 初始界面显示一个 Fragment。
  3. 点击“前往视图”,前往显示 TextView 的界面。
package com.example.nav3recipes.interop

import android.annotation.SuppressLint
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.fragment.app.Fragment

class MyCustomFragment : Fragment() {
    @SuppressLint("SetTextI18n")
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        return TextView(requireContext()).apply {
            text = "My Fragment"
        }
    }
}
package com.example.nav3recipes.interop

import android.annotation.SuppressLint
import android.os.Bundle
import android.widget.TextView
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.ui.Modifier
import androidx.compose.ui.viewinterop.AndroidView
import androidx.fragment.app.FragmentActivity
import androidx.fragment.compose.AndroidFragment
import androidx.lifecycle.compose.dropUnlessResumed
import androidx.navigation3.runtime.NavKey
import androidx.navigation3.runtime.entryProvider
import androidx.navigation3.runtime.rememberNavBackStack
import androidx.navigation3.ui.NavDisplay
import com.example.nav3recipes.ui.setEdgeToEdgeConfig
import kotlinx.serialization.Serializable

@Serializable
private data object FragmentRoute : NavKey

@Serializable
private data class ViewRoute(val id: String) : NavKey

class InteropActivity : FragmentActivity() {

    @SuppressLint("SetTextI18n")
    override fun onCreate(savedInstanceState: Bundle?) {
        setEdgeToEdgeConfig()
        super.onCreate(savedInstanceState)
        setContent {
            val backStack = rememberNavBackStack(FragmentRoute)

            NavDisplay(
                backStack = backStack,
                onBack = { backStack.removeLastOrNull() },
                entryProvider = entryProvider {
                    entry<FragmentRoute> {
                        Column(Modifier.fillMaxSize().wrapContentSize()) {
                            AndroidFragment<MyCustomFragment>()
                            Button(onClick = dropUnlessResumed {
                                backStack.add(ViewRoute("123"))
                            }) {
                                Text("Go to View")
                            }
                        }
                    }
                    entry<ViewRoute> { key ->
                        AndroidView(
                            modifier = Modifier.fillMaxSize().wrapContentSize(),
                            factory = { context ->
                                TextView(context).apply {
                                    text = "My View with key: ${key.id}"
                                }
                            }
                        )
                    }
                }
            )
        }
    }
}