CmComposeUI —— 基于 Kotlin Multiplatform Compose 的 UI 组件库

版本号

CmComposeUI 是一个基于 Kotlin Multiplatform Compose 的 UI 组件库,提供丰富的通用组件,支持 Android 和 iOS 双平台。

引入使用

在项目根目录 settings.gradle.kts 添加 JitPack 仓库:

kotlin 复制代码
dependencyResolutionManagement {
    repositories {
        maven { url = uri("https://jitpack.io") }
    }
}

在共享代码模块 composeApp/src/commonMain/kotlinbuild.gradle.kts 中添加依赖:

重要说明 :这是一个多模块项目,JitPack 需要指定 composeApp 子模块。

kotlin 复制代码
kotlin {
    sourceSets {
        commonMain {
            dependencies {
                implementation("com.github.Peakmain.CmComposeUI:composeApp:latest-version")
            }
        }
    }
}

或者简写方式:

kotlin 复制代码
dependencies {
    commonMainImplementation("com.github.Peakmain.CmComposeUI:composeApp:latest-version")
}

项目结构

bash 复制代码
composeApp/
├── src/
│   ├── commonMain/
│   │   └── kotlin/com/peakmain/cmp_compose/
│   │       ├── basic/               # 基础常量
│   │       │   ├── BasicColor.kt    # 颜色常量
│   │       │   ├── BasicFont.kt     # 字体大小常量
│   │       │   └── BasicSize.kt     # 尺寸常量
│   │       ├── space/               # 间距
│   │       │   └── PkSpacer.kt      # 间距组件
│   │       ├── theme/               # 主题
│   │       ├── ui/                  # UI 组件
│   │       │   ├── banner/          # 轮播
│   │       │   │   └── PkBanner.kt  # 轮播组件
│   │       │   ├── button/          # 按钮
│   │       │   │   ├── PkButton.kt  # 按钮组件
│   │       │   │   └── PkButtonDefault.kt  # 默认配置
│   │       │   ├── cell/           # 单元格
│   │       │   │   └── PkCell.kt    # 单元格组件
│   │       │   ├── divier/         # 分割线
│   │       │   │   ├── PkDivider.kt # 分割线组件
│   │       │   │   ├── PkDashDivider.kt
│   │       │   │   └── PkFullDivider.kt
│   │       │   ├── flow/           # 流式布局
│   │       │   │   └── PkFlowRow.kt
│   │       │   ├── grid/           # 瀑布流
│   │       │   │   └── PkStaggeredVerticalGrid.kt
│   │       │   ├── image/          # 图片
│   │       │   │   └── PkImageView.kt
│   │       │   ├── progress/       # 进度条
│   │       │   │   └── RoundedLinearProgressIndicator.kt
│   │       │   ├── text/           # 文本
│   │       │   │   └── PkHighlightText.kt
│   │       │   └── title/          # 标题/导航栏
│   │       │       ├── PkNavBar.kt # 顶部导航栏
│   │       │       └── PkTitle.kt  # 标题文本
│   │       └── utils/               # 工具类
│   ├── androidMain/                # Android 平台代码
│   └── iosMain/                    # iOS 平台代码
└── ...

3. 基础组件

3.1. 顶部应用栏(AppBar)组件

3.1.1. 介绍

TopAppBarCenter 是一个高度定制的顶部应用栏(App Bar)组件,基于 Jetpack Compose 实现。主要特性包括:

  • 标题居中显示,支持自定义标题内容
  • 可配置左侧导航图标(如返回按钮)和右侧操作图标组
  • 支持沉浸式状态栏(透明状态栏,内容延伸到状态栏下方)
  • 动态控制状态栏图标颜色(深色或浅色)
  • 无缝集成 Scaffold,可直接作为其 TopBar 参数使用

3.1.2. 参数

参数名 参数类型 是否必填 默认值 说明
title @Composable () -> Unit 标题内容(支持任意 Composable 内容,默认居中显示)
modifier Modifier Modifier 布局修饰符,会与组件内部修饰符合并
navigationIcon @Composable (() -> Unit)? null 左侧导航图标(如返回按钮),若为 null则不显示
backgroundColor Color MaterialTheme.colors.primarySurface 应用栏背景颜色
actions @Composable RowScope.() -> Unit {} 右侧操作图标组(可包含多个图标按钮)
isImmersive Boolean false 是否启用沉浸式状态栏(透明状态栏,内容向上延伸)
darkIcons Boolean false 状态栏图标颜色是否为深色(true为黑色,false为白色),仅在 isImmersive=true时生效
content @Composable (PaddingValues) -> Unit 页面主体内容(通过 Scaffold插入到应用栏下方)

3.1.3. 示例代码

ini 复制代码
@Composable
fun HomeFragment() {
    TopAppBarCenter(
        title = {
            Text(text = "首页", color = Color.White)
        },
        isImmersive = true,
        modifier = Modifier.background(Brush.linearGradient(listOf(Color_149EE7, Color_2DCDF5)))
    ) {

        Column(
            modifier = Modifier
                .padding(BasicSpace.space_18)
                .fillMaxSize(),
            verticalArrangement = Arrangement.spacedBy(BasicSpace.space_18),
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            PkCell(text = "标题组件", modifier = Modifier.clickable {

            }, type = PkTitleType.TitleBold1())
         
            PkCell(text = "单元格组件", modifier = Modifier.clickable {

            }, type = PkTitleType.TitleBold1())
            PkCell(text = "按钮组件", modifier = Modifier.clickable {

            }, type = PkTitleType.TitleBold1())
            PkCell(text = "图片组件", modifier = Modifier.clickable {

            }, type = PkTitleType.TitleBold1())
        }
    }
}

3.2. 标题组件

3.2.1. 介绍

  • 用于快速实现设计规范中的标题和内文样式。通过预定义的 PkTitleType 密封类(包含大标题、标题、小标题、内文等多种样式),开发者可以快速选择字体大小、字重等属性,保证 UI 一致性。
  • 组件支持自定义颜色、对齐方式、溢出处理等常见文本属性,同时保留与原生 Text 组件的兼容性

3.2.2. 参数说明

参数名 参数类型 是否必填 说明
text String 需要显示的文本内容
type PkTitleType 标题类型(默认为 BigTitle1),支持选择预定义的标题样式(如大标题、小标题、内文等)
modifier Modifier 布局修饰符(默认 Modifier),用于调整文本的布局、尺寸、间距等
color Color 文本颜色(默认 0xFF333333
fontStyle FontStyle? 字体风格(如斜体 FontStyle.Italic),默认 null表示不设置
textAlign TextAlign? 文本对齐方式(如居中 TextAlign.Center),默认 null表示继承父布局对齐
overflow TextOverflow 文本溢出处理方式(默认 TextOverflow.Clip),支持 Ellipsis等效果
maxLines Int 文本最大行数(默认无限制 Int.MAX_VALUE
style TextStyle 自定义文本样式(默认 LocalTextStyle.current),可覆盖 type中的部分属性

3.2.3. PkTitleType 类型说明

PkTitleType 是一个密封类,定义了以下预置样式:

类型名称 字体大小 字重 说明
BigTitle1 24.sp W500 大标题1(默认类型)
BigTitle2 22.sp W500 大标题2
BigTitle3 18.sp W500 大标题3
TitleBold1 16.sp W500 标题1(加粗)
TitleNormal1 16.sp W400 标题1(常规)
TitleBold2 15.sp W500 标题2(加粗)
TitleNormal2 15.sp W400 标题2(常规)
SmallTitleBold 14.sp W500 小标题(加粗)
SmallTitleNormal 14.sp W400 小标题(常规)
TextBold1 12.sp W500 内文1(加粗)
TextNormal1 12.sp W400 内文1(常规)
TextBold2 11.sp W500 内文2(加粗)
TextNormal2 11.sp W400 内文2(常规)

3.2.4. 示例代码

scss 复制代码
Column(verticalArrangement = Arrangement.spacedBy(8.dp), horizontalAlignment = Alignment.CenterHorizontally) {
    PkTitle("大标题1", PkTitleType.BigTitle1())
    PkTitle("大标题2", PkTitleType.BigTitle2())
    PkTitle("大标题3", PkTitleType.BigTitle3())
    PkDivider(modifier = Modifier.padding(vertical = 10.dp), isHorizontal = true)
    PkTitle("标题1加粗", PkTitleType.TitleBold1())
    PkTitle("标题1常规", PkTitleType.TitleNormal1())
    PkTitle("标题2加粗", PkTitleType.TitleBold2())
    PkTitle("标题2常规", PkTitleType.TitleNormal2())
    PkDivider(modifier = Modifier.padding(vertical = 10.dp), isHorizontal = true)
    PkTitle("小标题加粗", PkTitleType.SmallTitleBold())
    PkTitle("小标题常规", PkTitleType.SmallTitleNormal())
    PkDivider(modifier = Modifier.padding(vertical = 10.dp), isHorizontal = true)
    PkTitle("内文1加粗", PkTitleType.TextBold1())
    PkTitle("内文1正常", PkTitleType.TextNormal1())
    PkTitle("内文2加粗", PkTitleType.TextBold2())
    PkTitle("内文2正常", PkTitleType.TextNormal2())
}

3.3.1. 介绍

PkNavBar 是一个自定义的 Compose 顶部导航栏组件,适用于需要实现自定义标题栏、返回按钮、右侧操作按钮等功能的场景。

支持沉浸式状态栏背景设置、返回事件处理、右侧图标点击事件处理、标题样式自定义等功能。

3.3.2. 参数

参数名 参数类型 是否必填 说明
title String 导航栏标题文本
backgroundColor Color 背景颜色,默认 #FFFFFEFA
horizontalContentPadding Dp 水平内边距,默认 BasicSpace.space_18
verticalContentPadding Dp 垂直内边距,默认 BasicSpace.space_10
backResource @DrawableRes Int 返回按钮图标资源 ID,默认 R.drawable.compose_icon_retrun
backResourceSize Dp 返回图标尺寸,默认 BasicSize.size_24
showBack Boolean 是否显示返回按钮,默认 true
onBackClick (() -> Unit)? 返回按钮点击事件,默认 null(默认行为为关闭 Activity)
titleFontSize TextUnit 标题文字大小,默认 BasicFont.font_18
titleColor Color 标题文字颜色,默认 #1F401B
isImmersive Boolean 是否沉浸式状态栏(设置状态栏颜色),默认 true
darkIcons Boolean 状态栏图标是否为深色,默认 true
rightResource @DrawableRes Int? 右侧图标资源 ID,可为空表示不显示
onRightClick (() -> Unit)? 右侧图标点击事件,为空则不响应点击

3.3.3. 示例代码

scss 复制代码
Column(verticalArrangement = Arrangement.spacedBy(10.dp)) {
    PkNavBar("默认NavBar导航栏")
    PkNavBar("我是长文本的NavBar导航栏,超长的,但是不显示右边按钮")
    PkNavBar(
        "我是长文本的NavBar导航栏,超长的,显示右边按钮",
        rightResource = R.drawable.ic_menu
    )
    PkNavBar("自定义返回事件", onBackClick = {
        Toast.makeText(context,"自定义返回事件",Toast.LENGTH_LONG).show()
    })
}

3.4. 单元格组件

3.4.1. 介绍

PkCell 是一个通用的列表项/单元格组件,基于 Jetpack Compose 实现。核心功能如下:

  • 左右布局结构:左侧固定显示文本标题,右侧支持灵活组合文本、图标和交互动画或完全自定义内容(图标、开关、文本等)
  • 标题样式继承自 PkTitle 组件,支持预定义的标题类型(PkTitleType
  • 内置点击动画:支持右侧图标的旋转动画(如展开/收起场景)
  • 自动处理文本溢出(默认截断为省略号)
  • 适用于设置项、菜单项、信息展示等需要左右结构的场景

3.4.2. 参数说明------右侧支持灵活组合文本、图标和交互动画

参数名 参数类型 是否必填 默认值 说明
text String 左侧主标题文本内容
type PkTitleType PkTitleType.BigTitle1() 标题样式类型(字体大小、字重),参考 PkTitleType文档
modifier Modifier Modifier 整体容器修饰符(如边距、背景等)
color Color Color(0xFF333333) 左侧标题文本颜色
fontStyle FontStyle? null 字体风格(如斜体 FontStyle.Italic
textAlign TextAlign? null 文本对齐方式(默认跟随系统)
overflow TextOverflow TextOverflow.Ellipsis 文本溢出处理方式
maxLines Int 1 文本最大显示行数
style TextStyle LocalTextStyle.current 自定义文本样式(覆盖 type属性)
rightText String "" 右侧辅助文本内容(空字符串时不显示)
rightTextColor Color Color(0xFF666666) 右侧辅助文本颜色
rightTextSize TextUnit 12.sp 右侧辅助文本字体大小
rightIcon @DrawableRes Int? R.drawable.ic_right_arrow 右侧图标资源 ID(设为 null时不显示图标)
rightIconSize Dp 12.dp 右侧图标尺寸
isRightIconRotated Boolean false 是否启用图标旋转动画(用于展开/收起状态指示)
rightClick (() -> Unit)? null 点击右侧区域回调(触发动画和自定义逻辑)
scss 复制代码
Column(
    Modifier
        .background(Color.White)
        .fillMaxSize()
) {
    PkCell(
        "常用功能",
        PkTitleType.BigTitle3(),
        rightText = "展开",
        modifier = Modifier.padding(horizontal = 18.dp),
        color = Color(0xFF14401B)
    )
}

3.4.3. 参数说明------自定义右边内容

参数名 参数类型 是否必填 默认值 说明
text String 左侧显示的文本内容
type PkTitleType PkTitleType.BigTitle1() 标题样式类型(字体大小、字重等),参考 PkTitleType文档
modifier Modifier Modifier 布局修饰符(如尺寸、边距等),作用于整个单元格容器
color Color Color(0xFF333333) 文本颜色
fontStyle FontStyle? null 字体风格(如斜体 FontStyle.Italic
textAlign TextAlign? null 文本对齐方式(如 TextAlign.End右对齐),默认跟随系统
overflow TextOverflow TextOverflow.Ellipsis 文本溢出处理方式(默认显示省略号)
maxLines Int 1 文本最大显示行数
style TextStyle LocalTextStyle.current 自定义文本样式(可覆盖 type中的部分属性)
rightContent @Composable RowScope.() -> Unit 右侧自定义内容(可放置图标、开关等组件),通过 RowScope支持灵活布局
ini 复制代码
// 基础用法(右侧带箭头图标)
PkCell(
    text = "个人资料",
    type = PkTitleType.TitleBold1(),
    modifier = Modifier.padding(16.dp),
    rightContent = {
        Icon(
            imageVector = Icons.Default.ArrowForward,
            contentDescription = "进入",
            tint = Color.Gray
        )
    }
)

// 复杂右侧内容(文字 + 开关)
PkCell(
    text = "夜间模式",
    color = Color.Black,
    rightContent = {
        Text("已开启", color = Color.Gray)
        Spacer(Modifier.width(8.dp))
        Switch(
            checked = isDarkMode,
            onCheckedChange = { /* 状态更新逻辑 */ }
        )
    }
)

3.5. 按钮组件

3.5.1. 介绍

PkButton 是一个基于 Jetpack Compose 的标准化按钮组件,封装了 Material Design 的 Button 并扩展了预设样式。核心功能如下:

  • 统一设计规范:预定义按钮形状、颜色、内边距等样式,保证应用内按钮一致性
  • 灵活扩展:支持覆盖默认样式(如颜色、阴影、边框)
  • 交互状态集成:自动处理点击、禁用、按压等状态的视觉效果
  • 内容自定义:支持嵌入任意组合的文本、图标或其他组件

3.5.2. 参数

参数名 参数类型 是否必填 默认值 说明
onClick () -> Unit 按钮点击事件回调
modifier Modifier Modifier 布局修饰符(如尺寸、边距、背景等)
enabled Boolean true 是否启用按钮(禁用时自动降低透明度并禁用点击事件)
interactionSource MutableInteractionSource remember { MutableInteractionSource() } 用于自定义按钮交互状态(如按压、悬停效果)
elevation ButtonElevation? ButtonDefaults.elevation() 按钮阴影效果(设为 null可移除阴影)
shape Shape PkTheme.shapes.small 按钮形状(默认使用主题的小圆角,如 RoundedCornerShape(4.dp)
border BorderStroke? null 按钮边框(如 BorderStroke(1.dp, Color.Gray)
colors ButtonColors PkButtonDefault.buttonColors() 按钮颜色配置(含默认、禁用、按压等状态颜色)
contentPadding PaddingValues PkButtonDefault.ContentPadding 内容内边距(默认 PaddingValues(horizontal=16.dp, vertical=8.dp)
content @Composable RowScope.() -> Unit 按钮内容(支持 RowScope布局,如文本+图标组合)

3.5.3. 示例

ini 复制代码
Row(horizontalArrangement = Arrangement.spacedBy(10.dp), modifier = Modifier.padding(top=20.dp, start = 20.dp)) {
    PkButton(
        onClick = {

        }, elevation = null,
        colors = PkButtonDefault.transparentColor(),
        shape = PkTheme.shapes.medium,
        border = BorderStroke(0.5.dp, Color(0xFFD4D4D5))
    ) {
        Text(
            "继续挑战", fontWeight = FontWeight.W500,
            fontSize = BasicFont.font_12
        )
    }
    PkButton(
        onClick = {

        },
        elevation = null,
        colors = PkButtonDefault.buttonColors(),
        shape = PkTheme.shapes.medium,
    ) {
        Text(
            "领取任务", fontWeight = FontWeight.W500,
            fontSize = BasicFont.font_12
        )
    }
}

3.6. 图片组件

3.6.1. 介绍

PkImageView 是一个基于 Jetpack Compose 的定制化图片展示组件,对原生 Image 组件进行了封装,提供更简洁的默认配置和常用功能扩展。核心特性包括:

  • 预设常用参数:默认居中裁剪、支持透明度调整
  • 颜色滤镜 :一键添加统一色调(tintColor
  • 可访问性简化:默认隐藏内容描述(需根据场景手动添加)
  • 无缝兼容 :保留原生 Image 的所有能力,支持深度定制

3.6.2. 参数说明

参数名 参数类型 是否必填 默认值 说明
painter Painter 图片资源(支持 painterResourcerememberAsyncImagePainter等)
modifier Modifier Modifier 布局修饰符(尺寸、边距、背景等)
alignment Alignment Alignment.Center 图片在容器内的对齐方式
contentScale ContentScale ContentScale.Crop 图片缩放模式(如填充 FillBounds、适应 Fit等)
alpha Float DefaultAlpha(1.0F) 透明度(范围 0.0f完全透明 - 1.0f不透明)
tintColor Color? null 颜色滤镜(如 Color.Blue将图片染成蓝色),null表示不应用滤镜

3.6.3. 示例

ini 复制代码
@Composable
fun ImagePage() {
    val imageUrl="https://coil-kt.github.io/coil/images/coil_logo_black.svg"
    Column(verticalArrangement = Arrangement.spacedBy(10.dp)) {
        PkNavBar("图片组件")
        Column {
            PkTitle("加载本地图片", type = PkTitleType.BigTitle3())
            PkImageView(painter = painterResource(R.drawable.portrair), modifier = Modifier.size(80.dp))
        }
        Column {
            PkTitle("加载网络图片", type = PkTitleType.BigTitle3())
            PkImageView(painter =ImagePainterUtils.getPainter(imageUrl), modifier = Modifier.size(80.dp))
        }
        Column {
            PkTitle("加载网络图片,并修改颜色为红色", type = PkTitleType.BigTitle3())
            PkImageView(painter = ImagePainterUtils.getPainter(imageUrl), tintColor = Color.Red,modifier = Modifier.size(80.dp))
        }
    }
}

4. 展示组件

4.1. 网格布局

4.1.1. 介绍

P kGridLayout 是一个基于 Jetpack Compose 实现的网格布局组件,支持动态生成多行多列的布局结构。核心功能包括:

  • 自定义列数与列间距:灵活控制每行列数和列间空白
  • 自适应填充:自动计算行数,不足一行的位置用空白占位
  • 分割线支持:可显示水平分割线,支持自定义分割线样式
  • 高性能渲染:适用于中小规模数据集(非惰性加载,适合固定或少量数据场景)

4.1.2. 参数

参数名 参数类型 是否必填 默认值 说明
columns Int(取值范围 ≥1) 每行显示的列数
data MutableList<E> 数据源列表,泛型 E表示数据项类型
isShowHorizontalDivider Boolean false 是否显示水平分割线(仅在行之间显示)
divider @Composable (() -> Unit)? null 自定义分割线组件,若未提供且 isShowHorizontalDivider=true,则使用默认 Divider
columnSpacing Dp 12.dp 列之间的水平间距
content @Composable (Int, E) -> Unit 定义每个网格项的内容,参数为数据项索引和对应的数据项 E

4.1.3. 示例代码

ini 复制代码
@Composable
fun GridPage() {
    val dataList = mutableListOf("A", "B", "C", "D", "E", "F", "G")

    Column(modifier = Modifier.padding(horizontal = 15.dp)) {
        PkNavBar("网格布局")
        // 基础用法(2列,带列间距和默认分割线)
        PkGridLayout(
            columns = 2,
            data = dataList,
            isShowHorizontalDivider = true,
            columnSpacing = 16.dp,
            divider = {
               PkSpacer(isHorizontal = true)
            }
        ) { index, item ->
            Text(
                text = "$item${index + 1}",
                modifier = Modifier
                    .background(Color.LightGray, RoundedCornerShape(8.dp))
                    .padding(vertical = 8.dp)
                    .fillMaxWidth()

            )
        }
    }
}

4.2. 分割线

4.2.1. PkDivider分割线

4.2.1.1. 介绍
  • 支持设置水平/垂直 虚线或实线分割线
  • PkDashDivider(虚线)和 PkFullDivider(实线)整合类
4.2.1.2. 导入依赖
arduino 复制代码
import com.peakmain.compose.ui.divier.PkDivider
4.2.1.3. 参数
参数名 参数类型 说明
modifier Modifier 用于添加额外修饰符的 Modifier。
color Color 分隔线的颜色,默认为 0xFFF1EFE9。
height Dp 分隔线的高度,仅在垂直分隔线生效,默认为 28.dp。
thickness Dp 分隔线的厚度,仅在非虚线时生效,默认为 1.dp。
startIndent Dp 分隔线的起始缩进,仅在非虚线时生效,默认为 0.dp。
isHorizontal Boolean 是否为水平分隔线,默认为 false。
isDash Boolean 是否绘制虚线分隔线,默认为 false。
strokeWidth Dp 虚线的宽度,仅在绘制虚线时生效,默认为 0.5.dp。
dashLength Dp 虚线的线段长度,仅在绘制虚线时生效,默认为 2.dp。
gapLength Dp 虚线的间隔长度,仅在绘制虚线时生效,默认为 2.dp。
4.2.1.4. 示例代码
scss 复制代码
//默认垂直实线
PkDivider()
//水平实线
PkDivider(modifier = Modifier.padding(top = 10.dp), isHorizontal = true)
//垂直虚线
PkDivider(isDash=true)
//水平虚线
PkDivider(modifier = Modifier.padding(top = 10.dp), isHorizontal = true, isDash = true)

4.2.2. PkFullDivider实线分割线

4.2.2.1. 介绍
  • 创建一个水平/垂直实线分隔线组件
4.2.2.2. 导入依赖
arduino 复制代码
import com.peakmain.compose.ui.divier.PkFullDivider
4.2.2.3. 参数
参数名 参数类型 说明
modifier Modifier 用于添加额外修饰符的 Modifier。
color Color 分隔线的颜色,默认为 0xFFF1EFE9。
height Dp 分隔线的高度,垂直方向生效默认为 28.dp。
thickness Dp 分隔线的厚度,默认为 1.dp。
startIndent Dp 分隔线的起始缩进,默认为 0.dp。
isHorizontal Boolean 水平分割线 (true)/ 垂直分割线 (false),默认是 false
4.2.2.4. 示例代码
ini 复制代码
PkFullDivider(modifier = Modifier.padding(top = 10.dp), isHorizontal = true)

4.2.3. PkDashDivider虚线分割线

4.2.3.1. 介绍
  • 创建一个水平/垂直虚线分隔线组件
4.2.3.2. 导入依赖
arduino 复制代码
import com.peakmain.compose.ui.divier.PkDashDivider
4.2.3.3. 参数
参数名 参数类型 说明
modifier Modifier 用于添加额外修饰符的 Modifier。
color Color 分隔线的颜色,默认为 0xFFF1EFE9。
height Dp 分隔线的高度,垂直方向生效,默认为 28.dp。
strokeWidth Dp 虚线的宽度,默认为 0.5.dp。
dashLength Dp 虚线的长度,默认为 2.dp。
gapLength Dp 虚线之间的间隔长度,默认为 2.dp。
isHorizontal Boolean 水平分割线 (true)/ 垂直分割线 (false),默认是 false
4.2.3.4. 示例代码
ini 复制代码
 PkDashDivider(modifier = Modifier.padding(top = 10.dp), isHorizontal = true)

4.3. 流式布局PkFlowRow

4.3.1. 介绍

PkFlowRow 是一个定制化的流式布局组件,基于 Jetpack Compose 的 FlowRow 扩展而来。核心功能如下:

  • 支持子项水平排列,自动换行
  • 限制最大行数(超出部分自动隐藏)
  • 可自定义子项间水平/垂直间距
  • 自动裁剪超出最大高度的内容(通过 clipToBounds 实现)
  • 适用于标签组、动态分类展示等需要紧凑布局的场景

4.3.2. 参数

参数名 参数类型 是否必填 默认值 说明
modifier Modifier Modifier 布局修饰符(如尺寸、背景等),会与内部修饰符合并
horizontalSpacing Dp 0.dp 子项之间的水平间距
verticalSpacing Dp 0.dp 行之间的垂直间距
maxLine Int(取值范围 ≥1) 2 最大显示行数,超出部分将被隐藏
onLineCountChanged Int null 行数回调
content @Composable () -> Unit 子项内容,支持任意Composable 组件

4.3.3. 示例代码

less 复制代码
@Preview
@Composable
fun PkFlowRowPreview() {
    val tags = listOf("Android", "Kotlin", "Jetpack Compose", "KMP","Material Design", "UI", "Development")

    PkFlowRow(
        horizontalSpacing = 8.dp,
        verticalSpacing = 12.dp,
        maxLine = 1
    ) {
        tags.forEach { tag ->
            Text(
                text = tag,
                modifier = Modifier
                    .background(Color.LightGray, RoundedCornerShape(16.dp))
                    .padding(horizontal = 12.dp, vertical = 8.dp)
            )
        }
    }
}
ini 复制代码
@Composable
fun FlowRowPage() {
    val tags = listOf(
        "Android",
        "Kotlin",
        "Jetpack Compose",
        "KMP",
        "Material Design",
        "UI",
        "Development"
    )
    var currentLine by remember {
        mutableStateOf(0)
    }
    var isExpand by remember {
        mutableStateOf(false)
    }
    Column(modifier = Modifier.fillMaxSize()) {

        Column(modifier = Modifier.padding(top = 40.dp)) {
            if (currentLine > 2) {
                PkCell(
                    "超过2行显示展开/更多",
                    type = PkTitleType.TextBold1(),
                    rightText = if (!isExpand) "展开" else "收起",
                    rightIcon= if (isExpand) R.drawable.ic_expend_arrow_down else R.drawable.ic_expend_arrow_up,
                    rightClick = {
                        isExpand = !isExpand
                    }
                )
            }
            PkFlowRow(
                modifier = Modifier.padding(top = BasicSize.size_12),
                horizontalSpacing = 8.dp,
                verticalSpacing = 12.dp,
                maxLine = if (isExpand) Int.MAX_VALUE else 2,
                onLineCountChanged = {
                    currentLine = it
                }) {
                tags.forEach { tag ->
                    Text(
                        text = tag,
                        modifier = Modifier
                            .background(Color.LightGray, RoundedCornerShape(16.dp))
                            .padding(horizontal = 12.dp, vertical = 8.dp)
                    )
                }
            }
        }
    }
}

4.4. 轮播图

4.4.1. 介绍

PkBanner 是一个基于 Jetpack Compose 的横向轮播图组件,支持自动播放、手动滑动交互和点击事件。核心特性包括:

  • 自适应屏幕宽度,支持居中显示轮播项
  • 自动轮播功能(可配置间隔时间)
  • 自定义轮播项尺寸、间距和内容
  • 触摸交互时暂停自动播放(防止误操作)
  • 支持单页或多页布局模式
  • 支持水平/垂直轮播

4.4.2. 参数

参数名 参数类型 是否必填 默认值 说明
lists ArrayList<T> 轮播数据源(若为空数组,组件不渲染)
pagerWidth Dp 290.dp 单个轮播项的宽度
pagerHeight Dp 116.dp 轮播容器的高度
pageSpacing Dp 12.dp 轮播项之间的水平间距
contentPadding Dp 18.dp 首尾项两侧的边距(用于居中显示)
duration Long 3000 自动轮播间隔时间(单位:毫秒)
isAutoPlay Boolean true 是否启用自动轮播
initialPage Int 0 初始显示的页面索引(从0开始),超出范围时自动修正为有效值0
onBannerClick ((Int, T?) -> Unit)? null 点击轮播项的回调,参数为当前页索引
isVertical boolean false 垂直还是水平轮播,默认是水平
horizontalAlignment Alignment Alignment.Start 横向对齐方式
verticalAlignment Alignment Alignment.CenterVertically 内容的垂直对齐方式
userScrollEnabled Boolean true 是否允许用户手动滑动
forceContentPaddingZero Boolean false 是否强制内容边距为 0 只对水平轮播有作用
content @Composable (Int, T?) -> Unit 定义轮播项内容,参数为当前页索引

4.4.3. 示例代码

scss 复制代码
@Composable
fun BannerPage() {
    val lists = ArrayList<String>().apply {
        add("https://img2.baidu.com/it/u=292395973,2170347184&fm=253&fmt=auto&app=120&f=JPEG?w=1280&h=800")
        add("https://img0.baidu.com/it/u=3492687357,1203050466&fm=253&fmt=auto&app=138&f=JPEG?w=889&h=500")
        add("https://img2.baidu.com/it/u=2843793126,682473204&fm=253&fmt=auto&app=120&f=JPEG?w=1280&h=800")
        add("https://img1.baidu.com/it/u=3907217777,761642486&fm=253&fmt=auto&app=120&f=JPEG?w=1280&h=800")
        add("https://img1.baidu.com/it/u=1082651511,4058105193&fm=253&fmt=auto&app=120&f=JPEG?w=1422&h=800")
    }
    Column(
        modifier = Modifier
            .background(Color.White)
            .fillMaxSize()
    ) {
        PkBanner(
            lists,
            isAutoPlay = true,
            initialPage = 3,
            onBannerClick = {index,item->
                Log.e("TAG", "获取到点击后的数据:${item}")
            }) {index,item->
            Image(
                painter = ImagePainterUtils.getPainter(item),
                contentDescription = null,
                modifier = Modifier
                    .clip(RoundedCornerShape(8.dp))
                    .fillMaxSize(),
                contentScale = ContentScale.Crop,
                alignment = Alignment.TopCenter
            )
        }
    }
}

垂直轮播

ini 复制代码
@Composable
fun BannerPage() {
    val vLists = arrayListOf("广告", "我是垂直轮播", "生活好滋味,就要上四休三")
    val itemWidth = (LocalConfiguration.current.screenWidthDp.dp)
    PkBanner(
        vLists,
        isAutoPlay = true,
        isVertical = true,
        pagerHeight = 88.dp,
        pagerWidth = itemWidth
    ) { index, item ->
        Box() {
            Column(
                modifier = Modifier
                    .clip(RoundedCornerShape(BasicRadius.radius_8))
                    .background(PkColor.color_fill2)
                    .padding(bottom = BasicSpace.space_16)
                    .fillMaxSize(),
            ) {
                Box() {
                    Column {
                        Row(
                            modifier = Modifier
                                .padding(
                                    top = BasicSpace.space_16,
                                    start = BasicSpace.space_12,
                                    end = BasicSpace.space_12
                                ),
                        ) {
                            // 左侧 圆形背景 + 图标
                            Box(
                                modifier = Modifier
                                    .size(BasicSize.size_40)
                                    .clip(CircleShape)
                                    .background(PkColor.color_fill1),
                                contentAlignment = Alignment.Center
                            ) {
                                PkImageView(
                                    painter = painterResource(
                                        id = R.drawable.ic_online_check_out_disable
                                    ),
                                    modifier = Modifier.size(BasicSize.size_24),
                                )
                            }

                            Spacer(modifier = Modifier.width(BasicSpace.space_8))

                            // 中间 内容
                            Column(
                                modifier = Modifier.weight(1f)
                            ) {
                                Text(
                                    text = "已入住",
                                    color = PkColor.color_text1,
                                    fontSize = BasicFont.font_14,
                                )
                                Spacer(modifier = Modifier.height(BasicSize.size_2))
                                Text(
                                    text = "2025年06月27日" + "  |  " + "金会员",
                                    color = PkColor.color_text2,
                                    fontSize = BasicFont.font_11,
                                    maxLines = 1,
                                    overflow = TextOverflow.Ellipsis
                                )
                            }

                        }
                        // 底部进度条
                        RoundedLinearProgressIndicator(
                            progress = 0.5f,
                            modifier = Modifier
                                .padding(top = BasicSize.size_12)
                                .fillMaxWidth()
                                .height(BasicSize.size_4)
                                .padding(horizontal = BasicSpace.space_16),
                            color = PkColor.color_brand1,
                            cornerRadius = BasicRadius.radius_2
                        )
                        PkSpacer(height = BasicSize.size_16)
                    }
                    //洗衣取送
                    Box(
                        contentAlignment = Alignment.Center,
                        modifier = Modifier
                            .padding(end = BasicSpace.space_8)
                            .align(Alignment.TopEnd)
                    ) {
                        Image(
                            painter = painterResource(id = R.drawable.background_laundry_delivery),
                            contentDescription = null,
                            contentScale = ContentScale.FillBounds,
                            modifier = Modifier
                                .wrapContentWidth()
                                .wrapContentHeight()
                        )
                        androidx.compose.material3.Text(
                            text = "垂直轮播",
                            color = PkColor.color_text5,
                            fontSize = BasicFont.font_11,
                            modifier = Modifier
                                .padding(
                                    horizontal = BasicSpace.space_7,
                                    vertical = BasicSpace.space_4
                                )
                        )


                    }

                }
            }
        }
    }
}

4.5. 高亮文本

4.5.1. 介绍

PkHighlightText 是一个基于 Jetpack Compose 的文本高亮组件,支持在长文本中多关键字高亮显示,特性如下:

  • 智能匹配:支持不区分大小写、自动合并重叠高亮区间
  • 安全转义 :自动处理正则表达式特殊字符(如 $ , * , + 等)
  • 灵活样式:可自定义高亮颜色,继承外部文本样式(字体大小、字重等)
  • 鲁棒性:空关键字/非法正则表达式自动降级为普通文本
  • 重叠区间 :自动合并(如 0..53..80..8

4.5.2. 参数说明

参数名 参数类型 是否必填 默认值 说明
text String 需要处理的原始文本
keywords List<String> 高亮关键字列表(空列表时不进行高亮)
highlightColor Color Color.Red 高亮文本颜色
style TextStyle LocalTextStyle.current 基础文本样式(如字体大小、字重),高亮部分继承此样式并叠加颜色

4.5.3. 示例

ini 复制代码
// 示例1:基本用法(多个关键字)
PkHighlightText(
    text = "Jetpack Compose 是 Android 的现代 UI 工具包",
    keywords = listOf("compose", "android"),
    highlightColor = Color.Blue,
    style = MaterialTheme.typography.body1
)

// 示例2:含特殊字符的关键字
PkHighlightText(
    text = "价格:$199 (限时优惠)",
    keywords = listOf("$199", "(限时优惠)"), 
    highlightColor = Color(0xFF4CAF50)
)

// 示例3:无关键字/空列表
PkHighlightText(
    text = "Hello World",
    keywords = emptyList() // 显示普通文本
)

4.6. 瀑布流

4.6.1. 介绍

PkStaggeredVerticalGrid 是一个基于 Jetpack Compose 的瀑布流布局组件,专为呈现高度不规则的网格内容设计(如图片墙、卡片集合)。通过智能分配元素到最短列,实现自然错落的视觉效果,同时保证高效的空间利用率。

4.6.2. 参数

参数名 参数类型 是否必填 默认值 说明
columns Int 网格列数(必须 ≥1)
modifier Modifier Modifier 容器修饰符(背景、尺寸、滚动等)
contentPadding PaddingValues 0.dp 内容区域的内边距(支持独立设置各方向)
verticalItemSpacing Dp 8.dp 垂直方向(行间)间距
horizontalItemSpacing Dp 8.dp 水平方向(列间)间距
content @Composable () -> Unit 网格项内容(任意 Composable 组件)

4.6.3. 示例

ini 复制代码
@Composable
fun StaggeredVerticalGridPage() {
    // 生成示例数据(包含随机高度)
    val items = List(15) { index ->
        StaggeredItem(
            id = index, height = (20 + Random.nextInt(50)).dp, // 随机高度 (120-270dp)
            title = "Item ${index + 1}"
        )
    }
    Column {
        PkStaggeredVerticalGrid(
            columns = 2,
            contentPadding = PaddingValues(16.dp),
            verticalItemSpacing = 4.dp,
            horizontalItemSpacing = 16.dp, // 水平间距
            modifier = Modifier.wrapContentHeight()

        ) {
            items.forEach { item ->
                Box(
                    modifier = Modifier
                        .fillMaxWidth()
                        .background(
                            Color(
                                red = Random.nextInt(256),
                                green = Random.nextInt(256),
                                blue = Random.nextInt(256),
                                alpha = 255
                            )
                        ),
                ) {
                    Box(
                        modifier = Modifier
                            .fillMaxSize(), contentAlignment = Alignment.Center
                    ) {
                        Text(
                            text = item.title,
                            color = Color.White,
                            modifier = Modifier.padding(8.dp)
                        )
                    }
                }
            }
        }
    }
}

5. 工具类

5.1. ImagePainterUtils工具类

5.1.1. 介绍

  • 根据图片 URL 获取 AsyncImagePainter 对象

5.1.2. 导入依赖

arduino 复制代码
import com.peakmain.compose.utils.ImagePainterUtils

5.1.3. 参数

参数名 参数类型 说明
imageUrl String 图片的 URL,如果为空则显示占位图。
errorDrawableResId Int 图片加载失败时显示的 Drawable 资源 ID,默认为 R.drawable.icon_loading。
placeDrawableResId Int 图片加载过程中显示的占位图 Drawable 资源 ID,默认为 R.drawable.icon_loading。

5.1.4. 示例代码

ini 复制代码
Image(
    painter = ImagePainterUtils.getPainter(it.imageUrl),
    contentDescription = null,
    modifier = Modifier
        .clip(RoundedCornerShape(8.dp))
        .weight(1f)
        .height(75.dp),
    contentScale = ContentScale.Crop
)

6. 扩展类

6.1. List扩展类

6.1.1. 介绍

可空List的扩展类,作用如下

  • 可空List的大小
  • 可空List的大小是否大于0
  • 可空List大小是否为0
  • 截取 List 的子区间 [fromIndex, toIndex),返回子列表

6.1.2. 导入依赖

arduino 复制代码
import com.peakmain.compose.ext.orSize

6.1.3. 方法

方法名 返回值 参数 说明
orSize Int 获取 List 的大小。若 List 为 null,则返回 0;若 List 不为 null,则返回其 size。
sizeBigZero Boolean 判断 List 大小是否大于 0。若 List 为 null,则返回 false;若 List 不为 null,则判断其大小是否大于 0。
sizeEqualZero Boolean 判断 List 的大小是否为 0。若 List 为 null,则返回 true;若 List 不为 null,则判断其大小是否等于 0。
slice List ①、fromIndex:起始索引(包含),需满足 fromIndex >= 0 ②、toIndex结束索引(不包含),需满足 toIndex <= sizetoIndex >= fromIndex 此函数用于获取当前列表(可能为 null )在指定索引范围 [fromIndex, toIndex) 内的子列表视图。若原列表为 null、范围无效或超出实际大小,则直接返回原列表

6.1.4. 示例代码

kotlin 复制代码
@Composable
fun ListExtPage() {
    val list1: List<String>? = null
    val list2 = arrayListOf("list1", "list2", "list3", "list4")
    CpColumn("List扩展类") {
        CpTitle("空数组list1的大小:${list1.orSize()}")
        CpTitle("空数组list1的大小是否等于0:${list1.sizeBigZero()}")
        CpTitle("空数组list1的大小是否大于0:${list1.sizeBigZero()}")
        CpTitle("定索引范围 [fromIndex, toIndex) 内的子列表视图")
        var result: String = "结果是:"
        list2.slice(1, 3)?.forEach {
            result +="$it,"
        }
        Text(result, fontSize = BasicFont.font_10, color = PkColor.color_text1, modifier = Modifier.padding(horizontal = 18.dp))

    }
}

6.2. String扩展类

6.2.1. 介绍

这组扩展函数为 String? 类型提供了增强的空安全操作,支持链式调用与条件执行逻辑

6.2.2. 导入依赖

arduino 复制代码
import com.peakmain.compose.ext.*

6.2.3. 方法

函数签名 功能描述 返回值规则
fun String?.isEmpty(): Boolean 检查字符串是否为 null或空字符串("" true表示空或 null
fun String?.isEmpty(block: () -> Unit): String? 若字符串为空或 null,执行 block逻辑,保持链式调用 返回原字符串(this
fun String?.isNotEmpty(): Boolean 检查字符串非空且非 null true表示有内容
fun String?.isNotEmpty(block: (String) -> Unit): String? 若字符串非空且非 null,执行 block并将非空字符串传入,保持链式调用

6.2.4. 与 Kotlin 标准库对比

场景 本扩展函数 Kotlin 标准库
空检查 text.isEmpty() text.isNullOrEmpty()
非空检查 text.isNotEmpty() text.isNullOrEmpty().not()
带逻辑的空检查 text.isEmpty { ... } text?.takeIf { it.isEmpty() }?.also { ... }
带逻辑的非空检查 text.isNotEmpty { ... } text?.let { ... }

6.2.5. 示例代码

6.2.5.1. 优化前后场景
  • 以前代码逻辑
vbscript 复制代码
if (userInfo != null && !TextUtils.isEmpty(userInfo.nickName)) 
     userInfo.nickName 
else 
     "登录/注册",
  • 优化后代码
arduino 复制代码
if (userInfo?.nickName.isNotEmpty()) 
    userInfo!!.nickName 
else 
    "登录/注册",

或者

ini 复制代码
text= userInfo?.nickName.isNotEmpty {it}?: "登录/注册",
6.2.5.2. 其他场景示例:
scss 复制代码
// 场景:仅在非空时打印内容并转为大写
val result = nullableString
    .isNotEmpty { 
        println("Processing: $it")
        it.uppercase()
    }.isEmpty{
        
    }

// 场景:空值时显示默认文本
nullableString
    .isEmpty { showError("内容不能为空!") }
    ?.let { updateUI(it) }
相关推荐
studyForMokey2 小时前
【Android面试】Glide专题
android·面试·glide
m0_738120722 小时前
渗透知识ctfshow——Web应用安全与防护(三)
android·前端·安全
y = xⁿ2 小时前
【保姆级 :图解MySQL 执行全链路讲解】主键索引扫描,全局扫描,索引下推还是分不清楚?这一篇就够啦
android·mysql
薿夜10 小时前
SpringSecurity(三)
android
zh_xuan16 小时前
Android Hilt实现依赖注入
android·hilt
freshman_y16 小时前
Qtcreator怎么新建安卓项目?编写一个五子棋游戏APP?
android·qt
时寒的笔记17 小时前
js逆向7_案例惠nong网
android·开发语言·javascript
肯多洛夫斯基18 小时前
安卓工控屏静默连WiFi全攻略
android
极梦网络无忧18 小时前
Android无障碍服务实现抖音直播间界面监控(场控助手核心原理)
android