文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Android View与Compose互相调用的方法是什么

2023-07-05 02:00

关注

这篇文章主要讲解了“Android View与Compose互相调用的方法是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Android View与Compose互相调用的方法是什么”吧!

1. 前言

Compose 具有超强的兼容性,兼容现有的所有代码,Compose 能够与现有 View 体系并存,可实现渐进式替换。这就很有意义了,我们可以在现有项目中一小块一小块逐步地替换Compose,或者在旧项目中实现新的需求的时候,使用Compose

2. Android传统View调用Compose

2.1 新建传统View体系的Android项目

新建项目的时候选择 Empty Activity

Android View与Compose互相调用的方法是什么

2.2 项目添加Compose配置

2.2.1 在android代码块添加

appbuild.config android代码块中添加

buildFeatures {
    compose true
}
composeOptions {
    kotlinCompilerExtensionVersion '1.1.1'
}

2.2.2 在dependencies中添加依赖

appbuild.config dependencies代码块中添加

dependencies {
    //...省略...

    def compose_ui_version = '1.1.1'
    implementation "androidx.compose.ui:ui:$compose_ui_version"
    implementation "androidx.compose.ui:ui-tooling-preview:$compose_ui_version"
    androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_ui_version"
    debugImplementation "androidx.compose.ui:ui-tooling:$compose_ui_version"
    debugImplementation "androidx.compose.ui:ui-test-manifest:$compose_ui_version"

    implementation 'androidx.activity:activity-compose:1.3.1' //kotlin对应版本1.6.20
    implementation 'androidx.compose.material:material:1.1.1'
}

2.3 定义Compose函数

MainActivity.kt中定义Compose函数

@Composablefun ComposeContent() {    Box(        modifier = Modifier.fillMaxSize(),        contentAlignment = Alignment.Center    ) {        Text(text = "Hello world!")    }}

2.4 修改xml文件

activity_main.xml中添加androidx.compose.ui.platform.ComposeView

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    tools:context=".MainActivity">    <androidx.compose.ui.platform.ComposeView        android:id="@+id/compose_view"        android:layout_width="match_parent"        android:layout_height="match_parent" /></LinearLayout>

2.5 关联Compose函数

MainActivity.kt中,先通过findViewById找到ComposeView,然后通过composeView.setContent将Android 传统View和Compose建立关联。

override fun onCreate(savedInstanceState: Bundle?) {    super.onCreate(savedInstanceState)    setContentView(R.layout.activity_main)    val composeView : ComposeView = findViewById(R.id.compose_view)    composeView.setContent {        ComposeContent()    }}

3. Compose中调用Android View

3.1 调用传统View的日历

3.1.1 使用AndroidView

@Composable内使用: androidx.compose.ui.viewinterop.AndroidView,然后在factory里面返回原生View即可

@Composablefun AndroidViewPage() {    AndroidView(factory = {        CalendarView(it)    }, modifier = Modifier.fillMaxWidth(), update = {        it.setOnDateChangeListener { view, year, month, day ->            Toast.makeText(view.context, "${year}年${month}月${day}日", Toast.LENGTH_SHORT).show()        }    })}
3.1.2 显示效果如下

Android View与Compose互相调用的方法是什么

3.2 调用传统View的WebView

3.2.1 添加网络权限

首先需要在AndroidManifest.xml中添加网络权限

<uses-permission android:name="android.permission.INTERNET" />
3.2.2 首先要注册WebView的生命周期
@Composableprivate fun rememberWebViewLifecycleObserver(webView: WebView): LifecycleEventObserver {    return remember(webView) {        LifecycleEventObserver { _, event ->            run {                when (event) {                    Lifecycle.Event.ON_RESUME -> webView.onResume()                    Lifecycle.Event.ON_PAUSE -> webView.onPause()                    Lifecycle.Event.ON_DESTROY -> webView.destroy()                    else -> Log.e("WebView", event.name)                }            }        }    }}
3.2.3 创建有状态的WebView

创建有状态的WebView,并注册生命周期

@Composablefun rememberWebViewWIthLifecycle(): WebView {    val context = LocalContext.current    val webView = remember {        WebView(context)    }    val lifecycleObserver = rememberWebViewLifecycleObserver(webView)    val lifecycle = LocalLifecycleOwner.current.lifecycle    DisposableEffect(lifecycle) {        lifecycle.addObserver(lifecycleObserver)        onDispose {            lifecycle.removeObserver(lifecycleObserver)        }    }    return webView}
3.2.4 调用Android View
@Composablefun WebViewPage() {    //创建有状态的WebView,并注册生命周期    val webView = rememberWebViewWIthLifecycle()    AndroidView(factory = {        webView    }, modifier = Modifier        .fillMaxSize() //宽高占满父布局        .background(Color.Red),    update = {webView ->        //设置支持JavaScript        val webSettings = webView.settings        webSettings.javaScriptEnabled = true        webView.loadUrl("https://www.baidu.com")    })}

4. 双层嵌套

获取AndroidView中的原生View id

有时候,我们会遇到这种情况,就是在原生项目了,页面中有部分使用了Compose,然后在Compose中又有部分组件使用了原生View,这种情况下,要如何取到AndroidView中的原生View id 呢 ?

4.1 在定义Xml中定义ComposeView

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    tools:context=".MainActivity">    <androidx.compose.ui.platform.ComposeView        android:id="@+id/compose_view"        android:layout_width="match_parent"        android:layout_height="match_parent" /></LinearLayout>

4.2 关联Compose函数

MainActivity.kt中,先通过findViewById找到ComposeView,然后通过composeView.setContent将Android 传统View和Compose建立关联。

override fun onCreate(savedInstanceState: Bundle?) {    super.onCreate(savedInstanceState)    setContentView(R.layout.activity_main)    val composeView : ComposeView = findViewById(R.id.compose_view)    composeView.setContent {        ComposeContent()    }}@Composablefun ComposeContent() {//....}

4.3 创建ids.xml定义原生view id

resources/values目录下创建ids.xml

<?xml version="1.0" encoding="utf-8"?><resources>    <item type="id" name="my_calendar_view" /></resources>

4.4 实现ComposeContent

@Composablefun ComposeContent() {    AndroidView(factory = {        //这里也可以通过 layoutInflater.inflate(R.layout.xxxxxx) 的方式返回原生View        val calendarView = CalendarView(it)        val keyboard = R.id.my_calendar_view        Log.i(TAG,"my_calendar_view id:$keyboard")        calendarView.id = keyboard        calendarView    }, modifier = Modifier.fillMaxWidth(), update = {        it.setOnDateChangeListener { view, year, month, day ->            Toast.makeText(view.context, "${year}年${month}月${day}日", Toast.LENGTH_SHORT).show()        }    })}

4.5 在外层的原生代码处获取Compose中的原生View

在原生代码的地方,通过composeView.findViewById查找id为my_calendar_view的原生View

window?.decorView?.post {    val calendarViewId = R.id.my_calendar_view    Log.i(TAG,"my_calendar_view id ===>:$calendarViewId")    val calendarView = composeView.findViewById<CalendarView>(calendarViewId)    Log.i(TAG,"calendarView:$calendarView")    calendarView.setOnDateChangeListener { view, year, month, day ->        Toast.makeText(view.context, "!!!! ${year}年${month}月${day}日", Toast.LENGTH_SHORT).show()    }}

注意这里的window?.decorView?.post : 必须在页面加载完成后,才能查找到my_calendar_view对应的原生View,如果直接在onCreate里面去查找,会发现composeView.findViewById<CalendarView>(calendarViewId)返回的是null

4.6 运行项目

选择任意一个日期,可以发现弹出的toast是!!!! year年month月day日,即原生的setOnDateChangeListener覆盖了Compose中的setOnDateChangeListener监听,这样说明我们也在原生代码处,取到了Compose内部的原生View了。

感谢各位的阅读,以上就是“Android View与Compose互相调用的方法是什么”的内容了,经过本文的学习后,相信大家对Android View与Compose互相调用的方法是什么这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯