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

Android开发实战班 - 现代 UI 开发之自定义 Compose 组件

Jetpack Compose 不仅提供了丰富的内置组件,还允许开发者根据项目需求创建自定义组件。自定义 Compose 组件可以提高代码复用性、简化 UI 逻辑,并使应用界面更加一致和模块化。本章节将介绍如何创建自定义 Compose 组件,包括组件的创建、样式定制、状态管理以及在项目中的应用。

为什么需要自定义 Compose 组件

  • 代码复用:

    • 通过创建自定义组件,可以将常用的 UI 逻辑封装起来,避免重复代码,提高代码复用性。
  • 简化 UI 逻辑:

    • 将复杂的 UI 逻辑封装到自定义组件中,可以简化调用代码,使代码更简洁易懂。
  • 一致性:

    • 自定义组件可以保证应用界面的一致性,例如统一的按钮样式、输入框样式等。
  • 模块化:

    • 自定义组件可以将 UI 拆分成更小的模块,便于维护和测试。

创建自定义 Compose 组件

创建自定义 Compose 组件非常简单,只需定义一个带有 @Composable 注解的函数即可。以下是一个简单的自定义按钮组件示例:

import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp@Composable
fun MyButton(text: String,onClick: () -> Unit,modifier: Modifier = Modifier,backgroundColor: Color = MaterialTheme.colorScheme.primary,contentColor: Color = MaterialTheme.colorScheme.onPrimary
) {Text(text = text,modifier = modifier.clip(RoundedCornerShape(8.dp)).background(backgroundColor).clickable { onClick() }.padding(vertical = 12.dp, horizontal = 16.dp),color = contentColor,style = MaterialTheme.typography.labelLarge)
}
  • 参数说明:

    • text: 按钮显示的文本。
    • onClick: 按钮点击事件回调。
    • modifier: 修饰符,用于自定义按钮的布局和样式。
    • backgroundColor: 按钮背景颜色,默认为主题主色。
    • contentColor: 按钮文本颜色,默认为主题主色文本颜色。
  • 使用自定义按钮:

    MyButton(text = "Click Me",onClick = { /* 处理点击事件 */ },modifier = Modifier.align(Alignment.Center)
    )
    

样式定制

自定义 Compose 组件可以通过参数传递样式,例如颜色、字体、形状等,从而实现样式的定制。

  • 颜色定制:

    • 可以通过参数传递不同的颜色值来定制组件的颜色。
      MyButton(text = "Red Button",onClick = { /* 处理点击事件 */ },backgroundColor = Color.Red,contentColor = Color.White
      )
      
  • 字体和排版:

    • 可以通过 MaterialTheme.typography 来定制组件的字体和排版。
      MyButton(text = "Large Button",onClick = { /* 处理点击事件 */ },modifier = Modifier.padding(16.dp),style = MaterialTheme.typography.headlineMedium
      )
      
  • 形状定制:

    • 可以通过 clip()RoundedCornerShape 等函数来定制组件的形状。
      MyButton(text = "Rounded Button",onClick = { /* 处理点击事件 */ },modifier = Modifier.clip(RoundedCornerShape(16.dp))
      )
      

状态管理

自定义 Compose 组件可以管理自己的状态,例如按钮的选中状态、输入框的内容等。

  • 按钮选中状态:

    @Composable
    fun ToggleButton(text: String,isSelected: Boolean,onToggle: (Boolean) -> Unit,modifier: Modifier = Modifier
    ) {val backgroundColor = if (isSelected) MaterialTheme.colorScheme.primary else Color.Grayval contentColor = if (isSelected) MaterialTheme.colorScheme.onPrimary else Color.WhiteText(text = text,modifier = modifier.clip(RoundedCornerShape(8.dp)).background(backgroundColor).clickable { onToggle(!isSelected) }.padding(vertical = 12.dp, horizontal = 16.dp),color = contentColor,style = MaterialTheme.typography.labelLarge)
    }// 使用 ToggleButton
    var isButtonSelected by remember { mutableStateOf(false) }ToggleButton(text = "Toggle Me",isSelected = isButtonSelected,onToggle = { isButtonSelected = it }
    )
    
  • 输入框内容状态:

    @Composable
    fun MyTextField(value: String,onValueChange: (String) -> Unit,modifier: Modifier = Modifier,label: String = ""
    ) {TextField(value = value,onValueChange = onValueChange,label = { Text(text = label) },modifier = modifier,colors = TextFieldDefaults.textFieldColors(containerColor = MaterialTheme.colorScheme.secondaryContainer,textColor = MaterialTheme.colorScheme.onSecondaryContainer,placeholderColor = MaterialTheme.colorScheme.onSecondaryContainer.copy(alpha = 0.5f)))
    }// 使用 MyTextField
    var text by remember { mutableStateOf("") }MyTextField(value = text,onValueChange = { text = it },label = "Enter text"
    )
    

实战案例

  1. 案例一:自定义导航栏组件

    • 创建一个自定义导航栏组件,包含多个导航项。
    • 使用 RowButton 组件实现导航栏布局。
    • 通过参数传递导航项列表和点击事件回调。
    @Composable
    fun MyNavigationBar(items: List<String>,onItemClick: (String) -> Unit,modifier: Modifier = Modifier
    ) {Row(modifier = modifier) {items.forEach { item ->MyButton(text = item,onClick = { onItemClick(item) },modifier = Modifier.weight(1f))}}
    }// 使用 MyNavigationBar
    val navigationItems = listOf("Home", "Settings", "Profile")
    var selectedItem by remember { mutableStateOf("Home") }MyNavigationBar(items = navigationItems,onItemClick = { selectedItem = it }
    )
    
  2. 自定义卡片组件

    • 创建一个自定义卡片组件,包含标题、内容和按钮。
    • 使用 Card, Column, Text, Button 等组件实现卡片布局。
    • 通过参数传递标题、内容和按钮文本。
    @Composable
    fun MyCard(title: String,content: String,buttonText: String,onButtonClick: () -> Unit,modifier: Modifier = Modifier
    ) {Card(modifier = modifier,elevation = CardDefaults.cardElevation(defaultElevation = 4.dp),shape = RoundedCornerShape(8.dp)) {Column(modifier = Modifier.padding(16.dp)) {Text(text = title,style = MaterialTheme.typography.titleMedium,modifier = Modifier.padding(bottom = 8.dp))Text(text = content,style = MaterialTheme.typography.bodyMedium,modifier = Modifier.padding(bottom = 12.dp))MyButton(text = buttonText,onClick = onButtonClick)}}
    }// 使用 MyCard
    MyCard(title = "Welcome",content = "Thank you for using our app!",buttonText = "OK",onButtonClick = { /* 处理按钮点击事件 */ }
    )
    

课后作业

  1. 任务一:创建一个自定义按钮组件

    • 定义一个自定义按钮组件 MyButton,包含文本、点击事件、颜色、字体等参数。
    • 使用 Modifier 和 Compose 布局组件实现按钮布局。
    • 在应用中调用 MyButton 组件,并传递不同的参数。
  2. 任务二:创建一个自定义卡片组件

    • 定义一个自定义卡片组件 MyCard,包含标题、内容、按钮文本和点击事件等参数。
    • 使用 Card, Column, Text, Button 等组件实现卡片布局。
    • 在应用中调用 MyCard 组件,并传递不同的参数。
  3. 任务三:实现一个自定义导航栏组件

    • 定义一个自定义导航栏组件 MyNavigationBar,包含导航项列表和点击事件回调。
    • 使用 RowMyButton 组件实现导航栏布局。
    • 在应用中调用 MyNavigationBar 组件,并传递导航项列表和点击事件回调。

通过本章节的学习,学员将能够掌握创建自定义 Compose 组件的方法,包括组件的创建、样式定制、状态管理以及在项目中的应用,从而提高代码复用性、简化 UI 逻辑,并使应用界面更加一致和模块化。

作者简介

前腾讯电子签的前端负责人,现 whentimes tech CTO,专注于前端技术的大咖一枚!一路走来,从小屏到大屏,从 Web 到移动,什么前端难题都见过。热衷于用技术打磨产品,带领团队把复杂的事情做到极简,体验做到极致。喜欢探索新技术,也爱分享一些实战经验,帮助大家少走弯路!

温馨提示:可搜老码小张公号联系导师

相关文章:

Android开发实战班 - 现代 UI 开发之自定义 Compose 组件

Jetpack Compose 不仅提供了丰富的内置组件&#xff0c;还允许开发者根据项目需求创建自定义组件。自定义 Compose 组件可以提高代码复用性、简化 UI 逻辑&#xff0c;并使应用界面更加一致和模块化。本章节将介绍如何创建自定义 Compose 组件&#xff0c;包括组件的创建、样式…...

All-in-one Notion 介绍

Notion 是一款集笔记、知识管理、任务规划和协作于一体的工具&#xff0c;它以高度的灵活性和可自定义的工作空间而闻名。它适合个人和团队使用&#xff0c;能够帮助用户高效管理生活、学习和工作。以下是 Notion 的一些主要特点&#xff1a; 1. 多功能工作区 Notion 将笔记、…...

深入理解C++11右值引用与移动语义:高效编程的基石

文章目录 前言&#x1f4da;一、C11的历史发展&#x1f4d6;1.1 C11 之前的背景&#x1f4d6;1.2 C11 的发展历程&#x1f4d6;1.3 C11 的主要设计目标&#x1f4d6;1.4 C11 的主要特性&#x1f4d6;1.5 C11 的影响 &#x1f4da;二、统一的列表初始化&#x1f4d6;2.1 基本列表…...

【WRF-Urban】URBPARM_LCZ.TBL 查找表解释及内容

【WRF-Urban】URBPARM_LCZ.TBL 查找表解释及内容 URBPARM_LCZ.TBL 文件的作用URBPARM_LCZ.TBL 文件中的参数URBPARM_LCZ.TBL 的使用URBPARM_LCZ.TBL 文件内容如何调整或扩展 URBPARM_LCZ.TBL参考URBPARM_LCZ.TBL 文件是 WRF(天气研究与预报模型) 中用于处理 局地气候区(Loca…...

网络是怎么连接的

目录 URL HTTP&#xff08;超文本传输协议&#xff09; FTP&#xff08;文件传输协议&#xff09; File mailto HTTP的方法 Socket URL URL&#xff08;Uniform Resource Locator&#xff09;中文名为统一资源定位符&#xff0c;它是互联网上用来标识某一资源的地址。就…...

Java 实现PDF添加水印

maven依赖&#xff1a; <dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.4.3</version> </dependency>网络地址添加水印代码&#xff1a; public static boolean waterMarkNet(Stri…...

网络安全问题概述

1.1.计算机网络面临的安全性威胁 计算机网络上的通信面临以下的四种威胁&#xff1a; (1) 截获——从网络上窃听他人的通信内容。 (2) 中断——有意中断他人在网络上的通信。 (3) 篡改——故意篡改网络上传送的报文。可应用于域名重定向&#xff0c;即钓鱼网站。 (4) 伪造——伪…...

(udp)网络编程套接字Linux(整理)

源IP地址和目的IP地址 唐僧例子1 在IP数据包头部中, 有两个IP地址, 分别叫做源IP地址, 和目的IP地址.思考: 我们光有IP地址就可以完成通信了嘛? 想象一下发qq消息的例子, 有了IP地址能够把消息发送到对方的机器上,但是还需要有一个其他的标识来区分出, 这个数据要给哪个程序进…...

Web应用安全入门:架构搭建、漏洞分析与HTTP数据包处理

Web应用安全入门&#xff1a;架构搭建、漏洞分析与HTTP数据包处理 引言 在当今数字化时代&#xff0c;Web应用已成为企业和个人在线交互的核心。然而&#xff0c;随着技术的发展&#xff0c;Web应用面临的安全挑战也日益增加。本文旨在为初学者提供一个关于Web应用架构搭建、…...

[JAVA]MyBatis框架—获取SqlSession对象

SqlSessionFactory作为MyBatis框架的核心接口有三大特性 SqlSessionFactory是MyBatis的核心对象 用于初始化MyBatis&#xff0c;创建SqlSession对象 保证SqlSessionFactory在应用中全局唯一 1.SqlSessionFactory是MyBatis的核心对象 假设我们要查询数据库的用户信息&#x…...

Perl 简介

Perl 简介 Perl 是一种高级、通用、解释型、动态编程语言。由 Larry Wall 于 1987 年首次发布&#xff0c;它结合了 C、sed、awk 和 shell 脚本语言的特性。Perl 最初被设计用于文本处理&#xff0c;如报告生成和文件转换&#xff0c;但随着时间的推移&#xff0c;它已经发展成…...

spring-bean的销毁流程

1 引入 在 Spring 框架中&#xff0c;Bean 的生命周期管理是其核心功能之一&#xff0c;而 Bean 的注销&#xff08;Destruction&#xff09;是生命周期的最后一步。无论是关闭数据库连接、释放线程资源&#xff0c;还是执行缓存持久化操作&#xff0c;合适的销毁策略都至关重…...

问:Spring MVC DispatcherServlet流程步骤梳理

DispatcherServlet是Spring MVC框架中的核心组件&#xff0c;负责接收客户端请求并将其分发到相应的控制器进行处理。作为前端控制器&#xff08;Front Controller&#xff09;的实现&#xff0c;DispatcherServlet在整个请求处理流程中扮演着至关重要的角色。本文将探讨Dispat…...

用源码编译虚幻引擎,并打包到安卓平台

用源码编译虚幻引擎&#xff0c;并打包到安卓平台 前往我的博客,获取更优的阅读体验 作业内容: 源码编译UE5.4构建C项目&#xff0c;简单设置打包到安卓平台 编译虚幻 5 前置内容 这里需要将 Epic 账号和 Github 账号绑定&#xff0c;然后加入 Epic 邀请的组织&#xff0c…...

快速搭建Android开发环境:Docker部署docker-android并实现远程连接

目录 前言 1. 虚拟化环境检查 2. Android 模拟器部署 3. Ubuntu安装Cpolar 4. 配置公网地址 5. 远程访问 小结 6. 固定Cpolar公网地址 7. 固定地址访问 作者简介&#xff1a; 懒大王敲代码&#xff0c;计算机专业应届生 今天给大家聊聊快速搭建Android开发环境&#x…...

「Mac玩转仓颉内测版21」基础篇1 - 仓颉程序的基本组成

本篇将系统介绍Cangjie编程语言中程序的基本组成部分&#xff0c;涵盖 main 函数的定义、包与模块的使用、变量类型、作用域和代码结构原则&#xff0c;帮助开发者理解Cangjie程序的整体结构。 关键词 程序入口点main函数包与模块变量类型与作用域值类型与引用类型代码结构与规…...

【Linux网络编程】简单的UDP套接字

目录 一&#xff0c;socket编程的相关说明 1-1&#xff0c;sockaddr结构体 1-2&#xff0c;Socket API 二&#xff0c;基于Udp协议的简单通信 三&#xff0c;UDP套接字的应用 3-1&#xff0c;实现英译汉字典 一&#xff0c;socket编程的相关说明 Socket编程是一种网络通信…...

在Vue中使用Excalidraw实现在线画板

概述 Excalidraw是一个非常好用的画图板工具&#xff0c;但是是用React写的&#xff0c;本文分享一种在Vue项目中使用的方法。 效果 实现 Excalidraw简介 这篇文章(Excalidraw 完美的绘图工具&#xff1a;https://zhuanlan.zhihu.com/p/684940131)介绍的很全面&#xff0c;…...

游戏+AI的发展历程,AI技术在游戏行业的应用有哪些?

人工智能&#xff08;AI&#xff09;与游戏的结合&#xff0c;不仅是技术进步的体现&#xff0c;更是人类智慧的延伸。从最初的简单规则到如今的复杂决策系统&#xff0c;AI在游戏领域的发展历史可谓波澜壮阔。 早在2001年&#xff0c;就有研究指出游戏人工智能领域&#xff0…...

Methode Electronics EDI 需求分析

Methode Electronics 是一家总部位于美国的全球性技术公司&#xff0c;专注于设计和制造用于多个行业的电子和电气组件&#xff0c;产品涵盖汽车、工业、电信、医疗设备以及消费电子等多个领域&#xff0c;提供创新的解决方案。 填写Methode_EDI_Parameters_Template Methode_…...

MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例

一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...

Admin.Net中的消息通信SignalR解释

定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...

Docker 运行 Kafka 带 SASL 认证教程

Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明&#xff1a;server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...

Golang dig框架与GraphQL的完美结合

将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用&#xff0c;可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器&#xff0c;能够帮助开发者更好地管理复杂的依赖关系&#xff0c;而 GraphQL 则是一种用于 API 的查询语言&#xff0c;能够提…...

Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器

第一章 引言&#xff1a;语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域&#xff0c;文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量&#xff0c;支撑着搜索引擎、推荐系统、…...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列&#xff0c;以便知晓哪些列包含有价值的数据&#xff0c;…...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!

简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求&#xff0c;并检查收到的响应。它以以下模式之一…...

安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)

船舶制造装配管理现状&#xff1a;装配工作依赖人工经验&#xff0c;装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书&#xff0c;但在实际执行中&#xff0c;工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...

CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)

漏洞概览 漏洞名称&#xff1a;Apache Flink REST API 任意文件读取漏洞CVE编号&#xff1a;CVE-2020-17519CVSS评分&#xff1a;7.5影响版本&#xff1a;Apache Flink 1.11.0、1.11.1、1.11.2修复版本&#xff1a;≥ 1.11.3 或 ≥ 1.12.0漏洞类型&#xff1a;路径遍历&#x…...

现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?

现有的 Redis 分布式锁库&#xff08;如 Redisson&#xff09;相比于开发者自己基于 Redis 命令&#xff08;如 SETNX, EXPIRE, DEL&#xff09;手动实现分布式锁&#xff0c;提供了巨大的便利性和健壮性。主要体现在以下几个方面&#xff1a; 原子性保证 (Atomicity)&#xff…...