ComposeView的使用:

一、 ComposeView 核心使用指南

ComposeView 是 Android 原生视图系统(View)和 Jetpack Compose 之间的 "桥梁",核心作用是在传统 View 布局(XML / 代码创建)中嵌入 Compose 界面,比如在 Activity/Fragment/ 自定义 View 中使用 Compose 写局部 UI。

1、前置条件(必配)

首先确保项目已集成 Compose,在 Module 的 build.gradle 中配置:

arduino 复制代码
android { 
   buildFeatures { 
       compose true // 启用 Compose 
   } 
 
  composeOptions { 
    kotlinCompilerExtensionVersion "1.5.3" // 需和 Kotlin 版本匹配(比如 Kotlin 1.9.0 对应 1.5.3) 
   } 
  } 

dependencies { 
 // Compose 核心依赖 
 implementation "androidx.compose.ui:ui:1.6.0" 
 implementation "androidx.compose.material:material:1.6.0"     implementation "androidx.activity:activity-compose:1.8.2" // 关联生命周期 
}

二 、核心使用场景(按频率排序)

场景 1:在 XML 布局中嵌入 ComposeView(最常用)

步骤 1:编写 XML 布局(比如 activity_main.xml
xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <!-- 原生 View -->
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="原生View区域"/>

    <!-- 嵌入 ComposeView -->
    <androidx.compose.ui.platform.ComposeView
        android:id="@+id/compose_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>
步骤 2:在 Activity/Fragment 中绑定并设置 Compose 内容
kotlin 复制代码
// Activity 示例,
//注意:必须是FragmentActivity,选择AppCompatActivity会报Theme错误;
class MainActivity : FragmentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // 找到 ComposeView 并设置 Compose 内容
        val composeView = findViewById<ComposeView>(R.id.compose_view)
        composeView.setContent {
            // 这里写 Compose 代码(和纯 Compose 写法完全一致)
            MaterialTheme {
                Column(
                    modifier = Modifier
                        .fillMaxWidth()
                        .padding(16.dp),
                    horizontalAlignment = Alignment.CenterHorizontally
                ) {
                    Text(text = "Compose 嵌入区域", fontSize = 20.sp)
                    Button(onClick = { Toast.makeText(this@MainActivity, "点击按钮", Toast.LENGTH_SHORT).show() }) {
                        Text("Compose 按钮")
                    }
                }
            }
        }
    }
}

场景 2:纯代码创建 ComposeView(无需 XML)

适合动态添加 Compose 界面到原生 View 容器中:

kotlin 复制代码
//AppCompatActivity会报错  
class MainActivity : FragmentActivity () {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // 1. 创建 ComposeView 实例
        val composeView = ComposeView(this).apply {
            // 2. 设置 Compose 内容
            setContent {
                MaterialTheme {
                    Text("纯代码创建的 ComposeView", modifier = Modifier.padding(16.dp))
                }
            }
        }

        // 3. 将 ComposeView 添加到原生 View 容器(比如 LinearLayout)
        val rootLayout = LinearLayout(this).apply {
            orientation = LinearLayout.VERTICAL
            layoutParams = ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)
        }
        rootLayout.addView(composeView)

        // 4. 设置为 Activity 布局
        setContentView(rootLayout))
    }
}

场景 3:在 Fragment 中使用 ComposeView

核心是绑定 viewLifecycleOwner,避免生命周期泄漏:

kotlin 复制代码
class MyFragment : Fragment() {
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        // 方式1:从 XML 加载(推荐)
        val view = inflater.inflate(R.layout.fragment_my, container, false)
        val composeView = view.findViewById<ComposeView>(R.id.compose_view)

        // 关键:关联 Fragment 的视图生命周期
        composeView.setViewCompositionStrategy(
            ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed
        )
        composeView.setContent {
            MaterialTheme {
                Text("Fragment 中的 ComposeView")
            }
        }
        return view
    }
}

场景 4:在自定义 View 中嵌入 ComposeView

scss 复制代码
class MyCustomView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : LinearLayout(context, attrs, defStyleAttr) {

    init {
        orientation = VERTICAL

        // 添加原生 View
        addView(TextView(context).apply {
            text = "自定义 View 中的原生文本"
            layoutParams = LayoutParams(MATCH_PARENT, WRAP_CONTENT)
        })

        // 添加 ComposeView
        val composeView = ComposeView(context).apply {
            layoutParams = LayoutParams(MATCH_PARENT, WRAP_CONTENT)
            setContent {
                MaterialTheme {
                    Text("自定义 View 中的 Compose 文本")
                }
            }
        }
        addView(composeView)
    }
}

三 、自己写的Demo

1、HomeActivity

kotlin 复制代码
class HomeActivity: FragmentActivity (){

    @SuppressLint("MissingInflatedId")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContentView(R.layout.activity_home)
        
        val composeView = findViewById<ComposeView>(R.id.compose_view)
        //使用Compose写代码
        BuyCarUtils.bindComposeView(composeView)
    }
}

2、activity_home.xml

ini 复制代码
<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical"
    >
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="XML页面嵌套Compose代码"
        android:gravity="center"
        android:textSize="25dp"
        android:textColor="@color/purple_700"
        />
        <androidx.compose.ui.platform.ComposeView
            android:id="@+id/compose_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="12dp"
            />

</LinearLayout>

3、BuyCarUtils

kotlin 复制代码
object BuyCarUtils {

    @JvmStatic
    fun bindComposeView(composeView: ComposeView) {
        composeView.apply {
           setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
            setContent {
                AdapterDesignWidthByCompositionLocalProvider() {
                   BuyCarPage()
                }
            }
        }
    }
}

@Composable
private fun BuyCarPage() {
    Column (modifier = Modifier.padding(start = 12.dp).clickable {
        Log.d("lyy","---哈哈哈,点我了----")
    }){
        Text(text = "hello compose",
            color = Color.Black,
            fontSize = 15.sp,
        )

        Text(text = "hello 世界",
            color = Color.Black,
            fontSize = 15.sp,
        )
    }
}

@Preview(showBackground = true)
@Composable
private fun PreviewBuyCarPage() {
    BuyCarPage()
}

4、使用AppCompatActivity报错:

csharp 复制代码
- Caused by: java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity.

- java.lang.RuntimeException: Unable to start activity ComponentInfo{com.lyy.mydemo4/com.lyy.mydemo4.HomeActivity}: java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity.
class HomeActivity: FragmentActivity (){

结论:主题报错,把继承类AppCompatActivity 改为 FragmentActivity就行了。

相关推荐
两万五千个小时17 小时前
Agent 任务没做完就停了?我扒了 Claude Code 源码,找到了 4 层原因
人工智能·程序员·架构
CodeSheep19 小时前
DeepSeek的最新招人标准,太讽刺了。
前端·后端·程序员
SimonKing19 小时前
frontend-dev vs ui-ux-pro-max:谁才是Vibe Coding前端开发的“最强辅助”?
java·后端·程序员
Coffeeee21 小时前
用了一段时间的AI了,忍不住想吐点槽,你的AI帮你提效了吗?
前端·人工智能·程序员
刀法如飞1 天前
【合并已排序数组的三种实现策略,哪一种更可取?】
算法·程序员
小兵张健1 天前
30天减20斤挑战:少一斤发100红包(2)
后端·程序员·全栈
程序员cxuan2 天前
我开发了一个排版工具
程序员·前端框架
魔术师Grace2 天前
AI 浪潮下,拉开差距的不是工具,而是位置
人工智能·程序员
Hilaku2 天前
做了 6 年前端,技术不差却拿不到 Offer?
前端·javascript·程序员
程序员鱼皮2 天前
傻子可懂的 Harness Engineering 入门教程 + 项目实战,一次搞懂 AI 编程工程化!
ai·程序员·编程·ai编程·#计算机