Compose和Android View相互使用

文章目录

  • Compose和Android View相互使用
    • 在Compose中使用View
      • 概述
      • 简单控件
      • 复杂控件
      • 嵌入XML布局
    • 在View中使用Compose
      • 概述
      • 在Activity中使用Compose
      • 在Fragment中使用Compose
        • 布局使用多个ComposeView
      • 在布局中使用Compose
    • 组合使用

Compose和Android View相互使用

在Compose中使用View

概述

Compose是一个全新的UI框架,虽然重写了我们熟悉的很多控件,但不可能面面俱到,比如Android View中的一些复杂控件Compose并没有重写。

简单控件

属性:

@Composable
@UiComposable
fun <T : View> AndroidView(factory: (Context) -> T, // Android Viewmodifier: Modifier = Modifier, // 修饰符update: (T) -> Unit = NoOpUpdate // 加载布局后回调
)

使用:

在这里插入图片描述

AndroidView(factory = { CalendarView(it) },modifier = Modifier.fillMaxSize(),update = {it.setOnDateChangeListener { view, year, month, dayOfMonth ->Toast.makeText(view.context, "${year}${month}${dayOfMonth}日", Toast.LENGTH_SHORT).show()}}
)

复杂控件

使用WebView、MapView等控件时需要在对应生命周期中调用对应方法,否则会引起内存泄漏。

在 Compose 中如果需要根据生命周期来进行不同操作,就需要使用 LocalLifecycleOwner。通过 LocalLifecycleOwner 可以获取当前的lifecycle,然后在控件创建的时候加上监听,之后在关闭的时候关掉监听。

@Composable
fun rememberWebViewWithLifecycle(): WebView {val context = LocalContext.currentval webView = remember {WebView(context)}val lifecycleObserver = rememberWebViewLifecycleObserve(webView)val lifecycle = LocalLifecycleOwner.current.lifecycleDisposableEffect(lifecycle) {lifecycle.addObserver(lifecycleObserver)onDispose {lifecycle.removeObserver(lifecycleObserver)}}return webView
}@Composable
fun rememberWebViewLifecycleObserve(webView: WebView): LifecycleEventObserver {return remember(webView) {LifecycleEventObserver { source, event ->when (event) {Lifecycle.Event.ON_RESUME -> webView.onResume()Lifecycle.Event.ON_PAUSE -> webView.onPause()Lifecycle.Event.ON_DESTROY -> webView.destroy()else -> android.util.Log.e("TAG", "hello world")}}}
}@SuppressLint("SetJavaScriptEnabled")
@Composable
fun MyAndroidView() {val webView = rememberWebViewWithLifecycle()AndroidView(factory = { webView },modifier = Modifier.fillMaxSize(),update = { webView ->webView.settings.apply {javaScriptEnabled = true}webView.loadUrl("https://www.baidu.com")})
}

嵌入XML布局

如果大家在重构项目时遇到复杂的XML布局不易使用Compose来构建,也可以直接在Compose中使用XML布局,不过Compose目前只支持以ViewBinding的方式构建的XML布局。

开启ViewBinding:

viewBinding {enabled = true
}

添加依赖库:

implementation "androidx.compose.ui:ui-viewbinding:1.3.0-beta02"

属性:

fun <T : ViewBinding> AndroidViewBinding(// 创建ViewBindingfactory: (inflater: LayoutInflater, parent: ViewGroup, attachToParent: Boolean) -> T,// 修饰符modifier: Modifier = Modifier,// 加载完后回调update: T.() -> Unit = {}
) 

使用:

在这里插入图片描述

login_layout.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"><EditTextandroid:id="@+id/et_name"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_margin="30dp"android:hint="name" /><EditTextandroid:id="@+id/et_password"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginHorizontal="30dp"android:hint="password" /><Buttonandroid:id="@+id/btn_login"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:layout_marginTop="30dp"android:text="登录" />
</LinearLayout>

MainActivity

class MainActivity : ComponentActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContent {Scaffold() { paddingValues ->Box(modifier = Modifier.padding(paddingValues)) {MyAndroidXml()}}}}fun doLogin(name: String, password: String) {if (name.isEmpty() || password.isEmpty()) {Toast.makeText(this, "用户名密码不能为空", Toast.LENGTH_SHORT).show()return}Toast.makeText(this, "用户名:$name 密码:$password", Toast.LENGTH_SHORT).show()}
}@Composable
fun MyAndroidXml() {val context = LocalContext.current as MainActivityAndroidViewBinding(factory = { inflater, parent, attachToParent ->LoginLayoutBinding.inflate(inflater, parent, attachToParent)},modifier = Modifier.fillMaxSize(),update = {btnLogin.setOnClickListener {val name = etName.text.toString().trim()val password = etPassword.text.toString().trim()context.doLogin(name, password)}})
}

在View中使用Compose

概述

在 Android View 中也可以使用 Compose,平时编写 Android 代码的时候一般会使用 Activity 或 Fragment 来展示页面。

在Activity中使用Compose

添加依赖库:

如果是新建的Compose项目,编译器会直接帮我们引入 activity-compose 的依赖;如果是老项目,就需要我们手动添加依赖。

implementation 'androidx.activity:activity-compose:1.3.1'

通过 setContent 方式使用 Compose。

class MainActivity : ComponentActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContent {Text("hello world")}}
}

在Fragment中使用Compose

class MyFragment : Fragment() {override fun onCreateView(inflater: LayoutInflater,container: ViewGroup?,savedInstanceState: Bundle?): View {val composeView = ComposeView(requireContext()).apply {setContent {Text("hello world")}}return composeView}
}
布局使用多个ComposeView

如果一个布局中存在多个ComposeView,那么每个ComposeView必须有唯一ID才能使saveInstanceState发挥作用。

class MyFragment : Fragment() {override fun onCreateView(inflater: LayoutInflater,container: ViewGroup?,savedInstanceState: Bundle?): View {val linearLayout = LinearLayout(requireContext()).apply {orientation = LinearLayout.VERTICALval oneComposeView = ComposeView(requireContext()).apply {id = R.id.compose_onesetContent {Text("hello")}}addView(oneComposeView)val button = Button(requireContext()).apply {text = "world"}addView(button)val twoComposeView = ComposeView(requireContext()).apply {id = R.id.compose_twosetContent {Text("compose")}}addView(twoComposeView)}return linearLayout}
}

在布局中使用Compose

  • 在XML布局中使用ComposeView。
  • 通过ComposeView的setContent设置Compose组件。

布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/container"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><EditTextandroid:id="@+id/et_input"android:layout_width="match_parent"android:layout_height="wrap_content"android:padding="30dp" /><androidx.compose.ui.platform.ComposeViewandroid:id="@+id/compose_view"android:layout_width="match_parent"android:layout_height="wrap_content" /></LinearLayout>

代码:

class MainActivity : AppCompatActivity() {private lateinit var activityMainBinding: ActivityMainBindingoverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)activityMainBinding = ActivityMainBinding.inflate(layoutInflater)setContentView(activityMainBinding.root)initViews()}private fun initViews() {activityMainBinding.apply {composeView.setContent {var content by remember { mutableStateOf("") }Column(modifier = Modifier.fillMaxSize()) {Button(onClick = { content = etInput.text.toString().trim() }) {Text("提交")}Text(content)}}}}
}

组合使用

目前大部分应用都是基于 Android View 编写的,而 Android View 只能显示 View,因此需要将 Compose 转为 Android View 中使用的 View。

第一步:创建Compose

@Composable
fun rememberWebViewWithLifecycle(): WebView {val context = LocalContext.currentval webView = remember {WebView(context)}val lifecycleObserver = rememberWebViewLifecycleObserve(webView)val lifecycle = LocalLifecycleOwner.current.lifecycleDisposableEffect(lifecycle) {lifecycle.addObserver(lifecycleObserver)onDispose {lifecycle.removeObserver(lifecycleObserver)}}return webView
}@Composable
fun rememberWebViewLifecycleObserve(webView: WebView): LifecycleEventObserver {return remember(webView) {LifecycleEventObserver { source, event ->when (event) {Lifecycle.Event.ON_RESUME -> webView.onResume()Lifecycle.Event.ON_PAUSE -> webView.onPause()Lifecycle.Event.ON_DESTROY -> webView.destroy()else -> android.util.Log.e("TAG", "hello world")}}}
}@SuppressLint("SetJavaScriptEnabled")
@Composable
fun WebViewPage() {val webView = rememberWebViewWithLifecycle()AndroidView(factory = { webView },modifier = Modifier.fillMaxSize(),update = { webView ->webView.settings.apply {javaScriptEnabled = true}webView.loadUrl("https://www.baidu.com")})
}

第二步:将Compose转为Android View

class MyAndroidView @JvmOverloads constructor(context: Context,attrs: AttributeSet? = null,defStyleAttr: Int = 0
) : AbstractComposeView(context, attrs, defStyleAttr) {@Composableoverride fun Content() {WebViewPage()}
}

第三步:使用Android View

<com.example.app222.MyAndroidViewandroid:layout_width="match_parent"android:layout_height="match_parent" />

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/4074.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AIGC - SD(中英文本生成图片) + PaddleHub/HuggingFace + stable-diffusion-webui

功能 stable-diffusion(文本生成图片)webui-win搭建&#xff08;开启api界面汉化&#xff09;PaddleHubHuggingFace: SD2&#xff0c;中文-alibaba/EasyNLP stable-diffusion-webui 下载与安装 环境相关下载 python&#xff08;文档推荐&#xff1a;Install Python 3.10.6 …

linux开发板开机启动向日葵

硬件&#xff1a;orangepi 5 pro 操作系统&#xff1a;ubuntu 20.4 lts 安装向日葵 根据我的实测&#xff0c;arm架构的ubuntu系统只能安装向日葵提供的麒麟系统的那个版本&#xff0c;具体安装方式官网下载页面有 允许任意用户连接到 X11 使用root用户登录后打开终端输入一下…

Windows python3.10安装psbody

Windows环境下安装psbody 下载mesh GitHub - MPI-IS/mesh: MPI-IS Mesh Processing Library 下载安装boost Boost Downloads 解压到 D:\software\boost_1_85_0&#xff0c;这个路径后面要设置为环境变量 BOOST_ROOT 的值。 添加 BOOST_ROOT 环境变量 您可以通过图形界面配…

php的curl请求,包含了post,get,put,delete

php的curl请求,包含了post,get,put,delete 这段代码是一个非常实用的HTTP通信工具&#xff0c;可以轻松集成到需要网络通信的PHP项目中。它提供了足够的灵活性&#xff0c;适合多种网络请求任务。 if (!function_exists("http_curl")) {/*** 发送HTTP请求* param s…

react函数组件传值(父子/子父/兄弟)

父子组件传值 子父组件传值 兄弟组件传值 注&#xff1a;本人前端小白 &#xff0c;如有不对的地方还请多多指教

knife4j swagger 使用笔记

1.接口访问的端口跟后台设置的不一致&#xff0c;接口请求无反应 处理办法 2.响应参数不显示问题 &#xff08;1&#xff09;返回的参数里面一定要有响应的参数对象&#xff0c;如下&#xff1a; &#xff08;2&#xff09;TableDataInfo 定义成泛型类 TableDataInfo package…

ros2 node 之间的通信方式之 —— Topic通信案例

文章目录 ros2 node 之间的通信方式之 Topic通信Topic 通信案例1、创建工作空间2、创建功能包3、编写发布者和订阅者代码3.1 topic_helloworld_pub.cpp3.2 topic_helloworld_sub.cpp 4、编写CMakeLists.txt5、编译工作空间下的功能包6、运行结果 ros2 node 之间的通信方式之 To…

AutoGPT-Forge使用教程,自行构建agent智能体

本博客给出AutoGPT-forge四个教程的翻译与理解&#xff0c;使用GPT4翻译&#xff0c; 参考官方教程https://aiedge.medium.com/autogpt-forge-a-comprehensive-guide-to-your-first-steps-a1dfdf46e3b4 使用AutoGPT Github代码日期2024/4/22&#xff1b; 博客开始编辑日期20…

C语言项目实战——扫雷

目录 1.前言 2.完整流程 2.1规划书 2.2代码部分 2.2.1文件的结构设计 2.2.2变量的创建 2.2.3菜单的基本实现 2.2.4初始化期棋盘 2.2.5输出完整棋盘 2.2.6埋雷的实现 2.2.7查询周围雷的数量 2.2.8扫雷的实现 2.2.9完整代码 3.总结 1.前言 哈喽大家好吖&#xff0c;今…

深入了解数据结构中的查找算法

目录 前言 1. 查找的基本概念 2. 顺序查找和折半查找 2.1 顺序查找 2.2 折半查找 2.3分块查找 3. 树形查找 3.1 二叉搜索树 (BST) 3.2平衡二叉树 3.3红黑树 4. B 树和 B 树 4.1 B 树 4.2 B 树 5. 哈希表 (Hash Table) 5.1 基本操作 5.2 实现 5.3 复杂性分析 5…

# IntelliJ IDEA 中 springboot 启动类 SpringApplication.run 报红分析

IntelliJ IDEA 中 springboot 启动类 SpringApplication.run 报红分析 一、原因分析&#xff1a;通常 SpringApplication.run 报红&#xff0c;可能是由以下几种原因造成的&#xff1a; 1、项目的主配置文件中 pom.xml 可能没有导入相关依赖。 2、方法参数错误&#xff1a;S…

全量知识系统 程序详细设计 库模式的存储库模型: “三生”(派生衍生自生) (QA SmartChat)

Q1. 请仔细说说 派生和衍生 各自的意思以及关系 派生和衍生是两个近义词&#xff0c;但在语境不同的情况下有着不同的含义。 派生通常指从某种事物或概念中产生出新的东西或概念。它可以用来表示从一个基本的概念或原始的实体中推导或演化出来的新的思想、理论、产品或方法。…

【C++例】虚函数—代码实例

1.虚函数的动态绑定 //虚函数&#xff08;非静态的成员函数&#xff09; //动态绑定&#xff1a;只有通过基类的指针或引用调用虚函数时 #include<iostream> using namespace std; class Base1 { public:virtual void display() const; }; // 如果把某个函数指定为final…

通用型自定义拼接 SQL 脚本,摆脱重复工作量

通用型自定义拼接sql脚本,摆脱重复工作量 在开发 Restful 接口时&#xff0c;我们经常需要根据前端传递的参数动态拼接 SQL 查询语句&#xff0c;以满足不同的查询需求。本文将介绍一个通用的自定义拼接 SQL 脚本的方法&#xff0c;帮助开发人员减少重复工作量。 首先&#x…

【C++打怪之路Lv3】-- 类和对象(上)

&#x1f308; 个人主页&#xff1a;白子寰 &#x1f525; 分类专栏&#xff1a;C打怪之路&#xff0c;python从入门到精通&#xff0c;数据结构&#xff0c;C语言&#xff0c;C语言题集&#x1f448; 希望得到您的订阅和支持~ &#x1f4a1; 坚持创作博文(平均质量分82)&#…

避坑:我找到了Hexo安知鱼的音乐馆配置(目前好像还没有教程)

我发现安知鱼的音乐配置根本就找不到说明就无奈自己逆向了一下&#xff0c;找到了配置文件&#xff0c;写在博客里记录一下也算是给大家避坑 我的版本是1.6.12&#xff0c;如果你和我的不一样可以看后面 配置文件就是Blog\themes\anzhiyu\source\js\utils.js 打开该文件&…

开发环境搭建:Windows 桌面应用程序

文章目录 前言1、开发环境准备2、Hello World !3、发布总结 前言 操作系统&#xff1a;Windows 10 企业版 LTSC 1809 IDE&#xff1a;Microsoft Visual Studio 2022 Community 说明&#xff1a;Windows 10 企业版 LTSC 1809 不支持 .NET 4.8.1 详情请查看官方说明文档 1、开发…

【华为OD机试】手机App防沉迷系统【C卷|100分】

【华为OD机试】-真题 !!点这里!! 【华为OD机试】真题考点分类 !!点这里 !! 题目描述 智能手机方便了我们生活的同时,也侵占了我们不少的时间。 “手机App防沉迷系统”能够让我们每天合理地规划手机App使用时间,在正确的时间做正确的事。 它的大概原理是这样的: 在一天24小…

The Log-Structured Merge-Tree (LSM-Tree) 论文阅读笔记

原论文&#xff1a;The Log-Structured Merge-Tree (LSM-Tree) LSM-Tree的简介和关键技术要点 LSM-Tree&#xff08;Log-Structured Merge-Tree&#xff09;是一种为高吞吐量读写操作优化的数据结构&#xff0c;特别适用于写入密集型的应用场景。它由Patrick O’Neil等人开发…

基于streamlit快速部署机器学习项目(Public URL)

基于streamlit的AIGC项目前端展示 1.Streamlit 简介与入门1.1 安装 Streamlit1.2 开发Streamlit应用程序1.3 启动并运行1.3.1 本地运行1.3.2 部署 现在LLM技术发展迅速&#xff0c;很多人在学习的时候&#xff0c;都想展示效果&#xff0c;并且想部署在服务器上&#xff0c;但是…