• Kotlin Compose 与原生 嵌套使用


    依赖

    1. android {
    2. ...
    3. kotlinOptions {
    4. jvmTarget = '1.8'
    5. useIR = true
    6. }
    7. buildFeatures {
    8. ...
    9. compose true
    10. }
    11. composeOptions {
    12. kotlinCompilerExtensionVersion rootProject.composeVersion
    13. }
    14. }
    15. dependencies {
    16. ...
    17. // Compose
    18. implementation "androidx.compose.runtime:runtime:$rootProject.composeVersion"
    19. implementation "androidx.compose.ui:ui:$rootProject.composeVersion"
    20. implementation "androidx.compose.foundation:foundation:$rootProject.composeVersion"
    21. implementation "androidx.compose.foundation:foundation-layout:$rootProject.composeVersion"
    22. implementation "androidx.compose.material:material:$rootProject.composeVersion"
    23. implementation "androidx.compose.runtime:runtime-livedata:$rootProject.composeVersion"
    24. implementation "androidx.compose.ui:ui-tooling:$rootProject.composeVersion"
    25. implementation "com.google.android.material:compose-theme-adapter:$rootProject.composeVersion"
    26. ...
    27. }

    用到的版本如下

    1. /*
    2. * Copyright 2018 Google LLC
    3. *
    4. * Licensed under the Apache License, Version 2.0 (the "License");
    5. * you may not use this file except in compliance with the License.
    6. * You may obtain a copy of the License at
    7. *
    8. * https://www.apache.org/licenses/LICENSE-2.0
    9. *
    10. * Unless required by applicable law or agreed to in writing, software
    11. * distributed under the License is distributed on an "AS IS" BASIS,
    12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13. * See the License for the specific language governing permissions and
    14. * limitations under the License.
    15. */
    16. buildscript {
    17. // Define versions in a single place
    18. ext {
    19. // Sdk and tools
    20. compileSdkVersion = 31
    21. minSdkVersion = 21
    22. targetSdkVersion = 31
    23. // App dependencies
    24. appCompatVersion = '1.4.1'
    25. composeVersion = '1.1.1'
    26. constraintLayoutVersion = '2.1.3'
    27. coreTestingVersion = '2.1.0'
    28. coroutinesVersion = "1.6.0"
    29. // TODO: Updating to 3.4.0 leads to dependency conflicts
    30. espressoVersion = '3.3.0'
    31. fragmentVersion = '1.4.1'
    32. glideVersion = '4.12.0'
    33. gradleVersion = '7.2.0'
    34. gsonVersion = '2.8.6'
    35. junitVersion = '4.13.2'
    36. kotlinVersion = '1.6.10'
    37. ktlintVersion = '0.37.2'
    38. ktxVersion = '1.7.0'
    39. lifecycleVersion = '2.4.0'
    40. materialVersion = '1.5.0'
    41. materialComposeAdapterVersion = '1.1.5'
    42. navigationVersion = '2.5.0-alpha01'
    43. recyclerViewVersion = '1.2.1'
    44. roomVersion = '2.4.1'
    45. runnerVersion = '1.0.1'
    46. truthVersion = '1.1.2'
    47. testExtJunit = '1.1.3'
    48. uiAutomatorVersion = '2.2.0'
    49. viewPagerVersion = '1.0.0'
    50. workVersion = '2.7.1'
    51. }
    52. repositories {
    53. google()
    54. mavenCentral()
    55. }
    56. dependencies {
    57. classpath "com.android.tools.build:gradle:$gradleVersion"
    58. classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
    59. classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$navigationVersion"
    60. }
    61. }
    62. plugins {
    63. id "com.diffplug.spotless" version "5.12.4"
    64. }
    65. allprojects {
    66. repositories {
    67. google()
    68. mavenCentral()
    69. }
    70. }
    71. spotless {
    72. kotlin {
    73. target "**/*.kt"
    74. targetExclude("$buildDir/**/*.kt")
    75. targetExclude('bin/**/*.kt')
    76. ktlint(ktlintVersion)
    77. }
    78. }

    这次我们修改 原生布局为Compse

    这些布局为 

    ConstraintLayout  且里面有四个TextView
    1. <androidx.constraintlayout.widget.ConstraintLayout
    2. android:layout_width="match_parent"
    3. android:layout_height="match_parent"
    4. android:layout_margin="@dimen/margin_normal">
    5. <TextView
    6. android:id="@+id/plant_detail_name"
    7. android:layout_width="0dp"
    8. android:layout_height="wrap_content"
    9. android:layout_marginStart="@dimen/margin_small"
    10. android:layout_marginEnd="@dimen/margin_small"
    11. android:gravity="center_horizontal"
    12. android:text="@{viewModel.plant.name}"
    13. android:textAppearance="?attr/textAppearanceHeadline5"
    14. app:layout_constraintEnd_toEndOf="parent"
    15. app:layout_constraintStart_toStartOf="parent"
    16. app:layout_constraintTop_toTopOf="parent"
    17. tools:text="Apple" />
    18. <TextView
    19. android:id="@+id/plant_watering_header"
    20. android:layout_width="0dp"
    21. android:layout_height="wrap_content"
    22. android:layout_marginStart="@dimen/margin_small"
    23. android:layout_marginTop="@dimen/margin_normal"
    24. android:layout_marginEnd="@dimen/margin_small"
    25. android:gravity="center_horizontal"
    26. android:text="@string/watering_needs_prefix"
    27. android:textColor="?attr/colorAccent"
    28. android:textStyle="bold"
    29. app:layout_constraintEnd_toEndOf="parent"
    30. app:layout_constraintStart_toStartOf="parent"
    31. app:layout_constraintTop_toBottomOf="@id/plant_detail_name" />
    32. <TextView
    33. android:id="@+id/plant_watering"
    34. android:layout_width="0dp"
    35. android:layout_height="wrap_content"
    36. android:layout_marginStart="@dimen/margin_small"
    37. android:layout_marginEnd="@dimen/margin_small"
    38. android:gravity="center_horizontal"
    39. app:layout_constraintEnd_toEndOf="parent"
    40. app:layout_constraintStart_toStartOf="parent"
    41. app:layout_constraintTop_toBottomOf="@id/plant_watering_header"
    42. app:wateringText="@{viewModel.plant.wateringInterval}"
    43. tools:text="every 7 days" />
    44. <TextView
    45. android:id="@+id/plant_description"
    46. style="?android:attr/textAppearanceMedium"
    47. android:layout_width="0dp"
    48. android:layout_height="wrap_content"
    49. android:layout_marginStart="@dimen/margin_small"
    50. android:layout_marginTop="@dimen/margin_small"
    51. android:layout_marginEnd="@dimen/margin_small"
    52. android:minHeight="@dimen/plant_description_min_height"
    53. app:layout_constraintEnd_toEndOf="parent"
    54. app:layout_constraintStart_toStartOf="parent"
    55. app:layout_constraintTop_toBottomOf="@id/plant_watering"
    56. app:renderHtml="@{viewModel.plant.description}"
    57. tools:text="Details about the plant" />
    58. </androidx.constraintlayout.widget.ConstraintLayout>

    我们注释掉这些布局并替换为

    1. <androidx.compose.ui.platform.ComposeView
    2. android:id="@+id/compose_view"
    3. android:layout_width="match_parent"
    4. android:layout_height="match_parent">
    5. </androidx.compose.ui.platform.ComposeView>

    ComposeView

     找到这个view的Id并对其进行设置

    整个Compose的代码如下

    1. /*
    2. * Copyright 2020 Google LLC
    3. *
    4. * Licensed under the Apache License, Version 2.0 (the "License");
    5. * you may not use this file except in compliance with the License.
    6. * You may obtain a copy of the License at
    7. *
    8. * https://www.apache.org/licenses/LICENSE-2.0
    9. *
    10. * Unless required by applicable law or agreed to in writing, software
    11. * distributed under the License is distributed on an "AS IS" BASIS,
    12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13. * See the License for the specific language governing permissions and
    14. * limitations under the License.
    15. */
    16. package com.google.samples.apps.sunflower.plantdetail
    17. import android.content.res.Configuration
    18. import android.text.method.LinkMovementMethod
    19. import android.widget.TextView
    20. import androidx.compose.foundation.layout.*
    21. import androidx.compose.material.MaterialTheme
    22. import androidx.compose.material.Surface
    23. import androidx.compose.material.Text
    24. import androidx.compose.runtime.Composable
    25. import androidx.compose.runtime.getValue
    26. import androidx.compose.runtime.livedata.observeAsState
    27. import androidx.compose.ui.Alignment
    28. import androidx.compose.ui.Modifier
    29. import androidx.compose.ui.platform.LocalContext
    30. import androidx.compose.ui.res.dimensionResource
    31. import androidx.compose.ui.res.stringResource
    32. import androidx.compose.ui.text.font.FontWeight
    33. import androidx.compose.ui.tooling.preview.Preview
    34. import androidx.compose.ui.unit.dp
    35. import androidx.compose.ui.viewinterop.AndroidView
    36. import androidx.core.text.HtmlCompat
    37. import androidx.core.widget.TextViewCompat
    38. import com.google.android.material.composethemeadapter.MdcTheme
    39. import com.google.samples.apps.sunflower.R
    40. import com.google.samples.apps.sunflower.data.Plant
    41. import com.google.samples.apps.sunflower.viewmodels.PlantDetailViewModel
    42. import kotlin.math.min
    43. @Composable //Stateful :opinionated
    44. fun PlantDetailDescription(plantDetailViewModel: PlantDetailViewModel) {
    45. val currentPlant by plantDetailViewModel.plant.observeAsState()
    46. currentPlant?.let { plant ->
    47. PlantDetailDescription(plant)
    48. }
    49. }
    50. @Composable //Stateless:Preview+reusable
    51. private fun PlantDetailDescription(plant: Plant) {
    52. Surface {
    53. Column(modifier = Modifier
    54. .padding(dimensionResource(id = R.dimen.margin_normal))) {
    55. PlantName(plant.name)
    56. //Watering
    57. PlantWatering(plant.wateringInterval)
    58. //PlantDescription
    59. PlantDescription(description = plant.description)
    60. }
    61. }
    62. }
    63. @Composable
    64. fun PlantWatering(wateringInterval: Int) {
    65. Column(horizontalAlignment = Alignment.CenterHorizontally,
    66. modifier = Modifier
    67. .padding(horizontal = dimensionResource(id = R.dimen.margin_normal)
    68. )
    69. .fillMaxWidth()
    70. ) {
    71. Text(text = stringResource(id = R.string.watering_needs_prefix),
    72. modifier = Modifier
    73. .padding(top = dimensionResource(id = R.dimen.margin_normal)),
    74. color = MaterialTheme.colors.primaryVariant,
    75. fontWeight = FontWeight.Bold
    76. )
    77. val resources = LocalContext.current.resources
    78. val quantityString = resources.getQuantityString(
    79. R.plurals.watering_needs_suffix,
    80. wateringInterval, wateringInterval
    81. )
    82. Text(text = quantityString)
    83. }
    84. }
    85. @Composable
    86. fun PlantDescription(description: String) {
    87. AndroidView(factory = { context ->
    88. TextView(context).apply {
    89. movementMethod = LinkMovementMethod.getInstance()
    90. TextViewCompat.setTextAppearance(this, android.R.style.TextAppearance_Medium)
    91. }
    92. },
    93. update = { tv ->
    94. tv.text = HtmlCompat.fromHtml(description, HtmlCompat.FROM_HTML_MODE_COMPACT)
    95. },
    96. modifier =
    97. Modifier
    98. .padding(horizontal = dimensionResource(id = R.dimen.margin_small))
    99. .padding(top = dimensionResource(id = R.dimen.margin_small))
    100. .heightIn(min = dimensionResource(id = R.dimen.plant_description_min_height))
    101. )
    102. }
    103. @Composable
    104. fun PlantName(name: String) {
    105. Text(text = name,
    106. modifier = Modifier
    107. .padding(horizontal = dimensionResource(id = R.dimen.margin_small))
    108. .fillMaxWidth()
    109. .wrapContentWidth(Alignment.CenterHorizontally),
    110. style = MaterialTheme.typography.h5
    111. )
    112. }
    113. @Preview
    114. @Composable
    115. fun PlantNamePreview() {
    116. PlantName(name = "狗蛋")
    117. }
    118. @Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
    119. @Preview
    120. @Composable
    121. fun PlantDetailDescriptionPreview() {
    122. val fakePlant = Plant("asd", "asdas", "dasdahjskdhjasdj", 1, 3, "")
    123. MdcTheme() {
    124. PlantDetailDescription(plant = fakePlant)
    125. }
    126. }

    在第四个的TextView用到了spnner 也就是html文本

    其实。这个时候compose是暂时不支持的

    我们要切换到原生view

    大家看到这个了吗

    PlantDescription
    1. @Composable
    2. fun PlantDescription(description: String) {
    3. AndroidView(factory = { context ->
    4. TextView(context).apply {
    5. movementMethod = LinkMovementMethod.getInstance()
    6. TextViewCompat.setTextAppearance(this, android.R.style.TextAppearance_Medium)
    7. }
    8. },
    9. update = { tv ->
    10. tv.text = HtmlCompat.fromHtml(description, HtmlCompat.FROM_HTML_MODE_COMPACT)
    11. },
    12. modifier =
    13. Modifier
    14. .padding(horizontal = dimensionResource(id = R.dimen.margin_small))
    15. .padding(top = dimensionResource(id = R.dimen.margin_small))
    16. .heightIn(min = dimensionResource(id = R.dimen.plant_description_min_height))
    17. )
    18. }

    对其进行设置 就可以了。 而不是引入textView xml了。

    这就要求我们充分的使用Compose咯

  • 相关阅读:
    ELF格式分析动态链接原理
    获得Windows官方映像(ISO)
    Js逆向教程-09常见的加密方式
    同样是数据库 SQL和MySQL的区别是什么?
    [蓝桥杯 2022 省 B] 统计子矩阵
    python -- PyQt5(designer)中文详细教程(五)对话框
    一次网络请求的流程
    【华为OD机试python】评论转换输出【2023 B卷|100分】
    js中如何实现一个简单的防抖函数?
    如何使用Node.js、TypeScript和Express实现RESTful API服务
  • 原文地址:https://blog.csdn.net/mp624183768/article/details/125591127