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就行了。

相关推荐
文心快码BaiduComate5 小时前
Comate 3月全新升级:全新Plan模式、Explore Subagent深度检索能力增强
前端·后端·程序员
雨落Re5 小时前
谈谈我与AI的这几年
程序员·ai编程
SimonKing6 小时前
Spring Boot 动态多数据源:核心思路与关键考量
java·后端·程序员
唐叔在学习6 小时前
为了不付费,我硬生生用AI开发了一个跨平台待办应用
后端·程序员·ai编程
一拳不是超人7 小时前
龙虾🦞(OpenClaw) 本地部署体验:是真变革还是旧酒装新瓶?
前端·人工智能·程序员
databook1 天前
在AI的世界里,做一个真实的人
人工智能·程序员·创业
程序员鱼皮1 天前
VSCode + Copilot 保姆级 AI 编程实战教程,免费用 Claude,夯爆了!
vscode·ai·程序员·编程·ai编程
SimonKing1 天前
震撼:Qoder 搭载Qwen3.2-Plus模型,5步实现完整的多数据源切换
java·后端·程序员
Cyning1 天前
AI Content Automation Platform · 开发日志 Day1
程序员