Skip to content

About

基于 Compose Multiplatform 开发的 Vant 风格 UI 组件库,支持 Android、iOS 和 Web(WasmJs) 平台。

Resources

Stars

48 stars

Watchers

1 watching

Forks

Repository files navigation

DLJetpackComposeUtil

基于 Compose Multiplatform 开发的 Vant 风格 UI 组件库,提供丰富的跨平台 UI 组件,支持 Android、iOS、JVM Desktop、JavaScript 和 WebAssembly 平台。

Version Kotlin Compose Multiplatform License

参考 Vant4 设计规范,提供统一的设计语言和用户体验。

目录

特性

  • 🚀 跨平台支持:发布 Android、iOS Arm64、iOS Simulator Arm64、JVM、JavaScript 和 WasmJs 制品
  • 🎨 统一设计风格:参考 Vant4 设计规范,提供一致的视觉体验
  • 📦 丰富的组件:提供 20+ 个高质量组件,覆盖常见的 UI 场景
  • 🔧 灵活的主题定制:支持自定义主题色、形状和文字样式
  • 📱 响应式设计:组件自适应不同屏幕尺寸
  • 🛠️ 易于使用:API 设计简洁直观,上手成本低

预览与文档

安装

1. 添加仓库

// settings.gradle.kts
dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral()
        maven("https://raw.githubusercontent.com/D10NGYANG/maven-repo/main/repository")
    }
}

2. 添加依赖

Kotlin Multiplatform 项目在 commonMain 中添加依赖:

// build.gradle.kts
kotlin {
    sourceSets {
        commonMain.dependencies {
            implementation("com.github.D10NGYANG:DLJetpackComposeUtil:3.4.0")
        }
    }
}

Android 或 JVM 单平台项目可直接添加:

dependencies {
    implementation("com.github.D10NGYANG:DLJetpackComposeUtil:3.4.0")
}

3. 版本兼容性

以下为 3.4.0 的构建与验收基线。组件调用 API 保持兼容,但 Android 构建工具要求已提升,升级前请阅读 3.4.0 升级说明。

项目 版本或要求
Kotlin 2.4.21
Compose Multiplatform 1.12.1
JetBrains Material3 1.12.0-alpha03
Gradle / AGP 9.8.1 / 9.1.1
Android compileSdk 37
Android minSdk 26
JVM toolchain 11

Compose 1.12 的 Android 制品要求 AGP 9.1+ 和 compileSdk 37。library 与 composeApp 使用 Android KMP library 插件;跨平台 Demo 的 Android 入口迁至 composeAndroidApp,应用 ID 保持 com.d10ng.compose.demo。原 androidApp 主题示例保持独立。

./gradlew :composeAndroidApp:assembleDebug
./gradlew :DLJetpackComposeUtil:jvmTest :DLJetpackComposeUtil:testAndroidHostTest
./gradlew :composeApp:wasmJsBrowserDevelopmentExecutableDistribution

Gradle 9.8.1 用于修复构建工具安全漏洞,高于 Kotlin 2.4.21 文档列出的完整测试上限 9.7.0;本项目构建与验证结果见迁移报告。库的 Android 发布改为单变体,已核验消费坐标仍为 DLJetpackComposeUtil-android。

4. Android 混淆配置

启用代码压缩时,可保留组件库公开类型:

-keep class com.d10ng.compose.** {*;}
-dontwarn com.d10ng.compose.**

快速开始

1. 初始化 UI 管理器

在应用的入口处初始化 UI 管理器,用于管理全局的 Toast、Dialog 等组件:

@Composable
fun App() {
    // 应用内容
    MaterialTheme(
        colorScheme = AppColor.toColorScheme()
    ) {
        // 你的应用内容
        // TODO
        // 初始化 UI 管理器
        UiViewModelManager.Init()
    }
}

2. 使用组件示例

@Composable
fun SampleScreen() {
    Column(
        modifier = Modifier.fillMaxSize().padding(16.dp)
    ) {
        // 按钮组件
        Button(
            text = "主要按钮",
            type = ButtonType.PRIMARY,
            onClick = {
                // 显示 Toast
                UiViewModelManager.showToast("点击了按钮")
            }
        )
        
        Spacer(modifier = Modifier.height(16.dp))
        
        // 输入框组件
        var text by remember { mutableStateOf("") }
        Field(
            value = text,
            onValueChange = { text = it },
            label = "用户名",
            placeholder = "请输入用户名"
        )
    }
}

组件列表

支持程度图标说明

  • ✅ 完全支持
  • ⚠️ 部分支持
  • ℹ️ 计划实现,但暂时未实现
  • 🚫 不考虑实现(原生已经有更好的)
类型 组件 支持程度 备注
基础组件 Button 按钮 ⚠️ 暂不支持渐变色背景、动画按钮
Cell 单元格 ✅
Toast 轻提示 ✅
表单组件 Calendar 日历 ℹ️ TODO
Cascader 级联选择 ℹ️ TODO
Checkbox 复选框 ✅
Field 输入框 ✅
Picker 选择器 ✅
PickerGroup 选择器组 ℹ️ TODO
Search 搜索 ✅
Slider 滑块 ℹ️ TODO
Stepper 步进器 ✅
Switch 开关 ✅
CheckButton 选择按钮 ✅
反馈组件 Sheet 动作面板 ✅
Dialog 弹出框 ✅
DropdownMenu 下拉菜单 ℹ️ TODO
Loading 加载 ✅
Notify 消息提示 ✅
Overlay 遮罩层 ✅
ShareSheet 分享面板 ℹ️ TODO
SwipeCell 滑动单元格 ℹ️ TODO
PullRefresh 下拉刷新 🚫 已废弃该自定义实现,建议直接使用 Compose 官方的 pullRefresh
展示组件 Badge 徽标 ✅
Collapse 折叠面板 ℹ️ TODO
CountDown 倒计时 ℹ️ TODO
Divider 分割线 🚫 不考虑二次封装,建议选择原生
Empty 空状态 ℹ️ TODO
ImagePreview 图片预览 ⚠️ 目前仅支持单张本地图片展示,拖拽效果需要进一步优化 发现做得更好的作品,jvziyaoyao/ImageViewer
NoticeBar 通知栏 ℹ️ TODO
Popover 气泡弹出框 ⚠️ 支持自动识别弹出方向(上下),以及靠左、靠右、居中,深色浅色风格,更多特性如"水平排列、显示图标、禁用选项"可自行在此基础上实现
Skeleton 骨架屏 ℹ️ TODO
Steps 步骤条 ⚠️ 暂不支持自定义样式、竖向步骤条
Swipe 轮播 ℹ️ TODO
Tag 标签 ✅
Avatar 头像 ✅
导航组件 ActionBar 动作栏 🚫
BackTop 回到顶部 🚫
Grid 宫格 🚫
IndexBar 索引栏 ✅
NavBar 导航栏 ✅
Pagination 分页 ℹ️ TODO
Sidebar 侧边导航 ℹ️ TODO
Tab 标签页 ℹ️ TODO
Tabbar 标签栏 ℹ️ TODO
TreeSelect 分类选择 ℹ️ TODO

主要组件使用示例

Button 按钮

// 基础按钮
Button(
    text = "按钮",
    onClick = { /* 点击事件 */ }
)

// 主要按钮
Button(
    text = "主要按钮",
    type = ButtonType.PRIMARY,
    onClick = { /* 点击事件 */ }
)

// 成功按钮
Button(
    text = "成功按钮",
    type = ButtonType.SUCCESS,
    onClick = { /* 点击事件 */ }
)

// 警告按钮
Button(
    text = "警告按钮",
    type = ButtonType.WARNING,
    onClick = { /* 点击事件 */ }
)

// 危险按钮
Button(
    text = "危险按钮",
    type = ButtonType.DANGER,
    onClick = { /* 点击事件 */ }
)

// 朴素按钮
Button(
    text = "朴素按钮",
    type = ButtonType.PRIMARY,
    plain = true,
    onClick = { /* 点击事件 */ }
)

// 禁用状态
Button(
    text = "禁用按钮",
    disabled = true,
    onClick = { /* 点击事件 */ }
)

// 加载状态
Button(
    text = "加载中",
    loading = true,
    onClick = { /* 点击事件 */ }
)

// 按钮尺寸
Button(
    text = "大号按钮",
    size = ButtonSize.LARGE,
    onClick = { /* 点击事件 */ }
)

Button(
    text = "小号按钮",
    size = ButtonSize.SMALL,
    onClick = { /* 点击事件 */ }
)

Button(
    text = "迷你按钮",
    size = ButtonSize.MINI,
    onClick = { /* 点击事件 */ }
)

Field 输入框

var text by remember { mutableStateOf("") }

Field(
    value = text,
    onValueChange = { text = it },
    label = "用户名",
    placeholder = "请输入用户名"
)

// 密码输入框
Field(
    value = password,
    onValueChange = { password = it },
    label = "密码",
    type = KeyboardType.Password
)

// 带清除按钮的输入框
Field(
    value = text,
    onValueChange = { text = it },
    label = "搜索",
    canClear = true
)

// 只读输入框
Field(
    value = "只读内容",
    onValueChange = {},
    label = "只读",
    readonly = true
)

// 禁用输入框
Field(
    value = "禁用内容",
    onValueChange = {},
    label = "禁用",
    disabled = true
)

// 错误提示
Field(
    value = text,
    onValueChange = { text = it },
    label = "手机号",
    error = if (text.length != 11) "请输入11位手机号" else ""
)

Dialog 对话框

// 确认对话框
val dialogId = UiViewModelManager.showDialog(
    ConfirmDialogBuilder(
        title = "标题",
        content = "这是一条确认信息,是否继续?",
        onConfirm = {
            // 确认操作
            UiViewModelManager.hideDialog(it)
        },
        onCancel = {
            // 取消操作
            UiViewModelManager.hideDialog(it)
        }
    )
)

// 输入对话框
val inputDialogId = UiViewModelManager.showDialog(
    InputDialogBuilder(
        title = "输入框标题",
        content = "请输入内容",
        placeholder = "请输入",
        onConfirm = { id, text ->
            // 处理输入内容
            UiViewModelManager.hideDialog(id)
        }
    )
)

// 提示对话框
val tipsDialogId = UiViewModelManager.showDialog(
    TipsDialogBuilder(
        title = "提示",
        content = "操作成功!",
        onConfirm = {
            UiViewModelManager.hideDialog(it)
        }
    )
)

Toast 轻提示

// 普通提示
UiViewModelManager.showToast("这是一条提示消息")

// 成功提示
UiViewModelManager.showSuccessToast("操作成功")

// 失败提示
UiViewModelManager.showFailToast("操作失败")

// 加载提示
UiViewModelManager.showLoading("加载中...")
// 隐藏加载
UiViewModelManager.hideLoading()

Notify 消息通知

// 主要通知
UiViewModelManager.showNotify(NotifyType.Primary, "这是一条通知消息")

// 成功通知
UiViewModelManager.showNotify(NotifyType.Success, "操作成功")

// 警告通知
UiViewModelManager.showNotify(NotifyType.Warning, "注意事项")

// 错误通知
UiViewModelManager.showErrorNotify("发生错误")

Badge 徽标

// 红点徽标
Badge()

// 数字徽标
Badge(content = "5")

// 最大值徽标
Badge(num = 100, max = 99) // 显示 "99+"

// 自定义颜色
Badge(content = "NEW", color = Color.Blue)

// 徽标与内容组合
BadgeBox(
    badge = { Badge(content = "5") }
) {
    Icon(
        painter = painterResource(id = R.drawable.ic_notification),
        contentDescription = "通知"
    )
}

Tag 标签

// 基础标签
Tag(text = "标签")

// 主要标签
Tag(text = "标签", type = TagType.PRIMARY)

// 成功标签
Tag(text = "标签", type = TagType.SUCCESS)

// 警告标签
Tag(text = "标签", type = TagType.WARNING)

// 危险标签
Tag(text = "标签", type = TagType.DANGER)

// 朴素标签
Tag(text = "标签", type = TagType.PRIMARY, plain = true)

// 圆角标签
Tag(text = "标签", round = true)

// 可关闭标签
Tag(
    text = "标签",
    closeable = true,
    onClose = { /* 关闭事件 */ }
)

主题定制

DLJetpackComposeUtil 提供了灵活的主题定制能力,可以根据项目需求自定义颜色、形状和文字样式。组件库的颜色系统与 Material 3 的色彩角色紧密集成,通过 AppColor.toColorScheme() 方法将自定义颜色映射到 Material 3 的 ColorScheme。

Material 3 色彩介绍

颜色定制

组件库的颜色系统分为三大类:

1. 主色系统 (AppColor.Main)

主色系统定义了应用的核心颜色,直接映射到 Material 3 的主要色彩角色:

// 主色系统
AppColor.Main.primary = Color(0xFF1989FA)    // 主题色,映射到 M3 的 primary
AppColor.Main.secondary = Color(0xFF07C160)  // 第二主题色,映射到 M3 的 secondary
AppColor.Main.tertiary = Color(0xFFEE0A24)   // 第三主题色,映射到 M3 的 tertiary

2. 功能色系统 (AppColor.Func)

功能色系统定义了表达特定语义的颜色:

// 功能色系统
AppColor.Func.link = Color(0xFF576B95)      // 链接色,用于可点击文本
AppColor.Func.success = Color(0xFF07C160)   // 成功色,映射到相关组件的成功状态
AppColor.Func.error = Color(0xFFEE0A24)     // 错误色,映射到 M3 的 error
AppColor.Func.notice = Color(0xFFED6A0C)    // 通知色,用于警告和通知
AppColor.Func.noticeBg = Color(0xFFFFFBE8)  // 通知背景色
AppColor.Func.assist = Color(0xFFFAAB0C)    // 辅助色,用于强调和提示

3. 中性色系统 (AppColor.Neutral)

中性色系统定义了界面的基础色调,映射到 Material 3 的表面和文本颜色:

// 中性色系统
AppColor.Neutral.surface = Color(0xFFFEFEFE)  // 表面色,映射到 M3 的 surface
AppColor.Neutral.bg = Color(0xFFF7F8FA)       // 背景色,映射到 M3 的 background
AppColor.Neutral.card = Color(0xFFF2F3F5)     // 卡片背景色,映射到 M3 的 surfaceVariant
AppColor.Neutral.line = Color(0xFFEBEDF0)     // 线条色,映射到 M3 的 outlineVariant
AppColor.Neutral.border = Color(0xFFDCDEF0)   // 边框色,映射到 M3 的 outline
AppColor.Neutral.hint = Color(0xFFC8C9CC)     // 提示文本色,用于占位符和禁用状态
AppColor.Neutral.tips = Color(0xFF969799)     // 辅助文本色,用于次要信息
AppColor.Neutral.body = Color(0xFF646566)     // 正文文本色,映射到 M3 的 onSurfaceVariant
AppColor.Neutral.title = Color(0xFF323233)    // 标题文本色,映射到 M3 的 onSurface 和 onBackground
AppColor.Neutral.scrim = Color(0xFF010101)    // 遮罩色,映射到 M3 的 scrim

Material 3 色彩映射

组件库通过 AppColor.toColorScheme() 方法将自定义颜色映射到 Material 3 的 ColorScheme。这个方法不仅直接映射基础颜色,还通过 makeRelatedColors() 函数自动生成相关的配色方案,确保整个应用的色彩协调一致。

// 在应用入口处应用自定义主题
MaterialTheme(
    colorScheme = AppColor.apply {
        // 自定义颜色,只有在此之前设置颜色才能生效
        AppColor.Main.primary = Color.Red
    }.toColorScheme()
) {
    // 应用内容
}
基础颜色映射
Material 3 色彩角色 DLJetpackComposeUtil 颜色
primary AppColor.Main.primary
secondary AppColor.Main.secondary
tertiary AppColor.Main.tertiary
error AppColor.Func.error
background AppColor.Neutral.bg
surface AppColor.Neutral.surface
onBackground AppColor.Neutral.title
onSurface AppColor.Neutral.title
surfaceVariant AppColor.Neutral.card
onSurfaceVariant AppColor.Neutral.body
outline AppColor.Neutral.border
outlineVariant AppColor.Neutral.line
scrim AppColor.Neutral.scrim
surfaceTint AppColor.Main.primary
自动生成的相关颜色

组件库使用 makeRelatedColors() 函数基于主要颜色自动生成相关的配色:

// 基于主色生成相关颜色
val primaryRelatedColors = Main.primary.makeRelatedColors()
// primaryRelatedColors[0] → onPrimary
// primaryRelatedColors[1] → primaryContainer
// primaryRelatedColors[2] → onPrimaryContainer
// primaryRelatedColors[3] → inversePrimary
Material 3 色彩角色 生成方式
onPrimary primaryRelatedColors[0]
primaryContainer primaryRelatedColors[1]
onPrimaryContainer primaryRelatedColors[2]
inversePrimary primaryRelatedColors[3]
onSecondary secondaryRelatedColors[0]
secondaryContainer secondaryRelatedColors[1]
onSecondaryContainer secondaryRelatedColors[2]
onTertiary tertiaryRelatedColors[0]
tertiaryContainer tertiaryRelatedColors[1]
onTertiaryContainer tertiaryRelatedColors[2]
onError errorRelatedColors[0]
errorContainer errorRelatedColors[1]
onErrorContainer errorRelatedColors[2]
表面变体颜色

组件库还使用 next() 函数基于 Neutral.surface 生成多种表面变体颜色:

Material 3 色彩角色 生成方式
inverseSurface Neutral.surface.next(亮度调整)
inverseOnSurface 根据surface亮度自动选择黑色或白色
surfaceBright Neutral.surface.next(1.0)
surfaceDim Neutral.surface.next(-0.3)
surfaceContainer Neutral.surface.next(-0.2)
surfaceContainerHigh Neutral.surface.next(-0.3)
surfaceContainerHighest Neutral.surface.next(-0.4)
surfaceContainerLow Neutral.surface.next(-0.1)
surfaceContainerLowest Neutral.surface.next(1.0)

形状定制

// 使用预定义的圆角
val buttonShape = AppShape.RC.v8 // 8dp 圆角
val cardShape = AppShape.RC.v16 // 16dp 圆角
val chipShape = AppShape.RC.Cycle // 圆形

文字样式定制

// 标题文字样式
val titleStyle = AppText.Bold.Title.large // 粗体大号标题
val subtitleStyle = AppText.Medium.Title.default // 中等粗细默认标题

// 内容文字样式
val bodyStyle = AppText.Normal.Body.default // 正常粗细默认内容
val smallBodyStyle = AppText.Normal.Body.small // 正常粗细小号内容

// 强调文字样式
val primaryStyle = AppText.Bold.Primary.default // 粗体主题色文字
val errorStyle = AppText.Medium.Error.default // 中等粗细错误色文字

版本日志

3.4.0(2026-10-10)

  • 升级 Compose Multiplatform 1.12.1、Material3 1.12.0-alpha03、Lifecycle 2.11.0、Navigation3 1.1.2,Android Demo 使用 DLAppUtil 2.7.1。
  • 采用带安全修复的 Gradle 9.8.1,并固定官方 SHA-256;配套迁移 AGP 9.1.1、Kotlin 2.4.21 和 compileSdk 37。
  • KMP 模块改用 Android KMP library 插件,跨平台 Demo 的 Android 启动入口拆至 composeAndroidApp;应用 ID、minSdk 和 targetSdk 保持原值。
  • Sheet 适配 rememberBottomSheetState,显式仅启用 Hidden/Expanded,保留关闭策略与公开 Builder API。
  • 补充 Activity 重建、选图结果与预览、真实系统选图器取消和强制 Sheet 的 Android 仪器测试;完成多平台构建、19 项测试执行及 Web/Android/iOS UI 验证。
  • 完整兼容性要求、升级步骤和验证边界见 3.4.0 发布与升级说明。

3.3.5(2026-08-18)

本版本聚焦兼容性、稳定性和性能,不增加调用方迁移成本,不调整组件正常状态下的视觉样式。

  • 修复 Button、Checkbox、Radio 的禁用与加载状态处理,避免状态变化后仍使用旧值,并补充标准交互语义。
  • 修复 ImagePreview 缩放边界、无效图片路径和手势回调更新问题。
  • 修复 IndexBar 触摸越界、手势取消后状态残留和回调未更新问题。
  • 修复 Picker 滚动吸附越界及非法选中项处理;Picker 和 MultiPicker 继续要求选项集合非空。
  • 修复 DatePicker、TimePicker 的反向范围、越界值、月份天数和边界联动问题。
  • 修复 TimePickerSheetBuilder 初始值与选择模式不一致的问题,并对 MultiPickerSheetBuilder 空列配置明确报错。
  • 优化 Input 焦点请求生命周期,避免每次重组重复请求焦点,并过滤重复的焦点边沿回调。
  • 增加 Modifier 非法参数保护和北斗信号强度范围保护。
  • 保持 3.3.4 的公开类、函数参数、主题颜色和正常布局不变。

3.3.4(2026-07-10)

  • 优化 Sheet 展示时的焦点清理和虚拟键盘收起逻辑。

许可证

DLJetpackComposeUtil 使用 MIT 许可证。

About

基于 Compose Multiplatform 开发的 Vant 风格 UI 组件库,支持 Android、iOS 和 Web(WasmJs) 平台。

Resources

Stars

48 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages