news 2026/5/30 14:32:35

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/5/22 15:49:28

阿里通义Z-Image-Turbo显存不足?显存优化部署案例一文详解

阿里通义Z-Image-Turbo显存不足&#xff1f;显存优化部署案例一文详解 1. 背景与问题提出 阿里通义Z-Image-Turbo是基于Diffusion架构的高性能图像生成模型&#xff0c;支持在WebUI中实现快速推理&#xff08;最低1步完成生成&#xff09;&#xff0c;广泛应用于AI艺术创作、…

作者头像 李华
网站建设 2026/5/21 21:00:45

GPEN实战教程:如何准备高质量-低质量图像配对数据集

GPEN实战教程&#xff1a;如何准备高质量-低质量图像配对数据集 1. 引言 1.1 学习目标 本文旨在为使用 GPEN人像修复增强模型 的开发者和研究人员提供一套完整、可落地的数据准备流程。通过本教程&#xff0c;您将掌握&#xff1a; 如何构建用于监督式训练的高质量与低质量…

作者头像 李华
网站建设 2026/5/28 20:26:25

从语音到可用文本的关键一步|FST ITN-ZH镜像应用实践

从语音到可用文本的关键一步&#xff5c;FST ITN-ZH镜像应用实践 1. 引言&#xff1a;为什么需要中文逆文本标准化&#xff08;ITN&#xff09; 在语音识别&#xff08;ASR&#xff09;的实际应用中&#xff0c;一个常被忽视但至关重要的环节是后处理阶段的文本规整。尽管现代…

作者头像 李华
网站建设 2026/5/26 9:17:36

YOLO-v8.3应用前景:自动驾驶感知模块的技术适配性

YOLO-v8.3应用前景&#xff1a;自动驾驶感知模块的技术适配性 1. YOLO-v8.3 技术背景与核心演进 1.1 YOLO 系列的发展脉络 YOLO&#xff08;You Only Look Once&#xff09;是一种端到端的实时目标检测框架&#xff0c;自2015年由华盛顿大学的 Joseph Redmon 和 Ali Farhadi…

作者头像 李华
网站建设 2026/5/30 2:10:11

超详细部署教程:Qwen3-Embedding-0.6B本地运行全流程

超详细部署教程&#xff1a;Qwen3-Embedding-0.6B本地运行全流程 1. 引言 随着大模型在语义理解、信息检索和多语言处理等任务中的广泛应用&#xff0c;高质量的文本嵌入&#xff08;Text Embedding&#xff09;模型成为构建智能系统的核心组件之一。Qwen3-Embedding 系列是通…

作者头像 李华
网站建设 2026/5/20 12:34:09

实测阿里MGeo模型,中文地址相似度识别真香

实测阿里MGeo模型&#xff0c;中文地址相似度识别真香 1. 引言&#xff1a;中文地址匹配的挑战与MGeo的破局之道 在电商、物流、本地生活服务等数据密集型场景中&#xff0c;地址实体对齐是实现用户画像融合、订单归集、门店去重等关键任务的基础。然而&#xff0c;中文地址天…

作者头像 李华