您可以将基于 Compose 的界面添加到采用基于 View 的设计的现有应用中。
如需创建完全基于 Compose 的新屏幕,请让 activity 调用 setContent()
方法,并传递您想要使用的任何可组合函数。
class ExampleActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { // In here, we can call composables! MaterialTheme { Greeting(name = "compose") } } } } @Composable fun Greeting(name: String) { Text(text = "Hello $name!") }
这段代码看起来就和只含 Compose 元素的应用中的代码一样。
ComposeView
:ViewCompositionStrategy
ViewCompositionStrategy
用于定义应何时处置组合。默认值 ViewCompositionStrategy.Default
会在底层 ComposeView
与窗口分离时处理组合,除非它是池容器(例如 RecyclerView
)的一部分。在仅使用 Compose 的单 activity 应用中,您需要这种默认行为,但如果您要在代码库中逐步添加 Compose,这种行为在某些情况下可能会导致状态丢失。
如需更改 ViewCompositionStrategy
,请调用 setViewCompositionStrategy()
方法并提供其他策略。
下表总结了您可以使用 ViewCompositionStrategy
的不同场景:
ViewCompositionStrategy |
说明和互操作性场景 |
---|---|
DisposeOnDetachedFromWindow |
当底层 ComposeView 与窗口分离时,系统会处置组合。已被 DisposeOnDetachedFromWindowOrReleasedFromPool 取代。Interop 场景: * ComposeView 无论是在 View 层次结构中的唯一元素,还是在混合 View/Compose 屏幕(而非 Fragment)的上下文中。 |
DisposeOnDetachedFromWindowOrReleasedFromPool (默认) |
与 DisposeOnDetachedFromWindow 类似,当组合不在池化容器(例如 RecyclerView )中时。如果它位于池化容器中,则会在池化容器本身从窗口分离时或项被舍弃时(即池已满时)进行处置。Interop 场景: * ComposeView 无论它是 View 层次结构中的唯一元素,还是在混合 View/Compose 屏幕(而非 Fragment)的上下文中。* ComposeView 作为池化容器(例如 RecyclerView )中的项。 |
DisposeOnLifecycleDestroyed |
提供的 Lifecycle 被销毁时,系统会处理组合。Interop 场景 * Fragment 视图中的 ComposeView 。 |
DisposeOnViewTreeLifecycleDestroyed |
当视图附加到的下一个窗口的 ViewTreeLifecycleOwner.get 返回的 LifecycleOwner 拥有的 Lifecycle 被销毁时,系统会处置组合。Interop 场景: * Fragment 的 View 中的 ComposeView 。* 在生命周期尚未知晓的 View 中使用 ComposeView 。 |
Fragment 中的 ComposeView
如果您要将 Compose 界面内容并入 fragment 或现有 View 布局,请使用 ComposeView
并调用其 setContent()
方法。ComposeView
是一个 Android View
。
您可以将 ComposeView
放在 XML 布局中,就像放置其他任何 View
一样:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <androidx.compose.ui.platform.ComposeView android:id="@+id/compose_view" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
在 Kotlin 源代码中,通过 XML 中定义的布局资源使布局膨胀。然后,使用 XML ID 获取 ComposeView
,设置最适合宿主 View
的组合策略,并调用 setContent()
以使用 Compose。
class ExampleFragmentXml : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { val view = inflater.inflate(R.layout.fragment_example, container, false) val composeView = view.findViewById<ComposeView>(R.id.compose_view) composeView.apply { // Dispose of the Composition when the view's LifecycleOwner // is destroyed setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) setContent { // In Compose world MaterialTheme { Text("Hello Compose!") } } } return view } }
或者,您也可以使用视图绑定来获取对 ComposeView
的引用,方法是引用 XML 布局文件生成的绑定类:
class ExampleFragment : Fragment() { private var _binding: FragmentExampleBinding? = null // This property is only valid between onCreateView and onDestroyView. private val binding get() = _binding!! override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { _binding = FragmentExampleBinding.inflate(inflater, container, false) val view = binding.root binding.composeView.apply { // Dispose of the Composition when the view's LifecycleOwner // is destroyed setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) setContent { // In Compose world MaterialTheme { Text("Hello Compose!") } } } return view } override fun onDestroyView() { super.onDestroyView() _binding = null } }
图 1. 此图显示了在 View 界面层次结构中添加 Compose 元素的代码的输出。“Hello Android!”文本由 TextView
微件显示。“Hello Compose!”文本由 Compose 文本元素显示。
如果整个屏幕是使用 Compose 构建的,您还可以直接在 fragment 中添加 ComposeView
,这样可让您完全避免使用 XML 布局文件。
class ExampleFragmentNoXml : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { return ComposeView(requireContext()).apply { // Dispose of the Composition when the view's LifecycleOwner // is destroyed setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) setContent { MaterialTheme { // In Compose world Text("Hello Compose!") } } } } }
同一布局中的多个 ComposeView
实例
如果同一布局中存在多个 ComposeView
元素,每个元素必须具有唯一的 ID 才能使 savedInstanceState
发挥作用。
class ExampleFragmentMultipleComposeView : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View = LinearLayout(requireContext()).apply { addView( ComposeView(requireContext()).apply { setViewCompositionStrategy( ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed ) id = R.id.compose_view_x // ... } ) addView(TextView(requireContext())) addView( ComposeView(requireContext()).apply { setViewCompositionStrategy( ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed ) id = R.id.compose_view_y // ... } ) } }
ComposeView
ID 在 res/values/ids.xml
文件中进行定义:
<resources> <item name="compose_view_x" type="id" /> <item name="compose_view_y" type="id" /> </resources>
在布局编辑器中预览可组合项
您还可以在布局编辑器中预览包含 ComposeView
的 XML 布局的可组合项。这样,您就可以查看可组合项在混合 View 和 Compose 布局中的显示效果。
假设您想在布局编辑器中显示以下可组合项。请注意,带有 @Preview
注解的可组合项非常适合在布局编辑器中进行预览。
@Preview @Composable fun GreetingPreview() { Greeting(name = "Android") }
如需显示此可组合项,请使用 tools:composableName
tools 属性,并将其值设置为要在布局中预览的可组合项的完全限定名称。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <androidx.compose.ui.platform.ComposeView android:id="@+id/my_compose_view" tools:composableName="com.example.compose.snippets.interop.InteroperabilityAPIsSnippetsKt.GreetingPreview" android:layout_height="match_parent" android:layout_width="match_parent"/> </LinearLayout>
后续步骤
现在,您已经了解了在 View 中使用 Compose 的互操作性 API,接下来不妨了解如何在 Compose 中使用 View。
为您推荐
- 注意:当 JavaScript 处于关闭状态时,系统会显示链接文字
- 其他注意事项
- 迁移策略 {:#migration-strategy}
- 比较 Compose 和 View 的性能