Compose和XML的代码互相调用
传统 xml 布局项目中使用 Compose 方法
就像第一次使用kt一样,很多项目都是java和kt混着用,在难以确保开发协同工作人员同等技术追求(比如有的人想用Compose、有的人不想)的情况下,这种情况极易发生。所以传统XML布局和Compose方法互相调用的场景发生了也很正常。
相应的,谷歌公司已经考虑到这种情况,Compose 工具包已经提供了 androidx.compose.ui.platform.ComposeView 供在XML文件中使用Compose。
比如一个空的Activity布局xml文件中,我们加入 androidx.compose.ui.platform.ComposeView 如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv_xml"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextView For XML"
android:layout_gravity="center_horizontal"/>
<androidx.compose.ui.platform.ComposeView
android:id="@+id/tv_compose"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
很常规的一段代码,只是Compose里的组件通过androidx.compose.ui.platform.ComposeView来声明,这个时候在activity里通过findViewById来获取实例:
val mTvCompose = findViewById<ComposeView>(R.id.tv_compose)
注意这里的findViewById后是个再接的id。
这时候就可以把他当做在compose中组件来用了。
val mTvXml = findViewById<TextView>(R.id.tv_xml)
val mTvCompose = findViewById<ComposeView>(R.id.tv_compose)
mTvXml.text = "This is a TextView for XML"
mTvCompose.setContent {
Column() {
Text(text = "这是Compose组件")
Text(text = "成功调用")
}
}
对应的显示效果为:
使用addView()来添加View对于ComposeView来说也同样可以,具体形式为:
setContentView(LinearLayout(this).apply {
orientation = VERTICAL
addView(ComposeView(this@MainActivity).apply {
id = R.id.ll_layout
setContent {
MaterialTheme {
Text("LinearLayout Compose View")
}
}
})
addView(TextView(context).apply {
text = "TextView for xml"
})
addView(ComposeView(context).apply {
id = R.id.tv_compose
setContent {
MaterialTheme {
Text("ComposeView here")
}
}
})
})
Compose中使用View
唯物主义常说,事物往往都具有两面性,有在XML中想用Compose的情况,就会有在Compose中想用传统View的情况(比如想使用一些以前写好的自定义View、要用的View还没有Compose版本,,比如AdView, WebView之类的),同样Google也提供了 AndroidView 来实现这种操作。
例如以下代码:
setContent {
AndroidView(factory = {
TextView(it)
}){
it.apply {
text = "这是Compose里引用原生的TextView"
}
}
}
对应的效果为:
这时,我们看这个方法的构造函数:
@Composable
fun <T : View> AndroidView(
factory: (Context) -> T,
modifier: Modifier = Modifier,
update: (T) -> Unit = NoOpUpdate
)
不难看出,这里的factory接收一个Context参数, 用来构建一个View。Modifier是修饰符,这个之前我们详细讲解过,可以花式定义组件的函数。update()是一个callback,inflate之后会执行,读取的状态state值变化后也会被执行。
上述的代码是将TextView作为factory参数传入进去来构建一个View的。构建成功后会使用lamba调用后面{}内容(这句话可能没描述清楚)。
至此,算是成功在Compose中使用View了。啥,问我怎么在.java文件中调用Compose?不好意思,Compose只支持kotlin文件中调用。
Compose & View
从上述代码中,不难看出:
ComposeView其实是个Android的View。
AndroidView其实是个Compose函数。
AndroidView和ComposeView是采用传统XML的View和Compose组件互相调用的桥梁。
更多推荐
所有评论(0)