当前位置: 首页 > news >正文

Android自定义侧滑Item

源码地址:https://github.com/LanSeLianMa/CustomizeView/tree/master/cehuaitem

使用方式一:XML布局中直接使用

<?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"><com.test.festec.cehuaitem.widget.SideslipContainerandroid:id="@+id/sideslip_container01"android:layout_width="match_parent"android:layout_height="70dp"app:option_width="65dp"><com.test.festec.cehuaitem.widget.SideslipContentandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="horizontal"><TextViewandroid:background="@color/d5"android:paddingTop="20dp"android:textAlignment="center"android:textSize="20sp"android:text="content"android:layout_width="match_parent"android:layout_height="match_parent" /></com.test.festec.cehuaitem.widget.SideslipContent><com.test.festec.cehuaitem.widget.SideslipOptionandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@color/blue"android:tag="add"android:text="增加" /><com.test.festec.cehuaitem.widget.SideslipOptionandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@color/orange"android:tag="edit"android:text="编辑" /><com.test.festec.cehuaitem.widget.SideslipOptionandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@color/red"android:tag="delete"android:text="删除" /></com.test.festec.cehuaitem.widget.SideslipContainer></LinearLayout>

Activity中监听

class MainActivity : Activity() {private lateinit var binding: ActivityMainBindingprivate var options = mutableListOf("增加", "编辑", "删除")private var optionBg = mutableListOf(R.color.blue, R.color.orange, R.color.red)@SuppressLint("UseCompatLoadingForDrawables")@RequiresApi(Build.VERSION_CODES.LOLLIPOP)override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)binding = ActivityMainBinding.inflate(layoutInflater)setContentView(binding.root)binding.sideslipContainer01.addOnClickListener(object : SideslipContainer.SideslipContainerOnClick {override fun optionOnClick(optionTag: Any) {Toast.makeText(this@MainActivity,"optionTag:$optionTag", Toast.LENGTH_SHORT).show()binding.sideslipContainer01.sideslipRecover()}override fun contentOnClick() {Toast.makeText(this@MainActivity,"content", Toast.LENGTH_SHORT).show()binding.sideslipContainer01.sideslipRecover()}})}}

使用方式二:代码方式使用

先定义一个容器

<?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"><LinearLayoutandroid:id="@+id/container"android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="vertical" /></LinearLayout>

Activity中动态添加

class MainActivity : Activity() {private lateinit var binding: ActivityMainBindingprivate var options = mutableListOf("增加", "编辑", "删除")private var optionBg = mutableListOf(R.color.blue, R.color.orange, R.color.red)@SuppressLint("UseCompatLoadingForDrawables")@RequiresApi(Build.VERSION_CODES.LOLLIPOP)override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)binding = ActivityMainBinding.inflate(layoutInflater)setContentView(binding.root)// 创建侧滑容器,配置基础参数val sideslip = SideslipContainer(this, DensityUtil.dp2px(this, 65f))val layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,DensityUtil.dp2px(this, 70f))sideslip.layoutParams = layoutParams// 创建侧滑内容val content = SideslipContent(this).apply {background = resources.getDrawable(R.color.black,null)}// 加入侧滑容器中sideslip.addView(content)// 创建选项卡,并加入侧滑容器中options.forEachIndexed { index, str ->val option = SideslipOption(this,str)option.text = stroption.background = resources.getDrawable(optionBg[index], null)sideslip.addView(option)}// 点击监听sideslip.addOnClickListener(object : SideslipContainer.SideslipContainerListener {override fun optionOnClick(optionTag: Any) {Log.e("TAG","optionTag:$optionTag")}override fun contentOnClick() {Log.e("TAG","content")}})binding.container.addView(sideslip)}}

使用方式三:结合RecyclerView使用

重写LayoutManager

// 重写LayoutManager,动态让RecyclerView 禁止/恢复 Y轴滚动
open class CustomLinerLayoutManager(context: Context) : LinearLayoutManager(context) {private var isScrollEnabled = truefun getEnabled(): Boolean {return isScrollEnabled}fun setScrollEnabled(flag: Boolean) {isScrollEnabled = flag}override fun canScrollVertically(): Boolean {return isScrollEnabled && super.canScrollVertically();}}

重写RecyclerView

class MyRecyclerView : RecyclerView {constructor(context: Context) : super(context)constructor(context: Context, attributeSet: AttributeSet) : super(context, attributeSet)init {addOnScrollListener(object : RecyclerView.OnScrollListener() {/**** public static final int SCROLL_STATE_IDLE = 0;  :  RecyclerView 当前未滚动。** public static final int SCROLL_STATE_DRAGGING = 1;  :  RecyclerView 当前正在被外部输入(例如用户触摸输入)拖动。** public static final int SCROLL_STATE_SETTLING = 2;  :  RecyclerView 当前正在动画到最终位置,而不是在外部控制。*/override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {if (newState == RecyclerView.SCROLL_STATE_DRAGGING) {childrenRecover()}}})}// view初始化private var viewInit = false// 上一会触摸的子Viewvar originalChild: SideslipContainer? = null// 当前触摸的子Viewvar currentChild: SideslipContainer? = nullprivate var customLayoutManager: CustomLinerLayoutManager? = nullprivate var childMoveCallback = object : ChildOnTouchCallback {override fun currentChildMove() {childrenRecover()}override fun originalChild(originalSideslip: SideslipContainer?) {originalChild = originalSideslip}override fun currentChild(currentContainer: SideslipContainer?) {currentChild = currentContainer}override fun listStopYScroll() {// Log.e("TAG", "List停止滚动")if (customLayoutManager!!.getEnabled()) {customLayoutManager?.setScrollEnabled(false)}}override fun listRecoverYScroll() {// Log.e("TAG", "List恢复滚动")if (!(customLayoutManager!!.getEnabled())) {customLayoutManager?.setScrollEnabled(true)}}}// 子View恢复private fun childrenRecover() {children.forEach {(it as SideslipContainer).sideslipRecover()}}override fun onViewAdded(child: View?) {// Log.e("TAG","onViewAdded")val sideslipContainer = (child as SideslipContainer)sideslipContainer.addOnChildMoveCallback(childMoveCallback)}// 当复用item,彻底超出屏幕,不可见时执行override fun onViewRemoved(child: View?) {// Log.e("TAG","onViewRemoved")(child as SideslipContainer).sideslipStateRest()}override fun onWindowFocusChanged(hasWindowFocus: Boolean) {// Log.e("TAG","onWindowFocusChanged")super.onWindowFocusChanged(hasWindowFocus)if (!viewInit) {customLayoutManager = (layoutManager as CustomLinerLayoutManager)}viewInit = true}interface ChildOnTouchCallback {// 有子View侧滑了fun currentChildMove()// 上一个触摸的子Viewfun originalChild(originalSideslip: SideslipContainer?)// 当前触摸的子Viewfun currentChild(currentContainer: SideslipContainer?)// 列表停止Y轴滚动fun listStopYScroll()// 列表恢复Y轴滚动fun listRecoverYScroll()}}

RecyclerView适配器

class MyListAdapter(var context: Context,var data: MutableList<Info>
) : RecyclerView.Adapter<MyListAdapter.MyViewHolder>() {private var options = mutableListOf("增加", "编辑", "删除")private var optionBg =mutableListOf(R.color.blue, R.color.orange, R.color.red)@RequiresApi(Build.VERSION_CODES.LOLLIPOP)override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {val itemView = LayoutInflater.from(context).inflate(R.layout.list_item, parent, false)val sideslip = sideslipContainer(itemView)return MyViewHolder(sideslip)}@SuppressLint("UseCompatLoadingForDrawables", "ResourceAsColor")@RequiresApi(Build.VERSION_CODES.LOLLIPOP)override fun onBindViewHolder(holder: MyViewHolder, position: Int) {val sideslip = holder.itemView as SideslipContainer// 根据不同权限,添加不同的选项卡val optionsView = mutableListOf<SideslipOption>()if (data[position].level == 0) {optionsView.clear()} else if (data[position].level == 1) {val option = SideslipOption(context, options[1])option.text = options[1]option.background = context.resources.getDrawable(optionBg[1], null)optionsView.add(option)} else {options.forEachIndexed { index, str ->val option = SideslipOption(context, str)option.text = stroption.background = context.resources.getDrawable(optionBg[index], null)optionsView.add(option)}}sideslip.addMultipleOption(optionsView)// 点击回调sideslip.addOnClickListener(object : SideslipContainer.SideslipContainerOnClick {override fun optionOnClick(optionTag: Any) {Toast.makeText(context,"${holder.adapterPosition} -- optionTag:$optionTag",Toast.LENGTH_SHORT).show()sideslip.sideslipRecover()}override fun contentOnClick() {Toast.makeText(context,"${holder.adapterPosition} - content",Toast.LENGTH_SHORT).show()sideslip.sideslipRecover()}})holder.idTv.text = data[position].id.toString()holder.titleTv.text = data[position].titleholder.describeTv.text = data[position].describe}override fun getItemCount(): Int {return data.size}@SuppressLint("UseCompatLoadingForDrawables")@RequiresApi(Build.VERSION_CODES.LOLLIPOP)private fun sideslipContainer(itemView: View): SideslipContainer {// 创建侧滑容器,配置基础参数val sideslip = SideslipContainer(context)sideslip.setOptionWidth(DensityUtil.dp2px(context, 65f))val layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,DensityUtil.dp2px(context, 70f))sideslip.layoutParams = layoutParams// 创建侧滑内容val content = SideslipContent(context)content.addView(itemView)// 加入侧滑容器中sideslip.addView(content)// 创建选项卡,并加入侧滑容器中// options.forEachIndexed { index, str ->//    val option = SideslipOption(context, str)//    option.text = str//    option.background = context.resources.getDrawable(optionBg[index], null)//    sideslip.addView(option)// }return sideslip}class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {var idTv: TextViewvar titleTv: TextViewvar describeTv: TextViewinit {idTv = itemView.findViewById(R.id.id_tv)titleTv = itemView.findViewById(R.id.title_tv)describeTv = itemView.findViewById(R.id.describe_tv)}}
}

Activity中绑定数据

class ListActivity : Activity() {private lateinit var binding: ListLayoutBindingprivate val data: MutableList<Info> = mutableListOf(Info(0, "title", "content", 2),Info(1, "title", "content", 1),Info(2, "title", "content", 2),Info(3, "title", "content", 2),Info(4, "title", "content", 2),Info(5, "title", "content", 1),Info(6, "title", "content", 1),Info(7, "title", "content", 2),Info(8, "title", "content", 2),Info(9, "title", "content", 1),Info(10, "title", "content", 1),Info(11, "title", "content", 2),Info(12, "title", "content", 2),Info(13, "title", "content", 1),Info(14, "title", "content", 1),Info(15, "title", "content", 2),Info(16, "title", "content", 2),Info(17, "title", "content", 2),Info(18, "title", "content", 2),Info(19, "title", "content", 1),Info(20, "title", "content", 2),Info(21, "title", "content", 1),Info(22, "title", "content", 2),Info(23, "title", "content", 2),Info(24, "title", "content", 2),Info(25, "title", "content", 1),Info(26, "title", "content", 2),Info(27, "title", "content", 1),Info(28, "title", "content", 2),Info(29, "title", "content", 2),Info(30, "title", "content", 2),Info(31, "title", "content", 1),Info(32, "title", "content", 1),Info(33, "title", "content", 2),Info(34, "title", "content", 2),Info(35, "title", "content", 1),)override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)binding = ListLayoutBinding.inflate(layoutInflater)setContentView(binding.root)val adapter = MyListAdapter(this, data)val linearLayoutManager = CustomLinerLayoutManager(this)binding.root.layoutManager = linearLayoutManagerbinding.root.adapter = adapter}}

相关文章:

Android自定义侧滑Item

源码地址&#xff1a;https://github.com/LanSeLianMa/CustomizeView/tree/master/cehuaitem 使用方式一&#xff1a;XML布局中直接使用 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com…...

c++11 标准模板(STL)(std::basic_stringbuf)(三)

定义于头文件 <sstream> template< class CharT, class Traits std::char_traits<CharT>, class Allocator std::allocator<CharT> > class basic_stringbuf : public std::basic_streambuf<CharT, Traits> std::basic_stringbuf…...

Nodejs 第九章(模块化)

Nodejs 模块化规范遵循两套一 套CommonJS规范另一套esm规范 CommonJS 规范 引入模块&#xff08;require&#xff09;支持四种格式 支持引入内置模块例如 http os fs child_process 等nodejs内置模块支持引入第三方模块express md5 koa 等支持引入自己编写的模块 ./ …/ 等支…...

shell之正则表达式及三剑客grep命令

一、正则表达式概述 什么是正则表达式&#xff1f; 正则表达式是一种描述字符串匹配规则的重要工具 1、正则表达式定义: 正则表达式&#xff0c;又称正规表达式、常规表达式 使用字符串描述、匹配一系列符合某个规则的字符串 正则表达式 普通字符&#xff1a; 大小写字母…...

LeetCode 热题 100 JavaScript--33. 搜索旋转排序数组

整数数组 nums 按升序排列&#xff0c;数组中的值 互不相同 。 在传递给函数之前&#xff0c;nums 在预先未知的某个下标 k&#xff08;0 < k < nums.length&#xff09;上进行了 旋转&#xff0c;使数组变为 [nums[k], nums[k1], …, nums[n-1], nums[0], nums[1], …,…...

并发编程 - 线程池中的常见面试题

目录 1. 线程池相比于线程有什么优点 2. 线程池的参数有哪些 3. 线程工厂有什么用 4. 说一下线程的优先级 5. 说一下线程池的执行流程 6. 线程池的拒绝策略有哪些 7. 如何实现自定义拒绝策略 8. 如何判断线程池中的任务是否执行完成 1. 线程池相比于线程有什么优点 有…...

将多个单独的 Excel 文件合并成一个,并添加标题行

要将多个单独的 Excel 文件合并成一个&#xff0c;并添加标题行&#xff0c;可以使用 Python 的 pandas 库。以下是一个示例代码&#xff0c;假设要合并的 Excel 文件都在同一个文件夹中&#xff1a; import os import pandas as pd # 指定文件夹路径 folder_path path/to/fo…...

VPN pptp和l2tp协议破解

代码下载地址&#xff1a; https://download.csdn.net/download/m0_37567738/88215516?spm1001.2014.3001.5501...

4.3、Flink任务怎样读取Kafka中的数据

目录 1、添加pom依赖 2、API使用说明 3、这是一个完整的入门案例 4、Kafka消息应该如何解析 4.1、只获取Kafka消息的value部分 ​4.2、获取完整Kafka消息(key、value、Metadata) 4.3、自定义Kafka消息解析器 5、起始消费位点应该如何设置 ​5.1、earliest() 5.2、lat…...

C语言实例_和校验算法

一、算法介绍 和校验&#xff08;Checksum&#xff09;是一种简单的纠错算法&#xff0c;用于检测或验证数据传输或存储过程中的错误。它通过对数据进行计算并生成校验和&#xff0c;然后将校验和附加到数据中&#xff0c;在接收端再次计算校验和并进行比较&#xff0c;以确定…...

安全加密框架图——Oracle安全开发者

Oracle安全开发者 ACLs 设计 ACLs&#xff08;访问控制列表&#xff09;时&#xff0c;可以根据以下思路进行设计&#xff1a; 所有者文件权限&#xff1a;确定文件的所有者能够对文件执行哪些操作&#xff0c;如读取、写入、执行等。这可以根据文件的性质和拥有者的职责来决…...

Android databinding 被多次定义

一、报错&#xff1a; AndroidStudio运行代码时&#xff0c;编译器报 Type androidx.databinding.Bindable is defined multiple times...... 二、解决&#xff1a; 点击 Build -> Clean Project&#xff0c;关闭编译器再打开即可。 三、解决过程&#xff1a; 在使用Andro…...

云原生周刊:Kubernetes v1.28 新特性一览 | 2023.8.14

推荐一个 GitHub 仓库&#xff1a;Fast-Kubernetes。 Fast-Kubernetes 是一个涵盖了 Kubernetes 的实验室&#xff08;LABs&#xff09;的仓库。它提供了关于 Kubernetes 的各种主题和组件的详细内容&#xff0c;包括 Kubectl、Pod、Deployment、Service、ConfigMap、Volume、…...

机器学习之分类模型

机器学习之分类模型 概述分类模型逻辑回归最近邻分类朴素贝叶斯支持向量机决策树随机森林多层感知机基于集成学习的分类模型VotingBaggingStackingBlendingBoosting 概述 机器学习分类模型通过训练集进行学习&#xff0c;建立一个从输入空间 X X X到输出空间 Y Y Y&#xff08…...

学习Vue:创建第一个Vue实例

当您开始探索 Vue.js&#xff0c;第一步就是创建一个 Vue 实例。Vue 实例是 Vue.js 应用程序的核心构建块&#xff0c;它使您能够将数据与用户界面连接起来&#xff0c;实现动态交互。在本文中&#xff0c;我们将详细介绍如何创建您的第一个 Vue 实例。 步骤1&#xff1a;引入 …...

JavaFx基础学习【二】:Stage

一、介绍 窗口Stage为图中标绿部分&#xff1a; 实际为如下部分&#xff1a; 不同的操作系统表现的样式不同&#xff0c;以下都是以Windows操作系统为例&#xff0c;为了使大家更清楚Stage是那部分&#xff0c;直接看以下图&#xff0c;可能更清楚&#xff1a; 有点潦草&…...

C语言——动态内存函数(malloc、calloc、realloc、free)

了解动态内存函数 前言&#xff1a;一、malloc函数二、calloc函数三、realloc函数四、free函数 前言&#xff1a; 在C语言中&#xff0c;动态内存函数是块重要的知识点。以往&#xff0c;我们开辟空间都是固定得&#xff0c;数组编译结束后就不能继续给它开辟空间了&#xff0…...

Redis数据结构——Redis简单动态字符串SDS

定义 众所周知&#xff0c;Redis是由C语言写的。 对于字符串类型的数据存储&#xff0c;Redis并没有直接使用C语言中的字符串。 而是自己构建了一个结构体&#xff0c;叫做“简单动态字符串”&#xff0c;简称SDS&#xff0c;比C语言中的字符串更加灵活。 SDS的结构体是这样的…...

【计算机网络】TCP协议超详细讲解

文章目录 1. TCP简介2. TCP和UDP的区别3. TCP的报文格式4. 确认应答机制5. 超时重传6. 三次握手7. 为什么两次握手不行?8. 四次挥手9. 滑动窗口10. 流量控制11. 拥塞控制12. 延时应答13. 捎带应答14. 面向字节流15. TCP的连接异常处理 1. TCP简介 TCP协议广泛应用于可靠性要求…...

Salesforce特别元数据部署技巧

标准的picklist字段部署 <?xml version"1.0" encoding"UTF-8" standalone"yes"?> <Package xmlns"http://soap.sforce.com/2006/04/metadata"><types><members>Opportunity.StageName</members><…...

OpenClaw+千问3.5-9B:社交媒体内容自动生成与发布

OpenClaw千问3.5-9B&#xff1a;社交媒体内容自动生成与发布 1. 为什么需要自动化社交媒体运营 作为一个独立开发者兼技术博主&#xff0c;我每天需要维护多个社交媒体账号的内容更新。从选题构思、内容创作到排版发布&#xff0c;整个过程耗时耗力。最痛苦的是灵感枯竭时&am…...

从vim-plug到packer.nvim的终极迁移指南:3步实现无缝切换

从vim-plug到packer.nvim的终极迁移指南&#xff1a;3步实现无缝切换 【免费下载链接】packer.nvim A use-package inspired plugin manager for Neovim. Uses native packages, supports Luarocks dependencies, written in Lua, allows for expressive config 项目地址: ht…...

有能力的已经在投了:这一批AI公司,正在悄悄招人

导读很多人还在盯着互联网大厂&#xff0c;反复刷岗位、反复改简历。但另一批人&#xff0c;已经把简历投向了另一条线——人工智能公司、机器人公司、智能制造公司。这些公司有一个共同点&#xff1a;岗位不多&#xff0c;但含金量极高要求更高&#xff0c;但成长速度更快很多…...

Go的unsafe.Pointer与uintptr:手动内存管理的风险与收益

Go语言以其简洁的内存管理模型著称&#xff0c;但标准库中的unsafe包却为开发者提供了手动操作内存的能力。unsafe.Pointer与uintptr这两个类型&#xff0c;允许绕过Go的类型安全检查&#xff0c;直接与底层内存交互。这种能力虽然强大&#xff0c;却也伴随着极高的风险。本文将…...

【ESP32开发实战:HTTP客户端高效连接物联网云平台】

1. ESP32与物联网云平台的高效连接之道 第一次用ESP32连接物联网云平台时&#xff0c;我盯着满屏的HTTP状态码和JSON数据发懵——明明官方示例代码能跑通&#xff0c;换成自己的项目就各种超时和内存溢出。后来才发现&#xff0c;物联网设备的HTTP通信就像外卖小哥送餐&#xf…...

三相四桥臂APF的双闭环控制的simulink仿真图,用的是Matlab2018a,可以看出

三相四桥臂APF的双闭环控制的simulink仿真图&#xff0c;用的是Matlab2018a&#xff0c;可以看出&#xff0c;控制前电网电流THD值达24%&#xff0c;中线电流10A&#xff0c;经过PID控制以后降低到了5%以下&#xff0c;母线电压稳定在800v,中线电流降为2A 随仿真有参考文献最近…...

python cython

## 当Python需要速度&#xff1a;聊聊Cython的里里外外 做Python开发时间长了&#xff0c;总会遇到一些让人头疼的场景。代码逻辑明明很清晰&#xff0c;运行起来却慢得让人想砸键盘。特别是那些涉及大量数值计算、循环嵌套的部分&#xff0c;用纯Python写起来优雅&#xff0c;…...

降AI后格式乱了怎么修:Word格式修复操作指南

降AI后格式乱了怎么修&#xff1a;Word格式修复操作指南 上周室友第一次用降AI工具&#xff0c;操作错了好几步&#xff0c;差点浪费机会。觉得有必要写一篇详细教程。 我用的是嘎嘎降AI&#xff08;www.aigcleaner.com&#xff09;&#xff0c;4.8元一篇&#xff0c;达标率9…...

金融级权限设计实战:用RBAC3模型搞定互斥角色、基数限制与操作审计

金融级权限架构设计&#xff1a;基于RBAC3模型的合规实战指南 在金融行业数字化转型浪潮中&#xff0c;权限管理系统不仅是技术组件&#xff0c;更是合规生命线。某跨国银行曾因角色权限漏洞导致数千万美元误操作&#xff0c;最终面临监管重罚——这个真实案例揭示了权限设计在…...

#星光计划4.0#鸿蒙界面设计技术解析与实战案例

鸿蒙界面设计技术解析与实战案例 随着万物互联时代的到来&#xff0c;鸿蒙操作系统&#xff08;HarmonyOS&#xff09;以“全场景智慧体验”为核心&#xff0c;构建了一套独特的界面设计体系。不同于传统单设备操作系统的界面逻辑&#xff0c;鸿蒙界面设计围绕“分布式协同、原…...