news 2026/4/25 15:09:39

Compose笔记(七十)--movableContentWithReceiverOf

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Compose笔记(七十)--movableContentWithReceiverOf

这一节主要了解一下Compose中的movableContentWithReceiverOf,在Jetpack Compose开发中movableContentWithReceiverOf是用于创建可移动的组合内容的API,其核心作用是通过保留组合状态,实现将一段Composable内容封装为可在不同组合节点间“移动”的对象,避免重复重组和重新布局,提升性能。简单总结:

API:
MovableContent:可移动内容的核心类型,是封装后的Composable内容句柄
movableContentWithReceiverOf:创建带“接收者(Receiver)”的可移动内容,接收者可传递上下文数据

栗子:

import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.material3.Button import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.movableContentWithReceiverOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp data class ContentReceiver( val title: String, val color: Color, val count: Int ) @Composable fun MovableContentWithReceiverDemo() { var count by remember { mutableStateOf(0) } var isRed by remember { mutableStateOf(false) } val movableContent = remember { movableContentWithReceiverOf<ContentReceiver> { Box( modifier = Modifier .size(200.dp) .background(this.color.copy(alpha = 0.6f)) .padding(16.dp), contentAlignment = androidx.compose.ui.Alignment.Center ) { Column(horizontalAlignment = androidx.compose.ui.Alignment.CenterHorizontally) { Text(text = this@movableContentWithReceiverOf.title, color = Color.White, fontSize = 18.sp) Text(text = "计数:${this@movableContentWithReceiverOf.count}", color = Color.White, fontSize = 14.sp) } } } } val receiver = ContentReceiver( title = "带接收者的可复用内容", color = if (isRed) Color.Red else Color.Green, count = count ) Column(modifier = Modifier.padding(16.dp)) { movableContent(receiver) Button( onClick = { count++ }, modifier = Modifier.padding(top = 16.dp) ) { Text(text = "增加计数") } Button( onClick = { isRed = !isRed }, modifier = Modifier.padding(top = 8.dp) ) { Text(text = "切换颜色") } } }
import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Button import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.ExperimentalComposeApi import androidx.compose.runtime.InternalComposeApi import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.compose.runtime.movableContentWithReceiverOf data class CardReceiver( val cardId: Int, val title: String, val desc: String, val bgColor: Color, val isSelected: Boolean ) @OptIn(ExperimentalComposeApi::class, InternalComposeApi::class) @Composable fun ReusableCardGroup() { var selectedCardId by remember { mutableStateOf(1) } var clickCount by remember { mutableStateOf(0) } val cardContent = remember { movableContentWithReceiverOf<CardReceiver> { Card( modifier = Modifier .fillMaxWidth() .padding(8.dp), shape = RoundedCornerShape(12.dp), border = if (this.isSelected) { BorderStroke(2.dp, Color.Black) } else { BorderStroke(1.dp, Color.Gray) }, colors = CardDefaults.cardColors( containerColor = this.bgColor.copy(alpha = if (this.isSelected) 0.9f else 0.7f) ), elevation = CardDefaults.cardElevation( defaultElevation = if (this.isSelected) 8.dp else 2.dp ) ) { Column( modifier = Modifier .fillMaxWidth() .padding(16.dp), horizontalAlignment = Alignment.CenterHorizontally ) { Text( text = this@movableContentWithReceiverOf.title, fontSize = 18.sp, fontWeight = FontWeight.Bold, color = Color.White ) Text( text = "${this@movableContentWithReceiverOf.desc} | 全局点击数:$clickCount", fontSize = 14.sp, color = Color.White.copy(alpha = 0.8f), modifier = Modifier.padding(top = 4.dp) ) Text( text = "卡片ID:${this@movableContentWithReceiverOf.cardId}", fontSize = 12.sp, color = Color.White.copy(alpha = 0.6f), modifier = Modifier.padding(top = 8.dp) ) } } } } Column( modifier = Modifier .fillMaxSize() .padding(16.dp), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Top ) { Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceEvenly, verticalAlignment = Alignment.CenterVertically ) { Button( onClick = { selectedCardId = if (selectedCardId == 1) 2 else 1 }, modifier = Modifier.padding(4.dp) ) { Text(text = "切换选中卡片") } Button( onClick = { clickCount++ }, modifier = Modifier.padding(4.dp) ) { Text(text = "点击计数+1") } } Column(modifier = Modifier.fillMaxWidth()) { val receiver1 = CardReceiver( cardId = 1, title = "用户信息卡片", desc = "姓名:张三 | 年龄:25", bgColor = Color(0xFF64B5F6), // 蓝色 isSelected = selectedCardId == 1 ) val card1 = cardContent(receiver1) val receiver2 = CardReceiver( cardId = 2, title = "订单信息卡片", desc = "订单号:20260117 | 金额:99元", bgColor = Color(0xFF81C784), // 绿色 isSelected = selectedCardId == 2 ) cardContent(receiver2) } } } @Composable fun MovableContentDemoApp() { Column(modifier = Modifier.fillMaxSize()) { Text( text = "movableContentWithReceiverOf Demo", fontSize = 20.sp, fontWeight = FontWeight.Bold, modifier = Modifier .align(Alignment.CenterHorizontally) .padding(16.dp) ) ReusableCardGroup() } }

注意:
1 必须配合remember使用:movableContentWithReceiverOf需在remember块内调用,以确保组合内容在重新组合时不会被回收。
2 接收者类型需明确 指定正确的接收者类型,否则无法访问布局相关的上下文。
3 参数传递需显式 依赖项应通过参数传入。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/21 18:49:55

专为翻译优化的7B大模型来了|HY-MT1.5-7B镜像部署全指南

专为翻译优化的7B大模型来了&#xff5c;HY-MT1.5-7B镜像部署全指南 1. 引言&#xff1a;为什么需要专有翻译大模型&#xff1f; 在多语言内容高速流动的今天&#xff0c;机器翻译已从“能用”迈向“好用”的新阶段。尽管通用大模型具备一定的翻译能力&#xff0c;但在专业性…

作者头像 李华
网站建设 2026/4/25 14:27:43

ES客户端在多租户架构中的集成策略解析

如何让 ES 客户端在多租户系统中既安全又高效&#xff1f;一线架构师的实战拆解 你有没有遇到过这样的场景&#xff1a; 一个 SaaS 平台上线不到半年&#xff0c;租户数量从几十涨到上千&#xff0c;日志查询接口突然频繁超时。排查发现&#xff0c;某个“大客户”一口气查了三…

作者头像 李华
网站建设 2026/4/24 5:21:07

Qwen2.5-0.5B-Instruct实战指南:打造专属AI写作助手

Qwen2.5-0.5B-Instruct实战指南&#xff1a;打造专属AI写作助手 1. 引言 随着大模型技术的普及&#xff0c;越来越多开发者和内容创作者希望在本地或低算力设备上部署轻量级AI助手。然而&#xff0c;大多数大模型对硬件要求较高&#xff0c;难以在边缘计算场景中落地。为此&a…

作者头像 李华
网站建设 2026/4/24 0:05:58

Youtu-2B小样本学习:有限数据下的表现

Youtu-2B小样本学习&#xff1a;有限数据下的表现 1. 引言&#xff1a;轻量模型在小样本场景下的价值 随着大语言模型&#xff08;LLM&#xff09;在自然语言处理领域的广泛应用&#xff0c;如何在有限标注数据的条件下实现高效推理与任务适配&#xff0c;成为工程落地中的关…

作者头像 李华
网站建设 2026/4/25 4:40:32

NewBie-image-Exp0.1实战指南:多风格动漫图像生成技巧

NewBie-image-Exp0.1实战指南&#xff1a;多风格动漫图像生成技巧 1. 引言 随着生成式AI在视觉内容创作领域的持续演进&#xff0c;高质量、可控性强的动漫图像生成已成为研究与应用的热点方向。NewBie-image-Exp0.1作为基于Next-DiT架构的3.5B参数大模型&#xff0c;凭借其强…

作者头像 李华
网站建设 2026/4/16 12:06:58

智能文档扫描仪疑难解答:边缘检测失败的常见原因及修复

智能文档扫描仪疑难解答&#xff1a;边缘检测失败的常见原因及修复 1. 引言 1.1 业务场景描述 在日常办公与数字化管理中&#xff0c;将纸质文档快速转化为清晰、规整的电子扫描件是一项高频需求。AI 智能文档扫描仪基于 OpenCV 的透视变换算法&#xff0c;提供了一套轻量高…

作者头像 李华