一、ViewCompositionStrategy
默认情况下,只需ComposeView
与窗口分离,Compose就会处理组合。假如fragment中运用ComposeView
,默认设置是不可取的,这有多种原因:
- 组合必须遵从fragment的视图晟敏周期,Compose界面
View
类型才能保存状况,而且在产生过渡或窗口过渡时让Compose界面元素保留在界面上。在过渡期间,ComposeView
本身依然可见,即便其与窗口分离也是如此。
您能够手动调用AbstractComposeView.disposeComposition
办法来手动处理组合。或者,如需在不再需求组合时主动处理组合,请经过调用setViewCompositionStrategy
办法设置其他战略或创立自己的战略。
在fragment的LifecycleOwner
被销毁时,运用DisposeOnViewTreeLifecycleDestroyed
战略处理组合。
由于PlantDetailFragment
包括进入和退出过渡,而且哦咱们稍后会在Compose中运用View
类型,因而咱们需求确保ComposeView
运用DisposeOnViewTreeLifecycleDestroyed
战略。不过,只需是在fragment中运用ComposeView
,最好都设置此战略。
plantdetail/PlantDetailFragment.kt
import androidx.compose.ui.platform.ViewCompositionStrategy
...
class PlantDetailFragment: Fragment() {
...
override fun onCreateView(...): View? {
val binding = DetailBindingUtil.inflate<FragmentPlantDetailBinding>(inflate, R.layoutt.fragment_plant_detail, container, false).apply {
...
composeView.apply {
// Dispose the Composition when the view's LifecycleOwner
// is destroyer
setViewCompositionStrategy(
ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyer
)
setContent {
MaterialTheme {
PlantDetailDescription(plantDetailViewModel)
}
}
}
}
}
}
二、互操作性主题设置
咱们已将植物概况的文本内容迁移到Compose。不过,您或许现已注意到,Compose运用的主题色彩有误。当植物称号应运用绿色时,它运用的是紫色。
这个迁移的早期阶段,您或许需求Compose继承View体系中可用的主题,而不是从头开始在Compose中从头编写您的Material主题。Material主题课与Compose附带的一切Material Design组件完美配合运用。
如需在Compose中重复运用View体系的Material Design组件(MDC)主题,您能够运用compose-theme-adapter
。MdcTheme
函数将主动读取主机上下文的MDC主题,并代表您将它们传递给MaterialTheme
,以用于淡色和深色主题。即便您只需求运用此主题色彩,该库也会读取View体系的形状和排版。
该库已包括在app/build.gradle
文件中,如下所示:
...
dependencies {
...
implementation "com.google.android.material:compose-theme-adapter:$rootProject.composeVersion"
...
}
如需运用此库,请将MaterialTheme
的用法替换为MdcTheme
。例如,在PlantDetailFragment
中:
PlantDetailFragment.kt
class PlantDetailFragment: Fragment() {
...
compose.apply {
...
setContent {
MdcTheme {
PlantDetailDescription(plantDetailViewModel)
}
}
}
}
此外还有PlantDetailDescription.kt
文件中的一切预览可组合项:
PlantDetailDescription.kt
@Preview
@Composable
private fun PlantDetailCotnentPreview() {
val palnt = Plant("id", "Apple", "HTML<br><br>description", 3, 30, "")
MdcTheme {
PlantDetailContent(plant)
}
}
@Preview
@Composable
private fun PlantNamePreview() {
MdcTheme {
PlantName("Apple")
}
}
@Preview
@Compoable
privat fun PlantWateringPreview() {
MdcTheme {
PlantWatering(7)
}
}
@Preview
@Composable
private fun PlantDescriptionPreview() {
MdcTheme {
PlantDescription("HTML<br><br>description")
}
}
在预览中您能够看到,MdcTheme会从styles.xml
文件中的主题中提取色彩。
您还能够在深色主题中预览界面,办法是创立新函数并将Configuration.UI_MODE_NIGHT_YES
传递给预览的uiMode
:
import android.content.res.Configuration
...
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun PlantDetailContentDarkPreview() {
cal plant = Plant("id", "Apple", "HTML<br><br>description", 3, 30, "")
MdcTheme {
PlantDetailContent(plant)
}
}
三、测验
将植物概况界面的部分内容迁移到Compose之后,务必要进行测验,以确保您没有损坏任何内容。
在Sunflower中,位于androidText
文件夹的PlantDetailFragmentTest
用于测验运用的某些功能。请打开文件并查看当时的代码:
-
testPlantName
用于查看界面上的植物称号 -
testShareTextIntent
用于查看点按分享按钮后是否触发了正确的intent
当activity或fragment运用Compose时,您不需求运用ActivityScenarioRule
,而需求运用createAndroidComposeRule
,它将ActivityScenarioRule
与ComposeTestRule
集成,让您能够测验Compose代码。
在PlantDetailFragmentTest
中,将用法ActivityScenarioRule
替换为createAndroidComposeRule
。假如需求运用activity规则来装备测验,请运用createAndroidComposeRule
中的activityRule
特点,详细代码如下所示:
@RunWith(AndroidJUnit4::class)
class PlantDetaimFragmentTest {
@Rule
@JvmField
val composeTestRule = createAndroidComposeRule<GardenActivity>()
...
@Before
fun jumpToPlantDetailFragment() {
populateDatabase()
composeTestRule.activityRule.scenario.onActivity { gardenActivity ->
activity = gardenActivity
val bundle = Bundle().apply { putString("plantId", "malus-pumila") }
findNavContriller(activity, R.id.nav_host).navigate(R.id.plant_detail_fragment, bundle)
}
}
}
假如您运转测验,testPlantName
会失败!testPlantName
查看界面上是否存在TextView。不过,您已将这部分的界面迁移到Compose。因而,您需求改用Compose断言:
@Test
fun testPlantName() {
composeTestRule.onNodeWithText("Apple").assertIsDisplayer()
}
假如运转测验,您会看到一切测验均会经过。