写点什么

Jetpack Compose 和 View 的互操作性,这个回答让我错失 offer

用户头像
Android架构
关注
发布于: 刚刚

Jetpack Compose Interoperability


==============================================================================================


Compose 风这么大, 对于已有项目使用新技术, 难免会担心兼容性. 对于 Compose 来说, 至少和 View 的结合是无缝的. (目前来讲, 已有项目要采用 Compose, 可能初期要解决的就是升级 gradle plugin, gradle, Android Studio, kotlin 之类的问题.)


构建 UI 的灵活性还是有保证的:


  • 新界面想用 Compose, 可以.

  • Compose 支持不了的, 用 View.

  • 已有界面不想动, 可以不动.

  • 已有界面的一部分想用 Compose, 可以.

  • 有的 UI 效果想复用之前的, 好的, 可以直接拿来内嵌.


本文就是一些互相调用的简单小 demo, 初期用的时候可以复制粘贴一下很趁手.


官方文档: developer.android.com/jetpack/com…


在 Activity 或者 Fragment 中全部使用 Compose 来搭建 UI



Use Compose in Activity

class ExampleActivity : AppCompatActivity() {


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!")


}

Use Compose in Fragment

class PureComposeFragment : Fragment() {


override fun onCreateView(


inflater: LayoutInflater,


container: ViewGroup?,


savedInstanceState: Bundle?


): View {


return ComposeView(requireContext()).apply {


setContent {


MaterialTheme {


Text("Hello Compose!")


}


}


}


}


}


在 View 中使用 Compose



ComposeView 内嵌在 Xml 中:

一个平平无奇的 xml 布局文件中加入ComposeView:


<?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">


<TextView


android:id="@+id/hello_world"


android:layout_width="match_parent"


android:layout_height="wrap_content"


android:text="Hello from XML layout" />


<androidx.compose.ui.platform.ComposeView


android:id="@+id/compose_view"


android:layout_width="m


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


atch_parent"


android:layout_height="match_parent" />


</LinearLayout>


使用的时候, 先根据 id 查找出来, 再 setContent:


class ComposeViewInXmlActivity : AppCompatActivity() {


override fun onCreate(savedInstanceState: Bundle?) {


super.onCreate(savedInstanceState)


setContentView(R.layout.activity_compose_view_in_xml)


findViewById<ComposeView>(R.id.compose_view).setContent {


// In Compose world


MaterialTheme {


Text("Hello Compose!")


}


}


}


}

动态添加 ComposeView

在代码中使用addView()来添加 View 对于ComposeView来说也同样适用:


class ComposeViewInViewActivity : AppCompatActivity() {


override fun onCreate(savedInstanceState: Bundle?) {


super.onCreate(savedInstanceState)


setContentView(LinearLayout(this).apply {


orientation = VERTICAL


addView(ComposeView(this@ComposeViewInViewActivity).apply {


id = R.id.compose_view_x


setContent {


MaterialTheme {


Text("Hello Compose View 1")


}


}


})


addView(TextView(context).apply {


text = "I'm am old TextView"


})


addView(ComposeView(context).apply {


id = R.id.compose_view_y


setContent {


MaterialTheme {


Text("Hello Compose View 2")


}


}


})


})


}


}


这里在LinearLayout中添加了三个 child: 两个ComposeView中间还有一个TextView.


起到桥梁作用的ComposeView是一个ViewGroup, 它本身是一个 View, 所以可以混进 View 的 hierarchy tree 里占位, 它的setContent()方法开启了 Compose 世界的大门, 在这里可以传入 composable 的方法, 绘制 UI.


在 Compose 中使用 View




都用 Compose 搭建 UI 了, 什么时候会需要在其中内嵌 View 呢?


  • 要用的 View 还没有 Compose 版本, 比如AdView, MapView, WebView.

  • 有一块之前写好的 UI, (暂时或者永远)不想动, 想直接用.

  • 用 Compose 实现不了想要的效果, 就得用 View.

在 Compose 中加入 Android View

例子:


@Composable


fun CustomView() {


val state = remember { mutableStateOf(0) }


//widget.Button


AndroidView(


factory = { ctx ->


//Here you can construct your View


android.widget.Button(ctx).apply {


text = "My Button"


layoutParams = LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT)


setOnClickListener {


state.value++


}


}


},


modifier = Modifier.padding(8.dp)


)


//widget.TextView


AndroidView(factory = { ctx ->


//Here you can construct your View


TextView(ctx).apply {


layoutParams = LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT)


}


}, update = {


it.text = "You have clicked the buttons: " + state.value.toString() + " times"


})


}


这里的桥梁是AndroidView, 它是一个 composable 方法:


@Composable

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
Jetpack Compose和View的互操作性,这个回答让我错失offer