├── .gitignore ├── .idea ├── .gitignore ├── .name ├── compiler.xml ├── gradle.xml ├── inspectionProfiles │ └── Project_Default.xml ├── misc.xml └── vcs.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── peakmain │ │ └── compose │ │ └── project │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── peakmain │ │ │ └── compose │ │ │ └── project │ │ │ ├── MainActivity.kt │ │ │ ├── bean │ │ │ ├── home │ │ │ │ └── BannerBean.kt │ │ │ ├── main │ │ │ │ └── MainBean.kt │ │ │ └── mine │ │ │ │ └── MineItemBean.kt │ │ │ ├── component │ │ │ ├── CpCell.kt │ │ │ ├── CpColumn.kt │ │ │ └── CpTitle.kt │ │ │ ├── constants │ │ │ └── PkColor.kt │ │ │ ├── page │ │ │ ├── basic │ │ │ │ ├── BasicComponentActivity.kt │ │ │ │ └── compose │ │ │ │ │ ├── ButtonPage.kt │ │ │ │ │ ├── CellPage.kt │ │ │ │ │ ├── ImagePage.kt │ │ │ │ │ ├── NavBarPage.kt │ │ │ │ │ └── TitlePage.kt │ │ │ ├── display │ │ │ │ ├── DisplayComponentActivity.kt │ │ │ │ └── compose │ │ │ │ │ ├── BannerPage.kt │ │ │ │ │ ├── DividerPage.kt │ │ │ │ │ ├── FlowRowPage.kt │ │ │ │ │ ├── GridPage.kt │ │ │ │ │ ├── HighlightTextPage.kt │ │ │ │ │ └── StaggeredVerticalGridPage.kt │ │ │ ├── expand │ │ │ │ ├── ExpandActivity.kt │ │ │ │ └── component │ │ │ │ │ └── ListExtPage.kt │ │ │ └── tools │ │ │ │ ├── ToolsActivity.kt │ │ │ │ └── component │ │ │ │ └── ImagePainterUtilsPage.kt │ │ │ ├── ui │ │ │ ├── theme │ │ │ │ ├── Color.kt │ │ │ │ ├── Shape.kt │ │ │ │ ├── Theme.kt │ │ │ │ └── Type.kt │ │ │ └── view │ │ │ │ ├── MainFrame.kt │ │ │ │ └── main │ │ │ │ ├── BasicFragment.kt │ │ │ │ ├── DisplayFragment.kt │ │ │ │ ├── ExpandFragment.kt │ │ │ │ └── ToolsFragment.kt │ │ │ └── viewmodel │ │ │ ├── home │ │ │ └── HomeFragmentViewModel.kt │ │ │ └── mine │ │ │ └── MineFragmentViewModel.kt │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ ├── background_laundry_delivery.xml │ │ ├── ic_expend_arrow_down.xml │ │ ├── ic_expend_arrow_up.xml │ │ ├── ic_launcher_background.xml │ │ ├── ic_menu.xml │ │ ├── ic_online_check_out_disable.xml │ │ └── portrair.JPG │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── themes.xml │ └── test │ └── java │ └── com │ └── peakmain │ └── compose │ └── project │ └── ExampleUnitTest.kt ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── library ├── .gitignore ├── build.gradle ├── consumer-rules.pro ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── peakmain │ │ └── compose │ │ └── library │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── peakmain │ │ │ └── compose │ │ │ ├── basic │ │ │ ├── BasicColor.kt │ │ │ ├── BasicFont.kt │ │ │ ├── BasicRadius.kt │ │ │ ├── BasicSize.kt │ │ │ └── BasicSpace.kt │ │ │ ├── ext │ │ │ ├── IntExt.kt │ │ │ ├── ListExt.kt │ │ │ └── StringExt.kt │ │ │ ├── library │ │ │ └── TopAppBar.kt │ │ │ ├── space │ │ │ └── PkSpacer.kt │ │ │ ├── theme │ │ │ ├── PkColors.kt │ │ │ ├── PkIndication.kt │ │ │ ├── PkTheme.kt │ │ │ └── PkTranslateIndication.kt │ │ │ ├── ui │ │ │ ├── PkGridLayout.kt │ │ │ ├── banner │ │ │ │ └── PkBanner.kt │ │ │ ├── basic │ │ │ │ └── PkColumn.kt │ │ │ ├── button │ │ │ │ ├── PkButton.kt │ │ │ │ ├── PkButtonDefault.kt │ │ │ │ └── PkShapes.kt │ │ │ ├── cell │ │ │ │ └── PkCell.kt │ │ │ ├── divier │ │ │ │ ├── PkDashDivider.kt │ │ │ │ ├── PkDivider.kt │ │ │ │ └── PkFullDivider.kt │ │ │ ├── flow │ │ │ │ └── PkFlowRow.kt │ │ │ ├── grid │ │ │ │ └── PkStaggeredVerticalGrid.kt │ │ │ ├── image │ │ │ │ └── PkImageView.kt │ │ │ ├── progress │ │ │ │ └── RoundedLinearProgressIndicator.kt │ │ │ ├── text │ │ │ │ └── PkHighlightText.kt │ │ │ └── title │ │ │ │ ├── PkNavBar.kt │ │ │ │ └── PkTitle.kt │ │ │ └── utils │ │ │ └── ImagePainterUtils.kt │ └── res │ │ └── drawable │ │ ├── compose_icon_retrun.xml │ │ ├── ic_right_arrow.xml │ │ └── icon_loading.xml │ └── test │ └── java │ └── com │ └── peakmain │ └── compose │ └── library │ └── ExampleUnitTest.kt └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | local.properties 16 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | ComposeUI -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 20 | 21 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 128 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 26 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # composeProject 2 | 3 | > **常用Compose UI封装——提高Android Compose UI开发** 4 | 5 | **使用文档链接:** https://www.yuque.com/peakmain/alaof0/fis43sflpl602m18 6 | 7 | **How To** 8 | 9 | - Step 1. Add the JitPack repository to your build file 10 | - gradle 11 | 12 | ```groovy 13 | dependencyResolutionManagement { 14 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 15 | repositories { 16 | mavenCentral() 17 | maven { url 'https://jitpack.io' } 18 | } 19 | } 20 | ``` 21 | - gradle.kts 22 | ```kotlin 23 | dependencyResolutionManagement { 24 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 25 | repositories { 26 | mavenCentral() 27 | maven { url = uri("https://jitpack.io") } 28 | } 29 | } 30 | ``` 31 | - Step 2. Add the dependency 32 | ```groovy 33 | dependencies { 34 | implementation("com.github.Peakmain:ComposeUI:+") 35 | } 36 | ``` 37 | #### 关于我 38 | 39 | - 简书: https://www.jianshu.com/u/3ff32f5aea98 40 | - 我的GitHub地址:https://github.com/Peakmain 41 | 42 | #### Donations 43 | 44 | 如果您觉得我的开源库帮您节省了大量的开发时间,请扫描下方的二维码随意打赏,您的支持将激励我不断前进 45 | ![微信](https://user-images.githubusercontent.com/26482737/184805287-0561a7e2-da13-4ef4-b367-c5e8672c121d.jpg) 46 | ![支付宝](https://user-images.githubusercontent.com/26482737/184805306-f44511a7-7660-4fe1-9f07-305005576c2c.jpg) 47 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.application' 3 | id 'kotlin-android' 4 | } 5 | 6 | android { 7 | compileSdk 34 8 | 9 | defaultConfig { 10 | applicationId "com.peakmain.compose.project" 11 | minSdk 21 12 | targetSdk 31 13 | versionCode 1 14 | versionName "1.0" 15 | 16 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 17 | vectorDrawables { 18 | useSupportLibrary true 19 | } 20 | } 21 | 22 | buildTypes { 23 | release { 24 | minifyEnabled false 25 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 26 | } 27 | } 28 | compileOptions { 29 | sourceCompatibility JavaVersion.VERSION_1_8 30 | targetCompatibility JavaVersion.VERSION_1_8 31 | } 32 | kotlinOptions { 33 | jvmTarget = '1.8' 34 | } 35 | buildFeatures { 36 | compose true 37 | } 38 | composeOptions { 39 | kotlinCompilerExtensionVersion = "1.5.4" 40 | } 41 | packagingOptions { 42 | resources { 43 | excludes += '/META-INF/{AL2.0,LGPL2.1}' 44 | } 45 | } 46 | namespace 'com.peakmain.compose.project' 47 | } 48 | 49 | dependencies { 50 | implementation project(path: ':library') 51 | implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" 52 | implementation 'androidx.activity:activity-ktx:1.0.0' 53 | implementation 'androidx.activity:activity-compose:1.0.0' 54 | 55 | def lifecycle_version = "2.4.1" 56 | 57 | implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version" 58 | implementation "androidx.lifecycle:lifecycle-viewmodel-compose:$lifecycle_version" 59 | 60 | 61 | testImplementation 'junit:junit:4.13.2' 62 | androidTestImplementation 'androidx.test.ext:junit:1.1.2' 63 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' 64 | } -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /app/src/androidTest/java/com/peakmain/compose/project/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.project 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 22 | assertEquals("com.peakmain.compose.project", appContext.packageName) 23 | } 24 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 15 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/peakmain/compose/project/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.project 2 | 3 | import android.os.Bundle 4 | import androidx.activity.ComponentActivity 5 | import androidx.activity.compose.setContent 6 | import androidx.compose.foundation.layout.BoxWithConstraints 7 | import androidx.compose.material.Divider 8 | import androidx.compose.material.MaterialTheme 9 | import androidx.compose.material.Surface 10 | import androidx.compose.material.Text 11 | import androidx.compose.runtime.Composable 12 | import androidx.compose.ui.tooling.preview.Preview 13 | import androidx.core.view.WindowCompat 14 | import com.peakmain.compose.project.ui.theme.ComposeProjectTheme 15 | import com.peakmain.compose.project.ui.view.MainFrame 16 | 17 | class MainActivity : ComponentActivity() { 18 | override fun onCreate(savedInstanceState: Bundle?) { 19 | super.onCreate(savedInstanceState) 20 | //设置沉浸式状态栏 21 | WindowCompat.setDecorFitsSystemWindows(window, false) 22 | setContent { 23 | ComposeProjectTheme { 24 | // A surface container using the 'background' color from the theme 25 | Surface(color = MaterialTheme.colors.background) { 26 | MainFrame() 27 | } 28 | } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /app/src/main/java/com/peakmain/compose/project/bean/home/BannerBean.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.project.bean.home 2 | 3 | /** 4 | * author :Peakmain 5 | * createTime:2022/5/5 6 | * mail:2726449200@qq.com 7 | * describe:轮播图 8 | */ 9 | data class BannerBean(val imagePath:String,val desc:String) 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/java/com/peakmain/compose/project/bean/main/MainBean.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.project.bean.main 2 | 3 | import androidx.compose.ui.graphics.vector.ImageVector 4 | 5 | /** 6 | * author :Peakmain 7 | * createTime:2022/5/2 8 | * mail:2726449200@qq.com 9 | * describe: 10 | */ 11 | data class NavigationItem(val title:String,val icon:ImageVector) -------------------------------------------------------------------------------- /app/src/main/java/com/peakmain/compose/project/bean/mine/MineItemBean.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.project.bean.mine 2 | 3 | import androidx.compose.ui.graphics.vector.ImageVector 4 | 5 | /** 6 | * author :Peakmain 7 | * createTime:2022/5/7 8 | * mail:2726449200@qq.com 9 | * describe: 10 | */ 11 | data class MineItemBean(val title: String, val icon: ImageVector) -------------------------------------------------------------------------------- /app/src/main/java/com/peakmain/compose/project/component/CpCell.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.project.component 2 | 3 | import android.content.Context 4 | import android.content.Intent 5 | import androidx.compose.foundation.clickable 6 | import androidx.compose.runtime.Composable 7 | import androidx.compose.ui.Modifier 8 | import androidx.compose.ui.platform.LocalContext 9 | import com.peakmain.compose.project.page.display.DisplayComponentActivity 10 | import com.peakmain.compose.ui.cell.PkCell 11 | import com.peakmain.compose.ui.title.PkTitleType 12 | 13 | /** 14 | * author :Peakmain 15 | * createTime:2025/6/27 16 | * mail:2726449200@qq.com 17 | * describe: 18 | */ 19 | @Composable 20 | fun CpCell(title:String,intent:Intent,type:Int) { 21 | val context = LocalContext.current 22 | PkCell(text = title, modifier = Modifier.clickable { 23 | intent.putExtra("type",type) 24 | context.startActivity(intent) 25 | }, type = PkTitleType.TitleBold1()) 26 | } -------------------------------------------------------------------------------- /app/src/main/java/com/peakmain/compose/project/component/CpColumn.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.project.component 2 | 3 | import androidx.compose.foundation.background 4 | import androidx.compose.foundation.layout.Column 5 | import androidx.compose.foundation.layout.ColumnScope 6 | import androidx.compose.foundation.layout.fillMaxSize 7 | import androidx.compose.runtime.Composable 8 | import androidx.compose.ui.Modifier 9 | import com.peakmain.compose.project.constants.PkColor 10 | import com.peakmain.compose.ui.title.PkNavBar 11 | 12 | /** 13 | * author :Peakmain 14 | * createTime:2025/6/27 15 | * mail:2726449200@qq.com 16 | * describe: 17 | */ 18 | @Composable 19 | fun CpColumn(title:String, content: @Composable ColumnScope.() -> Unit) { 20 | Column( 21 | modifier = Modifier 22 | .background(PkColor.color_fill1) 23 | .fillMaxSize() 24 | ) { 25 | PkNavBar(title) 26 | content() 27 | } 28 | } -------------------------------------------------------------------------------- /app/src/main/java/com/peakmain/compose/project/component/CpTitle.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.project.component 2 | 3 | import androidx.compose.foundation.layout.padding 4 | import androidx.compose.runtime.Composable 5 | import androidx.compose.ui.Modifier 6 | import androidx.compose.ui.unit.dp 7 | import com.peakmain.compose.ui.title.PkTitle 8 | import com.peakmain.compose.ui.title.PkTitleType 9 | 10 | /** 11 | * author :Peakmain 12 | * createTime:2025/6/27 13 | * mail:2726449200@qq.com 14 | * describe: 15 | */ 16 | @Composable 17 | fun CpTitle(title:String) { 18 | PkTitle(title, type = PkTitleType.TextBold1(), modifier = Modifier.padding(18.dp)) 19 | } -------------------------------------------------------------------------------- /app/src/main/java/com/peakmain/compose/project/constants/PkColor.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.project.constants 2 | 3 | import com.peakmain.compose.basic.BasicColor 4 | 5 | /** 6 | * author :Peakmain 7 | * createTime:2025/6/26 8 | * mail:2726449200@qq.com 9 | * describe: 10 | */ 11 | object PkColor { 12 | /** 13 | * 主色 14 | */ 15 | val green1 = BasicColor.color_1F401B 16 | val green2 = BasicColor.color_677C64 17 | val green3_15 = BasicColor.color_1F401B_15 18 | 19 | /** 20 | * 辅色 21 | */ 22 | val brown1 = BasicColor.color_B59E6D 23 | val brown2 = BasicColor.color_DDCC9E 24 | 25 | /** 26 | * 中性色 27 | */ 28 | val grey1 = BasicColor.color_333333 29 | val grey2 = BasicColor.color_666666 30 | val grey3 = BasicColor.color_9D9C96 31 | val grey4 = BasicColor.color_D4D4D5 32 | val grey5 = BasicColor.color_EBEBF0 33 | val grey6_10 = BasicColor.color_9D9C96_10 34 | val grey7 = BasicColor.color_F8F9F3 35 | val grey8 = BasicColor.color_FFFEFA 36 | 37 | /** 38 | * 功能色 39 | */ 40 | val orange1=BasicColor.color_B9824C 41 | val red1=BasicColor.color_A5534D 42 | val color_67696a=BasicColor.color_67696a 43 | 44 | /** 45 | * 品牌色 46 | */ 47 | val color_brand1=BasicColor.color_1F401B 48 | val color_brand2=BasicColor.color_677C64 49 | val color_brand3=BasicColor.color_B59E6D 50 | val color_brand4=BasicColor.color_DDCC9E 51 | val color_fill1=BasicColor.color_F8F9F3 52 | val color_fill2=BasicColor.color_FFFEFA 53 | val color_fill3_10=BasicColor.color_9D9C96_10 54 | val color_fill4_15=BasicColor.color_1F401B_15 55 | 56 | 57 | /** 58 | * 文本色 59 | */ 60 | val color_text1=BasicColor.color_333333 61 | val color_text2=BasicColor.color_666666 62 | val color_text3=BasicColor.color_9D9C96 63 | val color_text4=BasicColor.color_D4D4D5 64 | val color_text5=BasicColor.color_FFFEFA 65 | val color_text6=BasicColor.color_1F401B 66 | val color_text7=BasicColor.color_126E82 67 | val color_272A2B=BasicColor.color_272A2B 68 | val color_line1=BasicColor.color_D4D4D5 69 | val color_line2=BasicColor.color_EBEBF0 70 | 71 | val color_price1=BasicColor.color_B9824C 72 | 73 | 74 | /** 75 | * 背景色 76 | */ 77 | val color_background1=BasicColor.color_ECECE0B3 78 | val color_background2=BasicColor.color_FFF3F3F3 79 | val color_background3=BasicColor.color_FF000000 80 | 81 | val color_notice1=BasicColor.color_A5534D 82 | val color_launch=BasicColor.color_F2F3EC 83 | } -------------------------------------------------------------------------------- /app/src/main/java/com/peakmain/compose/project/page/basic/BasicComponentActivity.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.project.page.basic 2 | 3 | import android.os.Bundle 4 | import androidx.activity.ComponentActivity 5 | import androidx.activity.compose.setContent 6 | import com.peakmain.compose.project.page.basic.compose.ButtonPage 7 | import com.peakmain.compose.project.page.basic.compose.CellPage 8 | import com.peakmain.compose.project.page.basic.compose.ImagePage 9 | import com.peakmain.compose.project.page.basic.compose.NavBarPage 10 | import com.peakmain.compose.project.page.basic.compose.TitlePage 11 | 12 | /** 13 | * author :Peakmain 14 | * createTime:2025/6/26 15 | * mail:2726449200@qq.com 16 | * describe:基础组件 17 | */ 18 | class BasicComponentActivity : ComponentActivity() { 19 | val type by lazy { 20 | intent.getIntExtra("type", 0) 21 | } 22 | 23 | override fun onCreate(savedInstanceState: Bundle?) { 24 | super.onCreate(savedInstanceState) 25 | setContent { 26 | when (type) { 27 | 1 -> { 28 | //标题组件 29 | TitlePage() 30 | } 31 | 32 | 2 -> { 33 | //导航栏组件 34 | NavBarPage() 35 | } 36 | 37 | 3 -> { 38 | //单元格组件 39 | CellPage() 40 | } 41 | 42 | 4 -> { 43 | //按钮组件 44 | ButtonPage() 45 | } 46 | 47 | 5 -> { 48 | //图片组件 49 | ImagePage() 50 | } 51 | } 52 | } 53 | } 54 | 55 | 56 | } 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /app/src/main/java/com/peakmain/compose/project/page/basic/compose/ButtonPage.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.project.page.basic.compose 2 | 3 | import androidx.compose.foundation.BorderStroke 4 | import androidx.compose.foundation.layout.Arrangement 5 | import androidx.compose.foundation.layout.Column 6 | import androidx.compose.foundation.layout.Row 7 | import androidx.compose.foundation.layout.padding 8 | import androidx.compose.material.Text 9 | import androidx.compose.runtime.Composable 10 | import androidx.compose.ui.Modifier 11 | import androidx.compose.ui.graphics.Color 12 | import androidx.compose.ui.text.font.FontWeight 13 | import androidx.compose.ui.unit.dp 14 | import com.peakmain.compose.basic.BasicFont 15 | import com.peakmain.compose.theme.PkTheme 16 | import com.peakmain.compose.ui.button.PkButton 17 | import com.peakmain.compose.ui.button.PkButtonDefault 18 | import com.peakmain.compose.ui.title.PkNavBar 19 | 20 | /** 21 | * author :Peakmain 22 | * createTime:2025/6/26 23 | * mail:2726449200@qq.com 24 | * describe: 25 | */ 26 | /** 27 | * 按钮组件 28 | */ 29 | @Composable 30 | fun ButtonPage() { 31 | Column { 32 | PkNavBar("按钮组件") 33 | Row( 34 | horizontalArrangement = Arrangement.spacedBy(10.dp), 35 | modifier = Modifier.padding(top = 20.dp, start = 20.dp) 36 | ) { 37 | PkButton( 38 | onClick = { 39 | 40 | }, elevation = null, 41 | colors = PkButtonDefault.transparentColor(), 42 | shape = PkTheme.shapes.medium, 43 | border = BorderStroke(0.5.dp, Color(0xFFD4D4D5)) 44 | ) { 45 | Text( 46 | "继续挑战", fontWeight = FontWeight.W500, 47 | fontSize = BasicFont.font_12 48 | ) 49 | } 50 | PkButton( 51 | onClick = { 52 | 53 | }, 54 | elevation = null, 55 | colors = PkButtonDefault.buttonColors(), 56 | shape = PkTheme.shapes.medium, 57 | ) { 58 | Text( 59 | "领取任务", fontWeight = FontWeight.W500, 60 | fontSize = BasicFont.font_12 61 | ) 62 | } 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /app/src/main/java/com/peakmain/compose/project/page/basic/compose/CellPage.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.project.page.basic.compose 2 | 3 | import androidx.compose.foundation.background 4 | import androidx.compose.foundation.layout.Arrangement 5 | import androidx.compose.foundation.layout.Column 6 | import androidx.compose.foundation.layout.Spacer 7 | import androidx.compose.foundation.layout.padding 8 | import androidx.compose.foundation.layout.width 9 | import androidx.compose.material.Icon 10 | import androidx.compose.material.Switch 11 | import androidx.compose.material.Text 12 | import androidx.compose.material.icons.Icons 13 | import androidx.compose.material.icons.filled.ArrowForward 14 | import androidx.compose.runtime.Composable 15 | import androidx.compose.ui.Modifier 16 | import androidx.compose.ui.graphics.Color 17 | import androidx.compose.ui.unit.dp 18 | import com.peakmain.compose.project.constants.PkColor 19 | import com.peakmain.compose.ui.cell.PkCell 20 | import com.peakmain.compose.ui.title.PkNavBar 21 | import com.peakmain.compose.ui.title.PkTitleType 22 | 23 | /** 24 | * author :Peakmain 25 | * createTime:2025/6/26 26 | * mail:2726449200@qq.com 27 | * describe: 28 | */ 29 | @Composable 30 | fun CellPage() { 31 | Column( 32 | verticalArrangement = Arrangement.spacedBy(10.dp), 33 | modifier = Modifier.background(PkColor.color_fill2) 34 | ) { 35 | PkNavBar("单元格组件") 36 | PkCell( 37 | "常用功能", 38 | PkTitleType.BigTitle3(), 39 | rightText = "展开", 40 | modifier = Modifier 41 | .padding(horizontal = 18.dp), 42 | color = Color(0xFF14401B) 43 | ) 44 | // 基础用法(右侧带箭头图标) 45 | PkCell( 46 | text = "个人资料", 47 | type = PkTitleType.TitleBold1(), 48 | modifier = Modifier.padding(16.dp), 49 | rightContent = { 50 | Icon( 51 | imageVector = Icons.Default.ArrowForward, 52 | contentDescription = "进入", 53 | tint = Color.Gray 54 | ) 55 | } 56 | ) 57 | 58 | // 复杂右侧内容(文字 + 开关) 59 | PkCell( 60 | text = "夜间模式", 61 | color = Color.Black, 62 | rightContent = { 63 | Text("已开启", color = Color.Gray) 64 | Spacer(Modifier.width(8.dp)) 65 | Switch( 66 | checked = true, 67 | onCheckedChange = { /* 状态更新逻辑 */ } 68 | ) 69 | } 70 | ) 71 | } 72 | } -------------------------------------------------------------------------------- /app/src/main/java/com/peakmain/compose/project/page/basic/compose/ImagePage.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.project.page.basic.compose 2 | 3 | import androidx.compose.foundation.layout.Arrangement 4 | import androidx.compose.foundation.layout.Column 5 | import androidx.compose.foundation.layout.size 6 | import androidx.compose.runtime.Composable 7 | import androidx.compose.ui.Modifier 8 | import androidx.compose.ui.graphics.Color 9 | import androidx.compose.ui.res.painterResource 10 | import androidx.compose.ui.unit.dp 11 | import com.peakmain.compose.project.R 12 | import com.peakmain.compose.ui.image.PkImageView 13 | import com.peakmain.compose.ui.title.PkNavBar 14 | import com.peakmain.compose.ui.title.PkTitle 15 | import com.peakmain.compose.ui.title.PkTitleType 16 | import com.peakmain.compose.utils.ImagePainterUtils 17 | 18 | /** 19 | * author :Peakmain 20 | * createTime:2025/6/26 21 | * mail:2726449200@qq.com 22 | * describe: 23 | */ 24 | @Composable 25 | fun ImagePage() { 26 | val imageUrl="https://coil-kt.github.io/coil/images/coil_logo_black.svg" 27 | Column(verticalArrangement = Arrangement.spacedBy(10.dp)) { 28 | PkNavBar("图片组件") 29 | Column { 30 | PkTitle("加载本地图片", type = PkTitleType.BigTitle3()) 31 | PkImageView(painter = painterResource(R.drawable.portrair), modifier = Modifier.size(80.dp)) 32 | } 33 | Column { 34 | PkTitle("加载网络图片", type = PkTitleType.BigTitle3()) 35 | PkImageView(painter = ImagePainterUtils.getPainter(imageUrl), modifier = Modifier.size(80.dp)) 36 | } 37 | Column { 38 | PkTitle("加载网络图片,并修改颜色为红色", type = PkTitleType.BigTitle3()) 39 | PkImageView(painter = ImagePainterUtils.getPainter(imageUrl), tintColor = Color.Red,modifier = Modifier.size(80.dp)) 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /app/src/main/java/com/peakmain/compose/project/page/basic/compose/NavBarPage.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.project.page.basic.compose 2 | 3 | import android.widget.Toast 4 | import androidx.compose.foundation.layout.Arrangement 5 | import androidx.compose.foundation.layout.Column 6 | import androidx.compose.runtime.Composable 7 | import androidx.compose.ui.platform.LocalContext 8 | import androidx.compose.ui.unit.dp 9 | import com.peakmain.compose.project.R 10 | import com.peakmain.compose.ui.divier.PkDivider 11 | import com.peakmain.compose.ui.title.PkNavBar 12 | 13 | /** 14 | * author :Peakmain 15 | * createTime:2025/6/26 16 | * mail:2726449200@qq.com 17 | * describe: 18 | */ 19 | /** 20 | * 导航栏组件 21 | */ 22 | @Composable 23 | fun NavBarPage() { 24 | val context = LocalContext.current 25 | Column() { 26 | PkNavBar("NavBar组件") 27 | PkDivider(isHorizontal = true) 28 | Column(verticalArrangement = Arrangement.spacedBy(10.dp)) { 29 | PkNavBar("默认NavBar导航栏") 30 | PkNavBar("我是长文本的NavBar导航栏,超长的,但是不显示右边按钮") 31 | PkNavBar( 32 | "我是长文本的NavBar导航栏,超长的,显示右边按钮", 33 | rightResource = R.drawable.ic_menu 34 | ) 35 | PkNavBar("自定义返回事件", onBackClick = { 36 | Toast.makeText(context, "自定义返回事件", Toast.LENGTH_LONG).show() 37 | }) 38 | } 39 | 40 | } 41 | } -------------------------------------------------------------------------------- /app/src/main/java/com/peakmain/compose/project/page/basic/compose/TitlePage.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.project.page.basic.compose 2 | 3 | import androidx.compose.foundation.layout.Arrangement 4 | import androidx.compose.foundation.layout.Column 5 | import androidx.compose.foundation.layout.padding 6 | import androidx.compose.runtime.Composable 7 | import androidx.compose.ui.Alignment 8 | import androidx.compose.ui.Modifier 9 | import androidx.compose.ui.unit.dp 10 | import com.peakmain.compose.ui.divier.PkDivider 11 | import com.peakmain.compose.ui.title.PkNavBar 12 | import com.peakmain.compose.ui.title.PkTitle 13 | import com.peakmain.compose.ui.title.PkTitleType 14 | 15 | /** 16 | * author :Peakmain 17 | * createTime:2025/6/26 18 | * mail:2726449200@qq.com 19 | * describe: 20 | */ 21 | /** 22 | * 标题组件 23 | */ 24 | @Composable 25 | fun TitlePage() { 26 | Column( 27 | verticalArrangement = Arrangement.spacedBy(8.dp), 28 | horizontalAlignment = Alignment.CenterHorizontally 29 | ) { 30 | PkNavBar("标题组件") 31 | PkTitle("大标题1", PkTitleType.BigTitle1()) 32 | PkTitle("大标题2", PkTitleType.BigTitle2()) 33 | PkTitle("大标题3", PkTitleType.BigTitle3()) 34 | PkDivider(modifier = Modifier.padding(vertical = 10.dp), isHorizontal = true) 35 | PkTitle("标题1加粗", PkTitleType.TitleBold1()) 36 | PkTitle("标题1常规", PkTitleType.TitleNormal1()) 37 | PkTitle("标题2加粗", PkTitleType.TitleBold2()) 38 | PkTitle("标题2常规", PkTitleType.TitleNormal2()) 39 | PkDivider(modifier = Modifier.padding(vertical = 10.dp), isHorizontal = true) 40 | PkTitle("小标题加粗", PkTitleType.SmallTitleBold()) 41 | PkTitle("小标题常规", PkTitleType.SmallTitleNormal()) 42 | PkDivider(modifier = Modifier.padding(vertical = 10.dp), isHorizontal = true) 43 | PkTitle("内文1加粗", PkTitleType.TextBold1()) 44 | PkTitle("内文1正常", PkTitleType.TextNormal1()) 45 | PkTitle("内文2加粗", PkTitleType.TextBold2()) 46 | PkTitle("内文2正常", PkTitleType.TextNormal2()) 47 | } 48 | } -------------------------------------------------------------------------------- /app/src/main/java/com/peakmain/compose/project/page/display/DisplayComponentActivity.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.project.page.display 2 | 3 | import android.os.Bundle 4 | import androidx.activity.ComponentActivity 5 | import androidx.activity.compose.setContent 6 | import androidx.compose.runtime.Composable 7 | import androidx.compose.runtime.staticCompositionLocalOf 8 | import androidx.compose.ui.Modifier 9 | import com.peakmain.compose.project.page.display.compose.BannerPage 10 | import com.peakmain.compose.project.page.display.compose.DividerPage 11 | import com.peakmain.compose.project.page.display.compose.FlowRowPage 12 | import com.peakmain.compose.project.page.display.compose.GridPage 13 | import com.peakmain.compose.project.page.display.compose.HighlightTextPage 14 | import com.peakmain.compose.project.page.display.compose.StaggeredVerticalGridPage 15 | import com.peakmain.compose.ui.grid.PkStaggeredVerticalGrid 16 | 17 | /** 18 | * author :Peakmain 19 | * createTime:2025/6/26 20 | * mail:2726449200@qq.com 21 | * describe:展示组件 22 | */ 23 | class DisplayComponentActivity:ComponentActivity() { 24 | val type by lazy { 25 | intent.getIntExtra("type",0) 26 | } 27 | override fun onCreate(savedInstanceState: Bundle?) { 28 | super.onCreate(savedInstanceState) 29 | setContent { 30 | when(type){ 31 | 1->{ 32 | //网格布局 33 | GridPage() 34 | } 35 | 2->{ 36 | //分割线 37 | DividerPage() 38 | } 39 | 3->{ 40 | //流式布局 41 | FlowRowPage() 42 | } 43 | 4->{ 44 | //轮播图 45 | BannerPage() 46 | } 47 | 48 | 5->{ 49 | //高亮文本 50 | HighlightTextPage() 51 | } 52 | 6->{ 53 | //瀑布流组件 54 | StaggeredVerticalGridPage() 55 | } 56 | } 57 | } 58 | } 59 | } 60 | 61 | -------------------------------------------------------------------------------- /app/src/main/java/com/peakmain/compose/project/page/display/compose/BannerPage.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.project.page.display.compose 2 | 3 | import android.util.Log 4 | import androidx.compose.foundation.Image 5 | import androidx.compose.foundation.background 6 | import androidx.compose.foundation.layout.Box 7 | import androidx.compose.foundation.layout.Column 8 | import androidx.compose.foundation.layout.Row 9 | import androidx.compose.foundation.layout.Spacer 10 | import androidx.compose.foundation.layout.fillMaxHeight 11 | import androidx.compose.foundation.layout.fillMaxSize 12 | import androidx.compose.foundation.layout.fillMaxWidth 13 | import androidx.compose.foundation.layout.height 14 | import androidx.compose.foundation.layout.padding 15 | import androidx.compose.foundation.layout.size 16 | import androidx.compose.foundation.layout.width 17 | import androidx.compose.foundation.layout.wrapContentHeight 18 | import androidx.compose.foundation.layout.wrapContentWidth 19 | import androidx.compose.foundation.shape.CircleShape 20 | import androidx.compose.foundation.shape.RoundedCornerShape 21 | import androidx.compose.material.Text 22 | import androidx.compose.runtime.Composable 23 | import androidx.compose.ui.Alignment 24 | import androidx.compose.ui.Modifier 25 | import androidx.compose.ui.draw.clip 26 | import androidx.compose.ui.graphics.Color 27 | import androidx.compose.ui.layout.ContentScale 28 | import androidx.compose.ui.res.colorResource 29 | import androidx.compose.ui.res.dimensionResource 30 | import androidx.compose.ui.res.painterResource 31 | import androidx.compose.ui.text.style.TextOverflow 32 | import androidx.compose.ui.unit.dp 33 | import androidx.compose.ui.unit.sp 34 | import com.peakmain.compose.basic.BasicColor 35 | import com.peakmain.compose.basic.BasicFont 36 | import com.peakmain.compose.basic.BasicRadius 37 | import com.peakmain.compose.basic.BasicSize 38 | import com.peakmain.compose.basic.BasicSpace 39 | import com.peakmain.compose.library.TopAppBarCenter 40 | import com.peakmain.compose.project.R 41 | import com.peakmain.compose.project.component.CpColumn 42 | import com.peakmain.compose.project.constants.PkColor 43 | import com.peakmain.compose.space.PkSpacer 44 | import com.peakmain.compose.ui.banner.PkBanner 45 | import com.peakmain.compose.ui.image.PkImageView 46 | import com.peakmain.compose.ui.progress.RoundedLinearProgressIndicator 47 | import com.peakmain.compose.ui.title.PkNavBar 48 | import com.peakmain.compose.ui.title.PkTitle 49 | import com.peakmain.compose.ui.title.PkTitleType 50 | import com.peakmain.compose.utils.ImagePainterUtils 51 | 52 | /** 53 | * author :Peakmain 54 | * createTime:2025/6/27 55 | * mail:2726449200@qq.com 56 | * describe:轮播图 57 | */ 58 | @Composable 59 | fun BannerPage() { 60 | val lists = ArrayList().apply { 61 | add("https://img2.baidu.com/it/u=292395973,2170347184&fm=253&fmt=auto&app=120&f=JPEG?w=1280&h=800") 62 | add("https://img0.baidu.com/it/u=3492687357,1203050466&fm=253&fmt=auto&app=138&f=JPEG?w=889&h=500") 63 | add("https://img2.baidu.com/it/u=2843793126,682473204&fm=253&fmt=auto&app=120&f=JPEG?w=1280&h=800") 64 | add("https://img1.baidu.com/it/u=3907217777,761642486&fm=253&fmt=auto&app=120&f=JPEG?w=1280&h=800") 65 | add("https://img1.baidu.com/it/u=1082651511,4058105193&fm=253&fmt=auto&app=120&f=JPEG?w=1422&h=800") 66 | } 67 | val vLists = arrayListOf("广告", "我是垂直轮播", "生活好滋味,就要上四休三") 68 | CpColumn("轮播图组件") { 69 | PkTitle("默认水平轮播", type = PkTitleType.TextBold1(), modifier = Modifier.padding(18.dp)) 70 | PkBanner( 71 | lists, 72 | isAutoPlay = true, 73 | initialPage = 3, 74 | onBannerClick = { index, item -> 75 | Log.e("TAG", "获取到点击后的数据:${item}") 76 | }) { index, item -> 77 | Image( 78 | painter = ImagePainterUtils.getPainter(item), 79 | contentDescription = null, 80 | modifier = Modifier 81 | .clip(RoundedCornerShape(8.dp)) 82 | .fillMaxSize(), 83 | contentScale = ContentScale.Crop, 84 | alignment = Alignment.TopCenter 85 | ) 86 | } 87 | PkTitle("垂直轮播", type = PkTitleType.TextBold1(), modifier = Modifier.padding(18.dp)) 88 | PkBanner( 89 | vLists, 90 | isAutoPlay = true, 91 | isVertical = true 92 | ) { index, item -> 93 | Box() { 94 | Column( 95 | modifier = Modifier 96 | .clip(RoundedCornerShape(BasicRadius.radius_8)) 97 | .background(PkColor.color_fill2) 98 | .padding(bottom = BasicSpace.space_16) 99 | .fillMaxHeight(), 100 | ) { 101 | Box() { 102 | Column { 103 | Row( 104 | modifier = Modifier 105 | .padding( 106 | top = BasicSpace.space_16, 107 | start = BasicSpace.space_12, 108 | end = BasicSpace.space_12 109 | ), 110 | ) { 111 | // 左侧 圆形背景 + 图标 112 | Box( 113 | modifier = Modifier 114 | .size(BasicSize.size_40) 115 | .clip(CircleShape) 116 | .background(PkColor.color_fill1), 117 | contentAlignment = Alignment.Center 118 | ) { 119 | PkImageView( 120 | painter = painterResource( 121 | id = R.drawable.ic_online_check_out_disable 122 | ), 123 | modifier = Modifier.size(BasicSize.size_24), 124 | ) 125 | } 126 | 127 | Spacer(modifier = Modifier.width(BasicSpace.space_8)) 128 | 129 | // 中间 内容 130 | Column( 131 | modifier = Modifier.weight(1f) 132 | ) { 133 | Text( 134 | text = "已入住", 135 | color = PkColor.color_text1, 136 | fontSize = BasicFont.font_14, 137 | ) 138 | Spacer(modifier = Modifier.height(BasicSize.size_2)) 139 | Text( 140 | text = "2025年06月27日" + " | " + "金会员", 141 | color = PkColor.color_text2, 142 | fontSize = BasicFont.font_11, 143 | maxLines = 1, 144 | overflow = TextOverflow.Ellipsis 145 | ) 146 | } 147 | 148 | } 149 | // 底部进度条 150 | RoundedLinearProgressIndicator( 151 | progress = 0.5f, 152 | modifier = Modifier 153 | .padding(top = BasicSize.size_12) 154 | .fillMaxWidth() 155 | .height(BasicSize.size_4) 156 | .padding(horizontal = BasicSpace.space_16), 157 | color = PkColor.color_brand1, 158 | cornerRadius = BasicRadius.radius_2 159 | ) 160 | PkSpacer(height = BasicSize.size_16) 161 | } 162 | //洗衣取送 163 | Box( 164 | contentAlignment = Alignment.Center, 165 | modifier = Modifier 166 | .padding(end = BasicSpace.space_8) 167 | .align(Alignment.TopEnd) 168 | ) { 169 | Image( 170 | painter = painterResource(id = R.drawable.background_laundry_delivery), 171 | contentDescription = null, 172 | contentScale = ContentScale.FillBounds, 173 | modifier = Modifier 174 | .wrapContentWidth() 175 | .wrapContentHeight() 176 | ) 177 | androidx.compose.material3.Text( 178 | text = "垂直轮播", 179 | color = PkColor.color_text5, 180 | fontSize = BasicFont.font_11, 181 | modifier = Modifier 182 | .padding( 183 | horizontal = BasicSpace.space_7, 184 | vertical = BasicSpace.space_4 185 | ) 186 | ) 187 | 188 | 189 | } 190 | 191 | } 192 | } 193 | } 194 | } 195 | } 196 | } -------------------------------------------------------------------------------- /app/src/main/java/com/peakmain/compose/project/page/display/compose/DividerPage.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.project.page.display.compose 2 | 3 | import androidx.compose.foundation.background 4 | import androidx.compose.foundation.layout.Arrangement 5 | import androidx.compose.foundation.layout.Column 6 | import androidx.compose.foundation.layout.fillMaxHeight 7 | import androidx.compose.foundation.layout.padding 8 | import androidx.compose.runtime.Composable 9 | import androidx.compose.ui.Alignment 10 | import androidx.compose.ui.Modifier 11 | import androidx.compose.ui.unit.dp 12 | import com.peakmain.compose.project.constants.PkColor 13 | import com.peakmain.compose.ui.divier.PkDivider 14 | import com.peakmain.compose.ui.title.PkNavBar 15 | import com.peakmain.compose.ui.title.PkTitle 16 | import com.peakmain.compose.ui.title.PkTitleType 17 | 18 | /** 19 | * author :Peakmain 20 | * createTime:2025/6/26 21 | * mail:2726449200@qq.com 22 | * describe:分割线组件 23 | */ 24 | @Composable 25 | fun DividerPage() { 26 | Column(Modifier 27 | .background(PkColor.color_brand2) 28 | .fillMaxHeight(), horizontalAlignment = Alignment.CenterHorizontally) { 29 | PkNavBar("分割线组件") 30 | Column { 31 | PkTitle("默认垂直实线分割线", type = PkTitleType.TextBold1()) 32 | PkDivider() 33 | } 34 | Column { 35 | PkTitle("水平实线", type = PkTitleType.TextBold1()) 36 | PkDivider(modifier = Modifier.padding(top = 10.dp), isHorizontal = true) 37 | } 38 | Column { 39 | PkTitle("垂直虚线", type = PkTitleType.TextBold1()) 40 | PkDivider(isDash = true) 41 | } 42 | Column { 43 | PkTitle("水平虚线", type = PkTitleType.TextBold1()) 44 | PkDivider(modifier = Modifier.padding(top = 10.dp), isHorizontal = true, isDash = true) 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /app/src/main/java/com/peakmain/compose/project/page/display/compose/FlowRowPage.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.project.page.display.compose 2 | 3 | import androidx.compose.foundation.background 4 | import androidx.compose.foundation.layout.Column 5 | import androidx.compose.foundation.layout.fillMaxSize 6 | import androidx.compose.foundation.layout.padding 7 | import androidx.compose.foundation.shape.RoundedCornerShape 8 | import androidx.compose.material.Text 9 | import androidx.compose.runtime.Composable 10 | import androidx.compose.runtime.getValue 11 | import androidx.compose.runtime.mutableStateOf 12 | import androidx.compose.runtime.remember 13 | import androidx.compose.runtime.setValue 14 | import androidx.compose.ui.Modifier 15 | import androidx.compose.ui.graphics.Color 16 | import androidx.compose.ui.unit.dp 17 | import com.peakmain.compose.basic.BasicSize 18 | import com.peakmain.compose.project.R 19 | import com.peakmain.compose.ui.cell.PkCell 20 | import com.peakmain.compose.ui.divier.PkDivider 21 | import com.peakmain.compose.ui.flow.PkFlowRow 22 | import com.peakmain.compose.ui.title.PkNavBar 23 | import com.peakmain.compose.ui.title.PkTitle 24 | import com.peakmain.compose.ui.title.PkTitleType 25 | 26 | /** 27 | * author :Peakmain 28 | * createTime:2025/6/26 29 | * mail:2726449200@qq.com 30 | * describe: 31 | */ 32 | @Composable 33 | fun FlowRowPage() { 34 | val tags = listOf( 35 | "Android", 36 | "Kotlin", 37 | "Jetpack Compose", 38 | "KMP", 39 | "Material Design", 40 | "UI", 41 | "Development" 42 | ) 43 | var currentLine by remember { 44 | mutableStateOf(0) 45 | } 46 | var isExpand by remember { 47 | mutableStateOf(false) 48 | } 49 | Column(modifier = Modifier.fillMaxSize()) { 50 | PkNavBar("流式布局组件") 51 | Column(Modifier.padding(horizontal = 20.dp, vertical = 10.dp)) { 52 | Column { 53 | PkTitle("默认限制2行", type = PkTitleType.TextBold1()) 54 | PkFlowRow( 55 | modifier = Modifier.padding(top = BasicSize.size_12), 56 | horizontalSpacing = 8.dp, 57 | verticalSpacing = 12.dp, 58 | ) { 59 | tags.forEach { tag -> 60 | Text( 61 | text = tag, 62 | modifier = Modifier 63 | .background(Color.LightGray, RoundedCornerShape(16.dp)) 64 | .padding(horizontal = 12.dp, vertical = 8.dp) 65 | ) 66 | } 67 | } 68 | } 69 | 70 | Column(modifier = Modifier.padding(top = 40.dp)) { 71 | if (currentLine > 2) { 72 | PkCell( 73 | "超过2行显示展开/更多", 74 | type = PkTitleType.TextBold1(), 75 | rightText = if (!isExpand) "展开" else "收起", 76 | rightIcon= if (isExpand) R.drawable.ic_expend_arrow_down else R.drawable.ic_expend_arrow_up, 77 | rightClick = { 78 | isExpand = !isExpand 79 | } 80 | ) 81 | } 82 | PkFlowRow( 83 | modifier = Modifier.padding(top = BasicSize.size_12), 84 | horizontalSpacing = 8.dp, 85 | verticalSpacing = 12.dp, 86 | maxLine = if (isExpand) Int.MAX_VALUE else 2, 87 | onLineCountChanged = { 88 | currentLine = it 89 | }) { 90 | tags.forEach { tag -> 91 | Text( 92 | text = tag, 93 | modifier = Modifier 94 | .background(Color.LightGray, RoundedCornerShape(16.dp)) 95 | .padding(horizontal = 12.dp, vertical = 8.dp) 96 | ) 97 | } 98 | } 99 | } 100 | } 101 | 102 | } 103 | } -------------------------------------------------------------------------------- /app/src/main/java/com/peakmain/compose/project/page/display/compose/GridPage.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.project.page.display.compose 2 | 3 | import androidx.compose.foundation.background 4 | import androidx.compose.foundation.layout.Column 5 | import androidx.compose.foundation.layout.Spacer 6 | import androidx.compose.foundation.layout.fillMaxWidth 7 | import androidx.compose.foundation.layout.padding 8 | import androidx.compose.foundation.layout.width 9 | import androidx.compose.foundation.shape.RoundedCornerShape 10 | import androidx.compose.material.TabRowDefaults.Divider 11 | import androidx.compose.material.Text 12 | import androidx.compose.runtime.Composable 13 | import androidx.compose.ui.Modifier 14 | import androidx.compose.ui.graphics.Color 15 | import androidx.compose.ui.unit.dp 16 | import com.peakmain.compose.project.page.basic.compose.NavBarPage 17 | import com.peakmain.compose.space.PkSpacer 18 | import com.peakmain.compose.ui.PkGridLayout 19 | import com.peakmain.compose.ui.title.PkNavBar 20 | 21 | /** 22 | * author :Peakmain 23 | * createTime:2025/6/26 24 | * mail:2726449200@qq.com 25 | * describe: 26 | */ 27 | /** 28 | * 网格布局 29 | */ 30 | @Composable 31 | fun GridPage() { 32 | val dataList = mutableListOf("A", "B", "C", "D", "E", "F", "G") 33 | 34 | Column(modifier = Modifier.padding(horizontal = 15.dp)) { 35 | PkNavBar("网格布局") 36 | // 基础用法(2列,带列间距和默认分割线) 37 | PkSpacer(isHorizontal = true) 38 | PkGridLayout( 39 | columns = 2, 40 | data = dataList, 41 | isShowHorizontalDivider = true, 42 | columnSpacing = 16.dp, 43 | divider = { 44 | PkSpacer(isHorizontal = true) 45 | }, 46 | ) { index, item -> 47 | Text( 48 | text = "$item${index + 1}", 49 | modifier = Modifier 50 | .background(Color.LightGray, RoundedCornerShape(8.dp)) 51 | .padding(vertical = 8.dp) 52 | .fillMaxWidth() 53 | 54 | ) 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /app/src/main/java/com/peakmain/compose/project/page/display/compose/HighlightTextPage.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.project.page.display.compose 2 | 3 | import androidx.compose.foundation.background 4 | import androidx.compose.foundation.layout.Column 5 | import androidx.compose.material.MaterialTheme 6 | import androidx.compose.runtime.Composable 7 | import androidx.compose.ui.Modifier 8 | import androidx.compose.ui.graphics.Color 9 | import com.peakmain.compose.project.constants.PkColor 10 | import com.peakmain.compose.ui.text.PkHighlightText 11 | import com.peakmain.compose.ui.title.PkNavBar 12 | 13 | /** 14 | * author :Peakmain 15 | * createTime:2025/6/27 16 | * mail:2726449200@qq.com 17 | * describe: 18 | */ 19 | @Composable 20 | fun HighlightTextPage() { 21 | Column(modifier = Modifier.background(PkColor.color_fill1)) { 22 | PkNavBar("高亮文本组件") 23 | // 示例1:基本用法(多个关键字) 24 | PkHighlightText( 25 | text = "Jetpack Compose 是 Android 的现代 UI 工具包", 26 | keywords = listOf("compose", "android"), 27 | highlightColor = Color.Blue, 28 | style = MaterialTheme.typography.body1 29 | ) 30 | 31 | // 示例2:含特殊字符的关键字 32 | PkHighlightText( 33 | text = "价格:$199 (限时优惠)", 34 | keywords = listOf("$199", "(限时优惠)"), 35 | highlightColor = Color(0xFF4CAF50) 36 | ) 37 | 38 | // 示例3:无关键字/空列表 39 | PkHighlightText( 40 | text = "Hello World", 41 | keywords = emptyList() // 显示普通文本 42 | ) 43 | } 44 | } -------------------------------------------------------------------------------- /app/src/main/java/com/peakmain/compose/project/page/display/compose/StaggeredVerticalGridPage.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.project.page.display.compose 2 | 3 | import androidx.compose.foundation.background 4 | import androidx.compose.foundation.layout.Arrangement 5 | import androidx.compose.foundation.layout.Box 6 | import androidx.compose.foundation.layout.Column 7 | import androidx.compose.foundation.layout.PaddingValues 8 | import androidx.compose.foundation.layout.fillMaxSize 9 | import androidx.compose.foundation.layout.fillMaxWidth 10 | import androidx.compose.foundation.layout.height 11 | import androidx.compose.foundation.layout.heightIn 12 | import androidx.compose.foundation.layout.padding 13 | import androidx.compose.foundation.layout.wrapContentHeight 14 | import androidx.compose.foundation.lazy.staggeredgrid.LazyVerticalStaggeredGrid 15 | import androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridCells 16 | import androidx.compose.material.Text 17 | import androidx.compose.runtime.Composable 18 | import androidx.compose.ui.Alignment 19 | import androidx.compose.ui.Modifier 20 | import androidx.compose.ui.graphics.Color 21 | import androidx.compose.ui.unit.Dp 22 | import androidx.compose.ui.unit.dp 23 | import androidx.compose.ui.unit.min 24 | import com.peakmain.compose.project.component.CpColumn 25 | import com.peakmain.compose.project.constants.PkColor 26 | import com.peakmain.compose.ui.grid.PkStaggeredVerticalGrid 27 | import kotlin.random.Random 28 | 29 | /** 30 | * author :Peakmain 31 | * createTime:2025/6/27 32 | * mail:2726449200@qq.com 33 | * describe: 34 | */ 35 | @Composable 36 | fun StaggeredVerticalGridPage() { 37 | // 生成示例数据(包含随机高度) 38 | val items = List(5) { index -> 39 | StaggeredItem( 40 | id = index, height = (20 + Random.nextInt(50)).dp, // 随机高度 (120-270dp) 41 | title = "Item ${index + 1}" 42 | ) 43 | } 44 | CpColumn("瀑布流组件") { 45 | Column { 46 | PkStaggeredVerticalGrid( 47 | columns = 2, 48 | contentPadding = PaddingValues(16.dp), 49 | verticalItemSpacing = 4.dp, 50 | horizontalItemSpacing = 16.dp, // 水平间距 51 | modifier = Modifier.wrapContentHeight() 52 | 53 | ) { 54 | items.forEach { item -> 55 | Box( 56 | modifier = Modifier 57 | .fillMaxWidth() 58 | .height(item.height) 59 | .background( 60 | Color( 61 | red = Random.nextInt(256), 62 | green = Random.nextInt(256), 63 | blue = Random.nextInt(256), 64 | alpha = 255 65 | ) 66 | ), 67 | ) { 68 | Box( 69 | modifier = Modifier 70 | .fillMaxSize(), contentAlignment = Alignment.Center 71 | ) { 72 | Text( 73 | text = item.title, 74 | color = Color.White, 75 | modifier = Modifier.padding(8.dp) 76 | ) 77 | } 78 | } 79 | } 80 | } 81 | } 82 | } 83 | } 84 | 85 | data class StaggeredItem( 86 | val id: Int, val height: Dp, val title: String 87 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/peakmain/compose/project/page/expand/ExpandActivity.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.project.page.expand 2 | 3 | import android.os.Bundle 4 | import androidx.activity.ComponentActivity 5 | import androidx.activity.compose.setContent 6 | import com.peakmain.compose.project.page.expand.component.ListExtPage 7 | 8 | /** 9 | * author :Peakmain 10 | * createTime:2025/6/27 11 | * mail:2726449200@qq.com 12 | * describe: 13 | */ 14 | class ExpandActivity : ComponentActivity() { 15 | val type by lazy { 16 | intent.getIntExtra("type", 0) 17 | } 18 | 19 | override fun onCreate(savedInstanceState: Bundle?) { 20 | super.onCreate(savedInstanceState) 21 | setContent { 22 | when (type) { 23 | 1 -> { 24 | //List扩展类 25 | ListExtPage() 26 | } 27 | } 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /app/src/main/java/com/peakmain/compose/project/page/expand/component/ListExtPage.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.project.page.expand.component 2 | 3 | import androidx.compose.foundation.layout.padding 4 | import androidx.compose.material.Text 5 | import androidx.compose.runtime.Composable 6 | import androidx.compose.ui.Modifier 7 | import androidx.compose.ui.input.key.Key.Companion.At 8 | import androidx.compose.ui.unit.dp 9 | import com.peakmain.compose.basic.BasicFont 10 | import com.peakmain.compose.ext.orSize 11 | import com.peakmain.compose.ext.sizeBigZero 12 | import com.peakmain.compose.ext.slice 13 | import com.peakmain.compose.project.component.CpColumn 14 | import com.peakmain.compose.project.component.CpTitle 15 | import com.peakmain.compose.project.constants.PkColor 16 | 17 | /** 18 | * author :Peakmain 19 | * createTime:2025/6/27 20 | * mail:2726449200@qq.com 21 | * describe: 22 | */ 23 | @Composable 24 | fun ListExtPage() { 25 | val list1: List? = null 26 | val list2 = arrayListOf("list1", "list2", "list3", "list4") 27 | CpColumn("List扩展类") { 28 | CpTitle("空数组list1的大小:${list1.orSize()}") 29 | CpTitle("空数组list1的大小是否等于0:${list1.sizeBigZero()}") 30 | CpTitle("空数组list1的大小是否大于0:${list1.sizeBigZero()}") 31 | CpTitle("定索引范围 [fromIndex, toIndex) 内的子列表视图") 32 | var result: String = "结果是:" 33 | list2.slice(1, 3)?.forEach { 34 | result +="$it," 35 | } 36 | Text(result, fontSize = BasicFont.font_10, color = PkColor.color_text1, modifier = Modifier.padding(horizontal = 18.dp)) 37 | 38 | } 39 | } -------------------------------------------------------------------------------- /app/src/main/java/com/peakmain/compose/project/page/tools/ToolsActivity.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.project.page.tools 2 | 3 | import android.os.Bundle 4 | import androidx.activity.ComponentActivity 5 | import androidx.activity.compose.setContent 6 | import com.peakmain.compose.project.page.tools.component.ImagePainterUtilsPage 7 | 8 | /** 9 | * author :Peakmain 10 | * createTime:2025/6/27 11 | * mail:2726449200@qq.com 12 | * describe: 13 | */ 14 | class ToolsActivity : ComponentActivity() { 15 | val type by lazy { 16 | intent.getIntExtra("type", 0) 17 | } 18 | 19 | override fun onCreate(savedInstanceState: Bundle?) { 20 | super.onCreate(savedInstanceState) 21 | setContent { 22 | when (type) { 23 | 1 -> { 24 | ImagePainterUtilsPage() 25 | } 26 | } 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /app/src/main/java/com/peakmain/compose/project/page/tools/component/ImagePainterUtilsPage.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.project.page.tools.component 2 | 3 | import androidx.compose.foundation.Image 4 | import androidx.compose.foundation.layout.Column 5 | import androidx.compose.foundation.layout.Row 6 | import androidx.compose.foundation.layout.height 7 | import androidx.compose.foundation.layout.padding 8 | import androidx.compose.foundation.layout.size 9 | import androidx.compose.foundation.layout.width 10 | import androidx.compose.material.Text 11 | import androidx.compose.runtime.Composable 12 | import androidx.compose.ui.Modifier 13 | import androidx.compose.ui.input.pointer.PointerIcon.Companion.Text 14 | import androidx.compose.ui.unit.dp 15 | import com.peakmain.compose.project.component.CpCell 16 | import com.peakmain.compose.project.component.CpColumn 17 | import com.peakmain.compose.project.component.CpTitle 18 | import com.peakmain.compose.ui.image.PkImageView 19 | import com.peakmain.compose.ui.title.PkTitle 20 | import com.peakmain.compose.ui.title.PkTitleType 21 | import com.peakmain.compose.utils.ImagePainterUtils 22 | 23 | /** 24 | * author :Peakmain 25 | * createTime:2025/6/27 26 | * mail:2726449200@qq.com 27 | * describe: 28 | */ 29 | @Composable 30 | fun ImagePainterUtilsPage() { 31 | val imageUrls = 32 | arrayListOf( 33 | "https://inews.gtimg.com/om_bt/O3HPBXvE8uZQS2PlMcFZpECPpRqLPVJ-ti-LYB2z5JdiYAA/641", 34 | "https://coil-kt.github.io/coil/images/coil_logo_black.svg", 35 | "https://ww3.sinaimg.cn/mw690/005Ohgevjw1eobhokb9ekg30cc06y1l0.gif" 36 | ) 37 | CpColumn("ImagePainterUtils工具类") { 38 | Row { 39 | Column { 40 | CpTitle("正常展示png/jpg/webp图片") 41 | PkImageView( 42 | ImagePainterUtils.getPainter(imageUrls[0]), 43 | modifier = Modifier.height(150.dp) 44 | ) 45 | } 46 | Column { 47 | CpTitle("展示svg图片") 48 | PkImageView( 49 | painter = ImagePainterUtils.getPainter(imageUrls[1]), 50 | modifier = Modifier.height(150.dp) 51 | ) 52 | } 53 | 54 | } 55 | Row { 56 | Column { 57 | CpTitle("展示gif图片") 58 | PkImageView( 59 | painter = ImagePainterUtils.getPainter(imageUrls[2]), 60 | ) 61 | 62 | } 63 | Column(modifier = Modifier.padding(horizontal = 18.dp)) { 64 | CpTitle("占位图") 65 | PkImageView( 66 | painter = ImagePainterUtils.getPainter(null), 67 | modifier = Modifier.size(150.dp) 68 | ) 69 | } 70 | } 71 | } 72 | } -------------------------------------------------------------------------------- /app/src/main/java/com/peakmain/compose/project/ui/theme/Color.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.project.ui.theme 2 | 3 | import androidx.compose.ui.graphics.Color 4 | val Color_149EE7= Color(0xFF149EE7) 5 | val Color_2DCDF5= Color(0xFF2DCDF5) 6 | 7 | val Color_999999=Color(0xFF999999) 8 | val Color_969799=Color(0xFF969799) 9 | val Color_323233=Color(0xFF323233) 10 | val Color_D1D1D1=Color(0xFFD1D1D1) 11 | -------------------------------------------------------------------------------- /app/src/main/java/com/peakmain/compose/project/ui/theme/Shape.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.project.ui.theme 2 | 3 | import androidx.compose.foundation.shape.RoundedCornerShape 4 | import androidx.compose.material.Shapes 5 | import androidx.compose.ui.unit.dp 6 | 7 | val Shapes = Shapes( 8 | small = RoundedCornerShape(4.dp), 9 | medium = RoundedCornerShape(4.dp), 10 | large = RoundedCornerShape(0.dp) 11 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/peakmain/compose/project/ui/theme/Theme.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.project.ui.theme 2 | 3 | import androidx.compose.material.MaterialTheme 4 | import androidx.compose.material.lightColors 5 | import androidx.compose.runtime.Composable 6 | 7 | private val LightColorPalette = lightColors( 8 | primary = Color_149EE7, 9 | primaryVariant = Color_149EE7, 10 | secondary = Color_2DCDF5 11 | ) 12 | 13 | @Composable 14 | fun ComposeProjectTheme( 15 | content: @Composable() () -> Unit, 16 | ) { 17 | val colors = 18 | LightColorPalette 19 | 20 | MaterialTheme( 21 | colors = colors, 22 | typography = Typography, 23 | shapes = Shapes, 24 | content = content 25 | ) 26 | } -------------------------------------------------------------------------------- /app/src/main/java/com/peakmain/compose/project/ui/theme/Type.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.project.ui.theme 2 | 3 | import androidx.compose.material.Typography 4 | import androidx.compose.ui.text.TextStyle 5 | import androidx.compose.ui.text.font.FontFamily 6 | import androidx.compose.ui.text.font.FontWeight 7 | import androidx.compose.ui.unit.sp 8 | 9 | // Set of Material typography styles to start with 10 | val Typography = Typography( 11 | body1 = TextStyle( 12 | fontFamily = FontFamily.Default, 13 | fontWeight = FontWeight.Normal, 14 | fontSize = 16.sp 15 | ) 16 | /* Other default text styles to override 17 | button = TextStyle( 18 | fontFamily = FontFamily.Default, 19 | fontWeight = FontWeight.W500, 20 | fontSize = 14.sp 21 | ), 22 | caption = TextStyle( 23 | fontFamily = FontFamily.Default, 24 | fontWeight = FontWeight.Normal, 25 | fontSize = 12.sp 26 | ) 27 | */ 28 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/peakmain/compose/project/ui/view/MainFrame.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.project.ui.view 2 | 3 | /** 4 | * author :Peakmain 5 | * createTime:2022/5/2 6 | * mail:2726449200@qq.com 7 | * describe: 8 | */ 9 | import android.annotation.SuppressLint 10 | import androidx.compose.foundation.layout.navigationBarsPadding 11 | import androidx.compose.material.* 12 | import androidx.compose.material.icons.Icons 13 | import androidx.compose.material.icons.filled.* 14 | import androidx.compose.runtime.* 15 | import androidx.compose.ui.Modifier 16 | import androidx.compose.ui.tooling.preview.Preview 17 | import com.peakmain.compose.project.bean.main.NavigationItem 18 | import com.peakmain.compose.project.ui.theme.Color_149EE7 19 | import com.peakmain.compose.project.ui.theme.Color_999999 20 | import com.peakmain.compose.project.ui.view.main.HomeFragment 21 | import com.peakmain.compose.project.ui.view.main.ExpandFragment 22 | import com.peakmain.compose.project.ui.view.main.ProjectFragment 23 | import com.peakmain.compose.project.ui.view.main.TypeFragment 24 | 25 | @SuppressLint("UnusedMaterialScaffoldPaddingParameter") 26 | @Composable 27 | fun MainFrame() { 28 | val navigationItems = listOf( 29 | NavigationItem("基础组件", Icons.Default.Home), 30 | NavigationItem("展示组件", Icons.Default.AccountCircle), 31 | NavigationItem("工具类", Icons.Default.LocationOn), 32 | NavigationItem("扩展类", Icons.Default.Person) 33 | ) 34 | var currentNavigationIndex by remember { 35 | mutableStateOf(0) 36 | } 37 | Scaffold( 38 | bottomBar = { 39 | BottomNavigation( 40 | backgroundColor = MaterialTheme.colors.surface, 41 | modifier = Modifier.navigationBarsPadding() 42 | ) { 43 | navigationItems.forEachIndexed { index, navigationItem -> 44 | BottomNavigationItem( 45 | selected = currentNavigationIndex == index, 46 | onClick = { currentNavigationIndex = index }, 47 | icon = { 48 | Icon(imageVector = navigationItem.icon, contentDescription = null) 49 | }, 50 | label = { 51 | Text(text = navigationItem.title) 52 | }, 53 | selectedContentColor = Color_149EE7, 54 | unselectedContentColor = Color_999999 55 | ) 56 | } 57 | } 58 | }, 59 | ) { 60 | when (currentNavigationIndex) { 61 | 0 -> HomeFragment() 62 | 1 -> ProjectFragment() 63 | 2 -> TypeFragment() 64 | else -> ExpandFragment() 65 | } 66 | } 67 | } 68 | 69 | @Preview 70 | @Composable 71 | fun MainFramePreview() { 72 | MainFrame() 73 | } 74 | 75 | -------------------------------------------------------------------------------- /app/src/main/java/com/peakmain/compose/project/ui/view/main/BasicFragment.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.project.ui.view.main 2 | 3 | /** 4 | * author :Peakmain 5 | * createTime:2022/5/2 6 | * mail:2726449200@qq.com 7 | * describe: 8 | */ 9 | import android.content.Intent 10 | import androidx.compose.foundation.background 11 | import androidx.compose.foundation.clickable 12 | import androidx.compose.foundation.layout.Arrangement 13 | import androidx.compose.foundation.layout.Column 14 | import androidx.compose.foundation.layout.fillMaxSize 15 | import androidx.compose.foundation.layout.padding 16 | import androidx.compose.material.Text 17 | import androidx.compose.runtime.Composable 18 | import androidx.compose.ui.Alignment 19 | import androidx.compose.ui.Modifier 20 | import androidx.compose.ui.graphics.Brush 21 | import androidx.compose.ui.graphics.Color 22 | import androidx.compose.ui.platform.LocalContext 23 | import com.peakmain.compose.basic.BasicSpace 24 | import com.peakmain.compose.library.TopAppBarCenter 25 | import com.peakmain.compose.project.page.basic.BasicComponentActivity 26 | import com.peakmain.compose.project.ui.theme.Color_149EE7 27 | import com.peakmain.compose.project.ui.theme.Color_2DCDF5 28 | import com.peakmain.compose.ui.cell.PkCell 29 | import com.peakmain.compose.ui.title.PkTitleType 30 | 31 | @Composable 32 | fun HomeFragment() { 33 | val context = LocalContext.current 34 | val intent=Intent(context,BasicComponentActivity::class.java) 35 | TopAppBarCenter( 36 | title = { 37 | Text(text = "首页", color = Color.White) 38 | }, 39 | isImmersive = true, 40 | modifier = Modifier.background(Brush.linearGradient(listOf(Color_149EE7, Color_2DCDF5))) 41 | ) { 42 | 43 | Column( 44 | modifier = Modifier 45 | .padding(BasicSpace.space_18) 46 | .fillMaxSize(), 47 | verticalArrangement = Arrangement.spacedBy(BasicSpace.space_18), 48 | horizontalAlignment = Alignment.CenterHorizontally 49 | ) { 50 | PkCell(text = "标题组件", modifier = Modifier.clickable { 51 | intent.putExtra("type",1) 52 | context.startActivity(intent) 53 | }, type = PkTitleType.TitleBold1()) 54 | PkCell(text = "NavBar导航栏", modifier = Modifier.clickable { 55 | intent.putExtra("type",2) 56 | context.startActivity(intent) 57 | }, type = PkTitleType.TitleBold1()) 58 | 59 | PkCell(text = "单元格组件", modifier = Modifier.clickable { 60 | intent.putExtra("type",3) 61 | context.startActivity(intent) 62 | }, type = PkTitleType.TitleBold1()) 63 | PkCell(text = "按钮组件", modifier = Modifier.clickable { 64 | intent.putExtra("type",4) 65 | context.startActivity(intent) 66 | }, type = PkTitleType.TitleBold1()) 67 | PkCell(text = "图片组件", modifier = Modifier.clickable { 68 | intent.putExtra("type",5) 69 | context.startActivity(intent) 70 | }, type = PkTitleType.TitleBold1()) 71 | } 72 | } 73 | } 74 | 75 | -------------------------------------------------------------------------------- /app/src/main/java/com/peakmain/compose/project/ui/view/main/DisplayFragment.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.project.ui.view.main 2 | 3 | /** 4 | * author :Peakmain 5 | * createTime:2022/5/2 6 | * mail:2726449200@qq.com 7 | * describe: 8 | */ 9 | import android.content.Intent 10 | import androidx.compose.foundation.background 11 | import androidx.compose.foundation.layout.Arrangement 12 | import androidx.compose.foundation.layout.Column 13 | import androidx.compose.foundation.layout.fillMaxSize 14 | import androidx.compose.foundation.layout.padding 15 | import androidx.compose.material.Text 16 | import androidx.compose.runtime.Composable 17 | import androidx.compose.ui.Alignment 18 | import androidx.compose.ui.Modifier 19 | import androidx.compose.ui.graphics.Brush 20 | import androidx.compose.ui.graphics.Color 21 | import androidx.compose.ui.platform.LocalContext 22 | import com.peakmain.compose.basic.BasicSpace 23 | import com.peakmain.compose.library.TopAppBarCenter 24 | import com.peakmain.compose.project.component.CpCell 25 | import com.peakmain.compose.project.page.display.DisplayComponentActivity 26 | import com.peakmain.compose.project.ui.theme.Color_149EE7 27 | import com.peakmain.compose.project.ui.theme.Color_2DCDF5 28 | 29 | @Composable 30 | fun ProjectFragment() { 31 | val context = LocalContext.current 32 | val intent = Intent(context, DisplayComponentActivity::class.java) 33 | val lists = arrayListOf("网格布局", "分割线", "流式布局", "轮播图", "高亮文本", "瀑布流") 34 | TopAppBarCenter( 35 | title = { 36 | Text(text = "展示组件", color = Color.White) 37 | }, 38 | isImmersive = true, 39 | modifier = Modifier.background(Brush.linearGradient(listOf(Color_149EE7, Color_2DCDF5))) 40 | ) { 41 | 42 | Column( 43 | modifier = Modifier 44 | .padding(BasicSpace.space_18) 45 | .fillMaxSize(), 46 | verticalArrangement = Arrangement.spacedBy(BasicSpace.space_18), 47 | horizontalAlignment = Alignment.CenterHorizontally 48 | ) { 49 | lists.forEachIndexed { index, item -> 50 | CpCell(item, intent, index + 1) 51 | } 52 | } 53 | } 54 | } 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /app/src/main/java/com/peakmain/compose/project/ui/view/main/ExpandFragment.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.project.ui.view.main 2 | 3 | /** 4 | * author :Peakmain 5 | * createTime:2022/5/2 6 | * mail:2726449200@qq.com 7 | * describe:我的 8 | */ 9 | import android.content.Intent 10 | import androidx.compose.foundation.background 11 | import androidx.compose.foundation.layout.* 12 | import androidx.compose.material.Text 13 | import androidx.compose.runtime.Composable 14 | import androidx.compose.ui.Alignment 15 | import androidx.compose.ui.Modifier 16 | import androidx.compose.ui.graphics.Brush 17 | import androidx.compose.ui.graphics.Color 18 | import androidx.compose.ui.platform.LocalContext 19 | import com.peakmain.compose.project.ui.theme.Color_149EE7 20 | import com.peakmain.compose.project.ui.theme.Color_2DCDF5 21 | import com.peakmain.compose.basic.BasicSpace 22 | import com.peakmain.compose.library.TopAppBarCenter 23 | import com.peakmain.compose.project.component.CpCell 24 | import com.peakmain.compose.project.page.display.DisplayComponentActivity 25 | import com.peakmain.compose.project.page.expand.ExpandActivity 26 | 27 | @Composable 28 | fun ExpandFragment() { 29 | val context = LocalContext.current 30 | val intent = Intent(context, ExpandActivity::class.java) 31 | val lists = arrayListOf("List扩展类", "String扩展类") 32 | TopAppBarCenter( 33 | title = { 34 | Text(text = "展示组件", color = Color.White) 35 | }, 36 | isImmersive = true, 37 | modifier = Modifier.background(Brush.linearGradient(listOf(Color_149EE7, Color_2DCDF5))) 38 | ) { 39 | 40 | Column( 41 | modifier = Modifier 42 | .padding(BasicSpace.space_18) 43 | .fillMaxSize(), 44 | verticalArrangement = Arrangement.spacedBy(BasicSpace.space_18), 45 | horizontalAlignment = Alignment.CenterHorizontally 46 | ) { 47 | lists.forEachIndexed { index, item -> 48 | CpCell(item, intent, index + 1) 49 | } 50 | } 51 | } 52 | } 53 | 54 | -------------------------------------------------------------------------------- /app/src/main/java/com/peakmain/compose/project/ui/view/main/ToolsFragment.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.project.ui.view.main 2 | 3 | /** 4 | * author :Peakmain 5 | * createTime:2022/5/2 6 | * mail:2726449200@qq.com 7 | * describe:分类Fragment 8 | */ 9 | import android.content.Intent 10 | import androidx.compose.foundation.ExperimentalFoundationApi 11 | import androidx.compose.foundation.background 12 | import androidx.compose.foundation.layout.Arrangement 13 | import androidx.compose.foundation.layout.Column 14 | import androidx.compose.foundation.layout.fillMaxSize 15 | import androidx.compose.foundation.layout.padding 16 | import androidx.compose.material.Text 17 | import androidx.compose.runtime.Composable 18 | import androidx.compose.ui.Alignment 19 | import androidx.compose.ui.Modifier 20 | import androidx.compose.ui.graphics.Brush 21 | import androidx.compose.ui.graphics.Color 22 | import androidx.compose.ui.platform.LocalContext 23 | import com.peakmain.compose.basic.BasicSpace 24 | import com.peakmain.compose.library.TopAppBarCenter 25 | import com.peakmain.compose.project.component.CpCell 26 | import com.peakmain.compose.project.page.tools.ToolsActivity 27 | import com.peakmain.compose.project.ui.theme.Color_149EE7 28 | import com.peakmain.compose.project.ui.theme.Color_2DCDF5 29 | 30 | 31 | @OptIn(ExperimentalFoundationApi::class) 32 | @Composable 33 | fun TypeFragment() { 34 | val context = LocalContext.current 35 | val intent = Intent(context, ToolsActivity::class.java) 36 | val lists = arrayListOf("ImagePainter工具类") 37 | TopAppBarCenter( 38 | title = { 39 | Text(text = "展示组件", color = Color.White) 40 | }, 41 | isImmersive = true, 42 | modifier = Modifier.background(Brush.linearGradient(listOf(Color_149EE7, Color_2DCDF5))) 43 | ) { 44 | 45 | Column( 46 | modifier = Modifier 47 | .padding(BasicSpace.space_18) 48 | .fillMaxSize(), 49 | verticalArrangement = Arrangement.spacedBy(BasicSpace.space_18), 50 | horizontalAlignment = Alignment.CenterHorizontally 51 | ) { 52 | lists.forEachIndexed { index, item -> 53 | CpCell(item, intent, index + 1) 54 | } 55 | } 56 | } 57 | } 58 | 59 | -------------------------------------------------------------------------------- /app/src/main/java/com/peakmain/compose/project/viewmodel/home/HomeFragmentViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.project.viewmodel.home 2 | 3 | import androidx.compose.runtime.getValue 4 | import androidx.compose.runtime.mutableStateOf 5 | import androidx.lifecycle.ViewModel 6 | import com.peakmain.compose.project.bean.home.BannerBean 7 | 8 | /** 9 | * author :Peakmain 10 | * createTime:2022/5/5 11 | * mail:2726449200@qq.com 12 | * describe: 13 | */ 14 | class HomeFragmentViewModel : ViewModel() { 15 | 16 | val bannerData by mutableStateOf( 17 | listOf( 18 | BannerBean("http://img.ahhuabang.com/data/banner/phone20220429gtvjsq.jpg","标题一"), 19 | BannerBean("http://img.ahhuabang.com/data/banner/phone20220429plqcyr.jpg","标题二"), 20 | BannerBean("http://img.ahhuabang.com/data/banner/phone20220429taojjf.jpg","标题三"), 21 | BannerBean("http://img.ahhuabang.com/data/banner/phone20220422aeoihx.jpg","标题四"), 22 | ) 23 | ) 24 | 25 | 26 | } -------------------------------------------------------------------------------- /app/src/main/java/com/peakmain/compose/project/viewmodel/mine/MineFragmentViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.project.viewmodel.mine 2 | 3 | import androidx.compose.material.icons.Icons 4 | import androidx.compose.material.icons.filled.Settings 5 | import androidx.compose.material.icons.filled.ThumbUp 6 | import androidx.compose.runtime.getValue 7 | import androidx.compose.runtime.mutableStateOf 8 | import androidx.lifecycle.ViewModel 9 | import com.peakmain.compose.project.bean.mine.MineItemBean 10 | 11 | /** 12 | * author :Peakmain 13 | * createTime:2022/5/7 14 | * mail:2726449200@qq.com 15 | * describe: 16 | */ 17 | class MineFragmentViewModel :ViewModel(){ 18 | val mineItemBeans by mutableStateOf( 19 | listOf( 20 | MineItemBean("我的收藏",Icons.Default.ThumbUp), 21 | MineItemBean("设置",Icons.Default.Settings), 22 | 23 | ) 24 | ) 25 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/background_laundry_delivery.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_expend_arrow_down.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_expend_arrow_up.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_menu.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_online_check_out_disable.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/portrair.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Peakmain/ComposeUI/130ddea901c25d528b4a130ba2c6919cb55a8155/app/src/main/res/drawable/portrair.JPG -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Peakmain/ComposeUI/130ddea901c25d528b4a130ba2c6919cb55a8155/app/src/main/res/mipmap-hdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Peakmain/ComposeUI/130ddea901c25d528b4a130ba2c6919cb55a8155/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Peakmain/ComposeUI/130ddea901c25d528b4a130ba2c6919cb55a8155/app/src/main/res/mipmap-mdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Peakmain/ComposeUI/130ddea901c25d528b4a130ba2c6919cb55a8155/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Peakmain/ComposeUI/130ddea901c25d528b4a130ba2c6919cb55a8155/app/src/main/res/mipmap-xhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Peakmain/ComposeUI/130ddea901c25d528b4a130ba2c6919cb55a8155/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Peakmain/ComposeUI/130ddea901c25d528b4a130ba2c6919cb55a8155/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Peakmain/ComposeUI/130ddea901c25d528b4a130ba2c6919cb55a8155/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Peakmain/ComposeUI/130ddea901c25d528b4a130ba2c6919cb55a8155/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Peakmain/ComposeUI/130ddea901c25d528b4a130ba2c6919cb55a8155/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FF149EE7 4 | #9D9C96 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | ComposeProject 3 | -------------------------------------------------------------------------------- /app/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /app/src/test/java/com/peakmain/compose/project/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.project 2 | 3 | import org.junit.Test 4 | 5 | import org.junit.Assert.* 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | class ExampleUnitTest { 13 | @Test 14 | fun addition_isCorrect() { 15 | assertEquals(4, 2 + 2) 16 | } 17 | } -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | buildscript { 3 | ext.kotlin_version = '1.9.20' 4 | repositories { 5 | maven { url = uri("https://maven.aliyun.com/repository/central") } 6 | maven { url = uri("https://maven.aliyun.com/repository/google") } 7 | maven { url = uri("https://maven.aliyun.com/repository/public") } 8 | google() 9 | mavenCentral() 10 | } 11 | dependencies { 12 | classpath 'com.android.tools.build:gradle:8.4.0' 13 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 14 | 15 | // NOTE: Do not place your application dependencies here; they belong 16 | // in the individual module build.gradle files 17 | } 18 | } 19 | 20 | task clean(type: Delete) { 21 | delete rootProject.buildDir 22 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app"s APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Automatically convert third-party libraries to use AndroidX 19 | android.enableJetifier=true 20 | # Kotlin code style for this project: "official" or "obsolete": 21 | kotlin.code.style=official 22 | android.nonTransitiveRClass=false 23 | android.nonFinalResIds=false -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Peakmain/ComposeUI/130ddea901c25d528b4a130ba2c6919cb55a8155/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon May 02 12:27:14 CST 2022 2 | distributionBase=GRADLE_USER_HOME 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip 4 | distributionPath=wrapper/dists 5 | zipStorePath=wrapper/dists 6 | zipStoreBase=GRADLE_USER_HOME 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | 86 | # Determine the Java command to use to start the JVM. 87 | if [ -n "$JAVA_HOME" ] ; then 88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 89 | # IBM's JDK on AIX uses strange locations for the executables 90 | JAVACMD="$JAVA_HOME/jre/sh/java" 91 | else 92 | JAVACMD="$JAVA_HOME/bin/java" 93 | fi 94 | if [ ! -x "$JAVACMD" ] ; then 95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 96 | 97 | Please set the JAVA_HOME variable in your environment to match the 98 | location of your Java installation." 99 | fi 100 | else 101 | JAVACMD="java" 102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 103 | 104 | Please set the JAVA_HOME variable in your environment to match the 105 | location of your Java installation." 106 | fi 107 | 108 | # Increase the maximum file descriptors if we can. 109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 110 | MAX_FD_LIMIT=`ulimit -H -n` 111 | if [ $? -eq 0 ] ; then 112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 113 | MAX_FD="$MAX_FD_LIMIT" 114 | fi 115 | ulimit -n $MAX_FD 116 | if [ $? -ne 0 ] ; then 117 | warn "Could not set maximum file descriptor limit: $MAX_FD" 118 | fi 119 | else 120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 121 | fi 122 | fi 123 | 124 | # For Darwin, add options to specify how the application appears in the dock 125 | if $darwin; then 126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 127 | fi 128 | 129 | # For Cygwin or MSYS, switch paths to Windows format before running java 130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 133 | 134 | JAVACMD=`cygpath --unix "$JAVACMD"` 135 | 136 | # We build the pattern for arguments to be converted via cygpath 137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 138 | SEP="" 139 | for dir in $ROOTDIRSRAW ; do 140 | ROOTDIRS="$ROOTDIRS$SEP$dir" 141 | SEP="|" 142 | done 143 | OURCYGPATTERN="(^($ROOTDIRS))" 144 | # Add a user-defined pattern to the cygpath arguments 145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 147 | fi 148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 149 | i=0 150 | for arg in "$@" ; do 151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 153 | 154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 156 | else 157 | eval `echo args$i`="\"$arg\"" 158 | fi 159 | i=`expr $i + 1` 160 | done 161 | case $i in 162 | 0) set -- ;; 163 | 1) set -- "$args0" ;; 164 | 2) set -- "$args0" "$args1" ;; 165 | 3) set -- "$args0" "$args1" "$args2" ;; 166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;; 167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 172 | esac 173 | fi 174 | 175 | # Escape application args 176 | save () { 177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 178 | echo " " 179 | } 180 | APP_ARGS=`save "$@"` 181 | 182 | # Collect all arguments for the java command, following the shell quoting and substitution rules 183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 184 | 185 | exec "$JAVACMD" "$@" 186 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /library/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /library/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.library' 3 | id 'kotlin-android' 4 | } 5 | 6 | android { 7 | compileSdk 35 8 | 9 | defaultConfig { 10 | minSdk 21 11 | targetSdk 31 12 | 13 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 14 | consumerProguardFiles "consumer-rules.pro" 15 | } 16 | 17 | buildTypes { 18 | release { 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | buildFeatures { 24 | compose true 25 | } 26 | composeOptions { 27 | kotlinCompilerExtensionVersion = "1.5.4" 28 | } 29 | kotlinOptions { 30 | jvmTarget = '1.8' 31 | } 32 | namespace 'com.peakmain.compose.library' 33 | } 34 | 35 | dependencies { 36 | api platform('androidx.compose:compose-bom:2023.10.01') 37 | 38 | // 按需引入组件(无需指定版本) 39 | api 'androidx.compose.ui:ui' 40 | api 'androidx.compose.material3:material3' 41 | api 'androidx.compose.foundation:foundation' 42 | api "androidx.compose.ui:ui-tooling:1.5.4" 43 | api "androidx.constraintlayout:constraintlayout-compose:1.0.0" 44 | api ("io.coil-kt:coil-compose:2.4.0") 45 | api ("io.coil-kt:coil-svg:2.4.0") 46 | api ("io.coil-kt:coil-gif:2.4.0") 47 | 48 | def accompanist_version = "0.33.1-alpha" 49 | api "com.google.accompanist:accompanist-systemuicontroller:${accompanist_version}" 50 | //api "com.google.accompanist:accompanist-insets:$accompanist_version" 51 | api "com.google.accompanist:accompanist-pager:${accompanist_version}" 52 | api "com.google.accompanist:accompanist-pager-indicators:${accompanist_version}" 53 | 54 | } -------------------------------------------------------------------------------- /library/consumer-rules.pro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Peakmain/ComposeUI/130ddea901c25d528b4a130ba2c6919cb55a8155/library/consumer-rules.pro -------------------------------------------------------------------------------- /library/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /library/src/androidTest/java/com/peakmain/compose/library/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.library 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 22 | assertEquals("com.peakmain.compose.base_library.test", appContext.packageName) 23 | } 24 | } -------------------------------------------------------------------------------- /library/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /library/src/main/java/com/peakmain/compose/basic/BasicColor.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.basic 2 | 3 | import androidx.compose.material.Card 4 | import androidx.compose.ui.graphics.Color 5 | 6 | /** 7 | * author :Peakmain 8 | * createTime:2025/3/31 9 | * mail:2726449200@qq.com 10 | * describe: 11 | */ 12 | 13 | /** 14 | * 不透明度 (Opacity) 与十六进制 (Hex) 对照表 15 | * 16 | * 不透明度 (%) | 十六进制 (Hex) | 不透明度 (%) | 十六进制 (Hex) | 不透明度 (%) | 十六进制 (Hex) 17 | * --------------------------------------------------------------------------------------------- 18 | * 0% | 00 | 34% | 57 | 68% | AC 19 | * 1% | 03 | 35% | 5A | 69% | AE 20 | * 2% | 05 | 36% | 5C | 70% | B2 21 | * 3% | 08 | 37% | 5F | 71% | B5 22 | * 4% | 0A | 38% | 61 | 72% | B7 23 | * 5% | 0D | 39% | 63 | 73% | BA 24 | * 6% | 0F | 40% | 66 | 74% | BC 25 | * 7% | 12 | 41% | 68 | 75% | BF 26 | * 8% | 14 | 42% | 6B | 76% | C1 27 | * 9% | 17 | 43% | 6D | 77% | C4 28 | * 10% | 1A | 44% | 70 | 78% | C6 29 | * 11% | 1C | 45% | 73 | 79% | C9 30 | * 12% | 1F | 46% | 75 | 80% | CC 31 | * 13% | 21 | 47% | 78 | 81% | CE 32 | * 14% | 24 | 48% | 7A | 82% | D1 33 | * 15% | 26 | 49% | 7D | 83% | D3 34 | * 16% | 29 | 50% | 80 | 84% | D6 35 | * 17% | 2B | 51% | 83 | 85% | D9 36 | * 18% | 2E | 52% | 85 | 86% | DB 37 | * 19% | 30 | 53% | 88 | 87% | DE 38 | * 20% | 33 | 54% | 8A | 88% | E0 39 | * 21% | 36 | 55% | 8D | 89% | E3 40 | * 22% | 38 | 56% | 8F | 90% | E6 41 | * 23% | 3B | 57% | 92 | 91% | E8 42 | * 24% | 3D | 58% | 94 | 92% | EB 43 | * 25% | 40 | 59% | 97 | 93% | ED 44 | * 26% | 42 | 60% | 99 | 94% | F0 45 | * 27% | 45 | 61% | 9C | 95% | F2 46 | * 28% | 47 | 62% | 9E | 96% | F5 47 | * 29% | 4A | 63% | A1 | 97% | F7 48 | * 30% | 4D | 64% | A3 | 98% | FA 49 | * 31% | 4F | 65% | A6 | 99% | FC 50 | * 32% | 52 | 66% | A8 | 100% | FF 51 | * 33% | 54 | 67% | AB 52 | */ 53 | object BasicColor { 54 | val color_80cbc4 = Color(0xFF80CBC4) 55 | val color_212121 = Color(0xFF212121) 56 | val color_FFFFFF = Color(0xFFFFFFFF) 57 | val color_E1F1EB = Color(0xFFE1F1EB) 58 | val color_EFF2F4 = Color(0xFFEFF2F4) 59 | 60 | 61 | val color_FFFFFF_80 = Color(0xCCFFFFFF) 62 | val color_FFFFFF_50 = Color(0x80FFFFFF) 63 | 64 | val color_E2263D = Color(0xFFE2263D) 65 | val color_0076ff = Color(0xFF0076FF) 66 | val color_FF5368 = Color(0xFFFF5368) 67 | val color_40BE65 = Color(0xFF40BE65) 68 | val color_80E56A54 = Color(0x80E56A54) 69 | val color_00FFFFFF =Color(0x00FFFFFF) 70 | val color_FFF3F3F3=Color(0xFFF3F3F3) 71 | val color_FF000000=Color(0xFF000000) 72 | 73 | val color_F7F7F7_80 = Color(0xCCF7F7F7) 74 | val color_ECECE080 = Color(0xECECE080) 75 | val color_000000_60 = Color(0x99000000) 76 | val color_ECECE0B3 = Color(0xB3ECECE0) 77 | 78 | val color_1F401B_15 = Color(0x261F401B) 79 | 80 | val color_333333 = Color(0xFF333333) 81 | val color_666666 = Color(0xFF666666) 82 | val color_9D9C96 = Color(0xFF9D9C96) 83 | val color_D4D4D5 = Color(0xFFD4D4D5) 84 | val color_EBEBF0 = Color(0xFFEBEBF0) 85 | val color_F8F9F3= Color(0xFFF8F9F3) 86 | val color_9D9C96_10 = Color(0x1A9D9C96) 87 | val color_FFFEFA= Color(0xFFFFFEFA) 88 | 89 | val color_B9824C=Color(0xFFB9824C) 90 | val color_A5534D=Color(0xFFA5534D) 91 | val color_67696a=Color(0xFF67696a) 92 | val color_272A2B=Color(0xFF272A2B) 93 | 94 | val color_1F401B=Color(0xFF1F401B) 95 | val color_677C64=Color(0xFF677C64) 96 | val color_B59E6D=Color(0xFFB59E6D) 97 | val color_DDCC9E=Color(0xFFDDCC9E) 98 | val color_126E82=Color(0xFF126E82) 99 | val color_F2F3EC=Color(0xFFF2F3EC) 100 | 101 | } -------------------------------------------------------------------------------- /library/src/main/java/com/peakmain/compose/basic/BasicFont.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.basic 2 | import androidx.compose.ui.unit.sp 3 | 4 | /** 5 | * author :Peakmain 6 | * createTime:2025/3/31 7 | * mail:2726449200@qq.com 8 | * describe: 9 | */ 10 | 11 | object BasicFont { 12 | val font_1 = 1.sp 13 | val font_2 = 2.sp 14 | val font_3 = 3.sp 15 | val font_4 = 4.sp 16 | val font_5 = 5.sp 17 | val font_6 = 6.sp 18 | val font_7 = 7.sp 19 | val font_8 = 8.sp 20 | val font_9 = 9.sp 21 | val font_10 = 10.sp 22 | val font_11 = 11.sp 23 | val font_12 = 12.sp 24 | val font_13 = 13.sp 25 | val font_14 = 14.sp 26 | val font_15 = 15.sp 27 | val font_16 = 16.sp 28 | val font_17 = 17.sp 29 | val font_18 = 18.sp 30 | val font_19 = 19.sp 31 | val font_20 = 20.sp 32 | val font_21 = 21.sp 33 | val font_22 = 22.sp 34 | val font_23 = 23.sp 35 | val font_24 = 24.sp 36 | val font_25 = 25.sp 37 | val font_26 = 26.sp 38 | val font_27 = 27.sp 39 | val font_28 = 28.sp 40 | val font_29 = 29.sp 41 | val font_30 = 30.sp 42 | val font_31 = 31.sp 43 | val font_32 = 32.sp 44 | val font_33 = 33.sp 45 | val font_34 = 34.sp 46 | val font_35 = 35.sp 47 | val font_36 = 36.sp 48 | val font_37 = 37.sp 49 | val font_38 = 38.sp 50 | val font_39 = 39.sp 51 | val font_40 = 40.sp 52 | val font_41 = 41.sp 53 | val font_42 = 42.sp 54 | val font_43 = 43.sp 55 | val font_44 = 44.sp 56 | val font_45 = 45.sp 57 | val font_46 = 46.sp 58 | val font_47 = 47.sp 59 | val font_48 = 48.sp 60 | val font_49 = 49.sp 61 | val font_50 = 50.sp 62 | val font_51 = 51.sp 63 | val font_52 = 52.sp 64 | val font_53 = 53.sp 65 | val font_54 = 54.sp 66 | val font_55 = 55.sp 67 | val font_56 = 56.sp 68 | val font_57 = 57.sp 69 | val font_58 = 58.sp 70 | val font_59 = 59.sp 71 | val font_60 = 60.sp 72 | val font_61 = 61.sp 73 | val font_62 = 62.sp 74 | val font_63 = 63.sp 75 | val font_64 = 64.sp 76 | val font_65 = 65.sp 77 | val font_66 = 66.sp 78 | val font_67 = 67.sp 79 | val font_68 = 68.sp 80 | val font_69 = 69.sp 81 | val font_70 = 70.sp 82 | val font_71 = 71.sp 83 | val font_72 = 72.sp 84 | val font_73 = 73.sp 85 | val font_74 = 74.sp 86 | val font_75 = 75.sp 87 | val font_76 = 76.sp 88 | val font_77 = 77.sp 89 | val font_78 = 78.sp 90 | val font_79 = 79.sp 91 | val font_80 = 80.sp 92 | val font_81 = 81.sp 93 | val font_82 = 82.sp 94 | val font_83 = 83.sp 95 | val font_84 = 84.sp 96 | val font_85 = 85.sp 97 | val font_86 = 86.sp 98 | val font_87 = 87.sp 99 | val font_88 = 88.sp 100 | val font_89 = 89.sp 101 | val font_90 = 90.sp 102 | val font_91 = 91.sp 103 | val font_92 = 92.sp 104 | val font_93 = 93.sp 105 | val font_94 = 94.sp 106 | val font_95 = 95.sp 107 | val font_96 = 96.sp 108 | val font_97 = 97.sp 109 | val font_98 = 98.sp 110 | val font_99 = 99.sp 111 | val font_100 = 100.sp 112 | } 113 | -------------------------------------------------------------------------------- /library/src/main/java/com/peakmain/compose/basic/BasicRadius.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.basic 2 | 3 | import androidx.compose.ui.unit.dp 4 | 5 | /** 6 | * author :Peakmain 7 | * createTime:2025/3/31 8 | * mail:2726449200@qq.com 9 | * describe: 10 | */ 11 | object BasicRadius { 12 | val radius_0 = 0.dp 13 | val radius_1 = 1.dp 14 | val radius_2 = 2.dp 15 | val radius_3 = 3.dp 16 | val radius_4 = 4.dp 17 | val radius_5 = 5.dp 18 | val radius_6 = 6.dp 19 | val radius_7 = 7.dp 20 | val radius_8 = 8.dp 21 | val radius_9 = 9.dp 22 | val radius_10 = 10.dp 23 | val radius_11 = 11.dp 24 | val radius_12 = 12.dp 25 | val radius_larger = 888.dp 26 | val radius_circle = 999.dp 27 | } -------------------------------------------------------------------------------- /library/src/main/java/com/peakmain/compose/basic/BasicSize.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.basic 2 | 3 | import androidx.compose.ui.unit.dp 4 | 5 | 6 | object BasicSize { 7 | val size_0= 0.dp 8 | val size_0_5 = 0.5.dp 9 | val size_1 = 1.dp 10 | val size_2 = 2.dp 11 | val size_3 = 3.dp 12 | val size_4 = 4.dp 13 | val size_5 = 5.dp 14 | val size_6 = 6.dp 15 | val size_7 = 7.dp 16 | val size_8 = 8.dp 17 | val size_9 = 9.dp 18 | val size_10 = 10.dp 19 | val size_11 = 11.dp 20 | val size_12 = 12.dp 21 | val size_13 = 13.dp 22 | val size_14 = 14.dp 23 | val size_15 = 15.dp 24 | val size_16 = 16.dp 25 | val size_17 = 17.dp 26 | val size_18 = 18.dp 27 | val size_19 = 19.dp 28 | val size_20 = 20.dp 29 | val size_21 = 21.dp 30 | val size_22 = 22.dp 31 | val size_23 = 23.dp 32 | val size_24 = 24.dp 33 | val size_25 = 25.dp 34 | val size_26 = 26.dp 35 | val size_27 = 27.dp 36 | val size_28 = 28.dp 37 | val size_29 = 29.dp 38 | val size_30 = 30.dp 39 | val size_31 = 31.dp 40 | val size_32 = 32.dp 41 | val size_33 = 33.dp 42 | val size_34 = 34.dp 43 | val size_35 = 35.dp 44 | val size_36 = 36.dp 45 | val size_37 = 37.dp 46 | val size_38 = 38.dp 47 | val size_39 = 39.dp 48 | val size_40 = 40.dp 49 | val size_41 = 41.dp 50 | val size_42 = 42.dp 51 | val size_43 = 43.dp 52 | val size_44 = 44.dp 53 | val size_45 = 45.dp 54 | val size_46 = 46.dp 55 | val size_47 = 47.dp 56 | val size_48 = 48.dp 57 | val size_49 = 49.dp 58 | val size_50 = 50.dp 59 | val size_51 = 51.dp 60 | val size_52 = 52.dp 61 | val size_53 = 53.dp 62 | val size_54 = 54.dp 63 | val size_55 = 55.dp 64 | val size_56 = 56.dp 65 | val size_57 = 57.dp 66 | val size_58 = 58.dp 67 | val size_59 = 59.dp 68 | val size_60 = 60.dp 69 | val size_61 = 61.dp 70 | val size_62 = 62.dp 71 | val size_63 = 63.dp 72 | val size_64 = 64.dp 73 | val size_65 = 65.dp 74 | val size_66 = 66.dp 75 | val size_67 = 67.dp 76 | val size_68 = 68.dp 77 | val size_69 = 69.dp 78 | val size_70 = 70.dp 79 | val size_71 = 71.dp 80 | val size_72 = 72.dp 81 | val size_73 = 73.dp 82 | val size_74 = 74.dp 83 | val size_75 = 75.dp 84 | val size_76 = 76.dp 85 | val size_77 = 77.dp 86 | val size_78 = 78.dp 87 | val size_79 = 79.dp 88 | val size_80 = 80.dp 89 | val size_81 = 81.dp 90 | val size_82 = 82.dp 91 | val size_83 = 83.dp 92 | val size_84 = 84.dp 93 | val size_85 = 85.dp 94 | val size_86 = 86.dp 95 | val size_87 = 87.dp 96 | val size_88 = 88.dp 97 | val size_89 = 89.dp 98 | val size_90 = 90.dp 99 | val size_91 = 91.dp 100 | val size_92 = 92.dp 101 | val size_93 = 93.dp 102 | val size_94 = 94.dp 103 | val size_95 = 95.dp 104 | val size_96 = 96.dp 105 | val size_97 = 97.dp 106 | val size_98 = 98.dp 107 | val size_99 = 99.dp 108 | val size_100 = 100.dp 109 | } 110 | -------------------------------------------------------------------------------- /library/src/main/java/com/peakmain/compose/basic/BasicSpace.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.basic 2 | 3 | import androidx.compose.ui.unit.dp 4 | 5 | /** 6 | * author :Peakmain 7 | * createTime:2025/3/31 8 | * mail:2726449200@qq.com 9 | * describe: 10 | */ 11 | object BasicSpace { 12 | val space_neg_8 = (-8).dp 13 | val space_neg_7 = (-7).dp 14 | val space_neg_6 = (-6).dp 15 | val space_neg_5 = (-5).dp 16 | val space_neg_4 = (-4).dp 17 | val space_neg_3 = (-3).dp 18 | val space_neg_2 = (-2).dp 19 | val space_neg_1 = (-1).dp 20 | val space_0 = 0.dp 21 | val space_1 = 1.dp 22 | val space_2 = 2.dp 23 | val space_3 = 3.dp 24 | val space_4 = 4.dp 25 | val space_5 = 5.dp 26 | val space_6 = 6.dp 27 | val space_7 = 7.dp 28 | val space_8 = 8.dp 29 | val space_9 = 9.dp 30 | val space_10 = 10.dp 31 | val space_11 = 11.dp 32 | val space_12 = 12.dp 33 | val space_13 = 13.dp 34 | val space_14 = 14.dp 35 | val space_15 = 15.dp 36 | val space_16 = 16.dp 37 | val space_17 = 17.dp 38 | val space_18 = 18.dp 39 | val space_19 = 19.dp 40 | val space_20 = 20.dp 41 | val space_21 = 21.dp 42 | val space_22 = 22.dp 43 | val space_23 = 23.dp 44 | val space_24 = 24.dp 45 | val space_25 = 25.dp 46 | val space_26 = 26.dp 47 | val space_27 = 27.dp 48 | val space_28 = 28.dp 49 | val space_29 = 29.dp 50 | val space_30 = 30.dp 51 | val space_31 = 31.dp 52 | val space_32 = 32.dp 53 | val space_33 = 33.dp 54 | val space_34 = 34.dp 55 | val space_35 = 35.dp 56 | val space_36 = 36.dp 57 | val space_37 = 37.dp 58 | val space_38 = 38.dp 59 | val space_39 = 39.dp 60 | val space_40 = 40.dp 61 | val space_41 = 41.dp 62 | val space_42 = 42.dp 63 | val space_43 = 43.dp 64 | val space_44 = 44.dp 65 | val space_45 = 45.dp 66 | val space_46 = 46.dp 67 | val space_47 = 47.dp 68 | val space_48 = 48.dp 69 | val space_49 = 49.dp 70 | val space_50 = 50.dp 71 | val space_51 = 51.dp 72 | val space_52 = 52.dp 73 | val space_53 = 53.dp 74 | val space_54 = 54.dp 75 | val space_55 = 55.dp 76 | val space_56 = 56.dp 77 | val space_57 = 57.dp 78 | val space_58 = 58.dp 79 | val space_59 = 59.dp 80 | val space_60 = 60.dp 81 | val space_61 = 61.dp 82 | val space_62 = 62.dp 83 | val space_63 = 63.dp 84 | val space_64 = 64.dp 85 | val space_65 = 65.dp 86 | val space_66 = 66.dp 87 | val space_67 = 67.dp 88 | val space_68 = 68.dp 89 | val space_69 = 69.dp 90 | val space_70 = 70.dp 91 | val space_71 = 71.dp 92 | val space_72 = 72.dp 93 | val space_73 = 73.dp 94 | val space_74 = 74.dp 95 | val space_75 = 75.dp 96 | val space_76 = 76.dp 97 | val space_77 = 77.dp 98 | val space_78 = 78.dp 99 | val space_79 = 79.dp 100 | val space_80 = 80.dp 101 | val space_81 = 81.dp 102 | val space_82 = 82.dp 103 | val space_83 = 83.dp 104 | val space_84 = 84.dp 105 | val space_85 = 85.dp 106 | val space_86 = 86.dp 107 | val space_87 = 87.dp 108 | val space_88 = 88.dp 109 | val space_89 = 89.dp 110 | val space_90 = 90.dp 111 | val space_91 = 91.dp 112 | val space_92 = 92.dp 113 | val space_93 = 93.dp 114 | val space_94 = 94.dp 115 | val space_95 = 95.dp 116 | val space_96 = 96.dp 117 | val space_97 = 97.dp 118 | val space_98 = 98.dp 119 | val space_99 = 99.dp 120 | val space_100 = 100.dp 121 | } 122 | -------------------------------------------------------------------------------- /library/src/main/java/com/peakmain/compose/ext/IntExt.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.ext 2 | 3 | /** 4 | * author :Peakmain 5 | * createTime:2022/5/5 6 | * mail:2726449200@qq.com 7 | * describe: 8 | */ 9 | fun Int.floorMod(other: Int): Int = when (other) { 10 | 0 -> this 11 | else -> this - floorDiv(other) * other 12 | } -------------------------------------------------------------------------------- /library/src/main/java/com/peakmain/compose/ext/ListExt.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.ext 2 | 3 | 4 | /** 5 | * author :Peakmain 6 | * createTime:2025/3/11 7 | * mail:2726449200@qq.com 8 | * describe:List扩展类 9 | */ 10 | /** 11 | * 获取List的大小 12 | * ①、如果List为null,则返回0。 13 | * ②、如果List不为null,则返回size 14 | */ 15 | fun List?.orSize(): Int { 16 | return this?.size ?: return 0 17 | } 18 | /** 19 | * 判断List大小是否大于0 20 | * ①、如果List为null,则返回false。 21 | * ②、如果List不为null,则判断大小是否大于0 22 | */ 23 | fun List?.sizeBigZero(): Boolean { 24 | return (this?.size ?: 0) > 0 25 | } 26 | 27 | /** 28 | * List的大小是否为0 29 | * ①、如果List为null,则返回true。 30 | * ②、如果List不为null,则判断大小是否等于0 31 | */ 32 | fun List?.sizeEqualZero(): Boolean { 33 | return (this?.size ?: 0) == 0 34 | } 35 | 36 | /** 37 | * 返回此列表中指定[fromIndex](包含)和[toIndex](不包含)之间部分的视图 38 | */ 39 | fun List?.slice(fromIndex: Int, toIndex: Int): List? { 40 | return if (this.orSize() > (toIndex-fromIndex)) this?.subList(fromIndex, toIndex) else this 41 | } -------------------------------------------------------------------------------- /library/src/main/java/com/peakmain/compose/ext/StringExt.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.ext 2 | 3 | import android.text.TextUtils 4 | import androidx.compose.runtime.Composable 5 | 6 | /** 7 | * author :Peakmain 8 | * createTime:2025/4/29 9 | * mail:2726449200@qq.com 10 | * describe:字符串工具类 11 | */ 12 | fun String?.isEmpty(): Boolean { 13 | return TextUtils.isEmpty(this) 14 | } 15 | fun String?.isEmpty(block: () -> Unit): String? { 16 | if(isEmpty()){ 17 | block.invoke() 18 | } 19 | return this 20 | } 21 | fun String?.isNotEmpty(): Boolean { 22 | return !isEmpty() 23 | } 24 | 25 | fun String?.isNotEmpty(block: ((String)) -> Unit): String? { 26 | if (isNotEmpty()) { 27 | block.invoke(this!!) 28 | } 29 | return this 30 | } 31 | @Composable 32 | fun String?.isNotEmptyComposable(block: @Composable ((String)) -> Unit): String? { 33 | if (isNotEmpty()) { 34 | block.invoke(this!!) 35 | } 36 | return this 37 | } 38 | -------------------------------------------------------------------------------- /library/src/main/java/com/peakmain/compose/library/TopAppBar.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.library 2 | 3 | import android.graphics.Color.luminance 4 | import androidx.compose.foundation.background 5 | import androidx.compose.foundation.layout.* 6 | import androidx.compose.material.* 7 | import androidx.compose.material3.CenterAlignedTopAppBar 8 | import androidx.compose.runtime.Composable 9 | import androidx.compose.runtime.CompositionLocalProvider 10 | import androidx.compose.runtime.SideEffect 11 | import androidx.compose.ui.Modifier 12 | import androidx.compose.ui.graphics.Color 13 | import androidx.compose.ui.graphics.luminance 14 | import androidx.compose.ui.layout.layoutId 15 | import androidx.compose.ui.platform.LocalContext 16 | import androidx.compose.ui.platform.LocalDensity 17 | import androidx.compose.ui.unit.Dp 18 | import androidx.compose.ui.unit.dp 19 | import androidx.constraintlayout.compose.ConstraintLayout 20 | import androidx.constraintlayout.compose.ConstraintSet 21 | import com.google.accompanist.systemuicontroller.rememberSystemUiController 22 | 23 | /** 24 | * author :Peakmain 25 | * createTime:2022/5/4 26 | * mail:2726449200@qq.com 27 | * describe: 28 | */ 29 | 30 | /** 31 | * @param title 标题 32 | * @param modifier Modifier,设置后会和已经设置好Modifier进行合并 33 | * @param navigationIcon 左边图标 34 | * @param backgroundColor 背景颜色 35 | * @param actions 右边图标 36 | * @param isImmersive 是否是沉浸式 37 | * @param darkIcons 状态栏的文字图标颜色是黑色还是白色,默认是false(白色) 38 | * @param content 内容区域 39 | */ 40 | @Composable 41 | fun TopAppBarCenter( 42 | title: @Composable () -> Unit, 43 | modifier: Modifier = Modifier, 44 | navigationIcon: @Composable (() -> Unit)? = null, 45 | backgroundColor: Color = MaterialTheme.colors.primarySurface, 46 | actions: @Composable RowScope.() -> Unit = {}, 47 | isImmersive: Boolean = false, 48 | darkIcons: Boolean = false, 49 | content: @Composable (PaddingValues) -> Unit, 50 | ) { 51 | val topAppBarHeight = 44.dp 52 | if (isImmersive) { 53 | val systemUiController = rememberSystemUiController() 54 | SideEffect { 55 | systemUiController.setSystemBarsColor( 56 | color = Color.Transparent, 57 | darkIcons = darkIcons 58 | ) 59 | } 60 | } 61 | 62 | Scaffold(topBar = { 63 | val constraintSet = ConstraintSet { 64 | val titleRef = createRefFor("title") 65 | val navigationIconRef = createRefFor("navigationIcon") 66 | val actionsRef = createRefFor("actions") 67 | constrain(titleRef) { 68 | start.linkTo(parent.start) 69 | end.linkTo(parent.end) 70 | top.linkTo(parent.top) 71 | bottom.linkTo(parent.bottom) 72 | } 73 | constrain(navigationIconRef) { 74 | top.linkTo(parent.top) 75 | bottom.linkTo(parent.bottom) 76 | } 77 | constrain(actionsRef) { 78 | top.linkTo(parent.top) 79 | bottom.linkTo(parent.bottom) 80 | end.linkTo(parent.end) 81 | } 82 | } 83 | ConstraintLayout(constraintSet, modifier = Modifier 84 | .fillMaxWidth() 85 | .background(backgroundColor) 86 | .then(modifier.statusBarsPadding()) 87 | .height(topAppBarHeight) 88 | ) { 89 | Box( 90 | Modifier 91 | .layoutId("title") 92 | .padding(horizontal = 4.dp) 93 | ) { 94 | ProvideTextStyle(value = MaterialTheme.typography.h6) { 95 | CompositionLocalProvider( 96 | LocalContentAlpha provides ContentAlpha.high, 97 | content = title 98 | ) 99 | } 100 | } 101 | if (navigationIcon != null) { 102 | Box(modifier = Modifier 103 | .layoutId("navigationIcon") 104 | .padding(start = 4.dp)) { 105 | CompositionLocalProvider( 106 | LocalContentAlpha provides ContentAlpha.high, 107 | content = navigationIcon 108 | ) 109 | } 110 | } 111 | Row( 112 | Modifier 113 | .layoutId("actions") 114 | .padding(end = 4.dp), 115 | content = actions 116 | ) 117 | } 118 | }) { 119 | content(it) 120 | } 121 | 122 | } 123 | -------------------------------------------------------------------------------- /library/src/main/java/com/peakmain/compose/space/PkSpacer.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.space 2 | 3 | import androidx.compose.foundation.layout.Spacer 4 | import androidx.compose.foundation.layout.fillMaxHeight 5 | import androidx.compose.foundation.layout.fillMaxWidth 6 | import androidx.compose.foundation.layout.height 7 | import androidx.compose.foundation.layout.width 8 | import androidx.compose.runtime.Composable 9 | import androidx.compose.ui.Modifier 10 | import androidx.compose.ui.unit.Dp 11 | import androidx.compose.ui.unit.dp 12 | 13 | /** 14 | * author :Peakmain 15 | * createTime:2025/6/23 16 | * mail:2726449200@qq.com 17 | * describe: 18 | */ 19 | @Composable 20 | fun PkSpacer( 21 | modifier: Modifier = Modifier, 22 | width: Dp = 10.dp, 23 | height: Dp = 10.dp, 24 | isHorizontal: Boolean = true 25 | ) { 26 | if (isHorizontal) { 27 | return PkHorizontalSpacer(modifier, height) 28 | } else { 29 | PkVerticalSpacer(modifier, width) 30 | } 31 | } 32 | 33 | @Composable 34 | fun PkVerticalSpacer(modifier: Modifier = Modifier, width: Dp) { 35 | Spacer(modifier 36 | .width(width) 37 | .fillMaxHeight()) 38 | } 39 | 40 | @Composable 41 | fun PkHorizontalSpacer(modifier: Modifier = Modifier, height: Dp) { 42 | Spacer(modifier 43 | .height(height) 44 | .fillMaxWidth()) 45 | } 46 | -------------------------------------------------------------------------------- /library/src/main/java/com/peakmain/compose/theme/PkColors.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.theme 2 | 3 | import androidx.compose.material.Colors 4 | import androidx.compose.runtime.staticCompositionLocalOf 5 | import androidx.compose.ui.graphics.Color 6 | 7 | /** 8 | * author :Peakmain 9 | * createTime:2025/4/10 10 | * mail:2726449200@qq.com 11 | * describe: 12 | */ 13 | val color_FFFEFA=Color(0xFFFFFEFA) 14 | val error_A5534D= Color(0xFFA5534D) 15 | 16 | fun pkColors( 17 | primary: Color = Color(0xFF1F401B), 18 | primaryVariant: Color = Color(0xB21F401B), 19 | secondary: Color = Color(0xFFB59E6D),//辅色 20 | secondaryVariant: Color = Color(0xFFDDCC9E), 21 | background: Color = Color(0xFFF8F9F3), 22 | surface: Color = color_FFFEFA, 23 | error: Color =error_A5534D, 24 | onPrimary: Color = color_FFFEFA, 25 | onSecondary: Color = Color(0xFF666666),//次要按钮上的文字颜色 26 | onBackground: Color =Color(0xFF333333),//背景颜色上的字体颜色 27 | onSurface: Color = Color(0xFF333333),//卡片上文字颜色 28 | onError: Color = color_FFFEFA,//错误上的文字颜色 29 | ): Colors = Colors( 30 | primary, 31 | primaryVariant, 32 | secondary, 33 | secondaryVariant, 34 | background, 35 | surface, 36 | error, 37 | onPrimary, 38 | onSecondary, 39 | onBackground, 40 | onSurface, 41 | onError, 42 | true 43 | ) 44 | internal val LocalPkColors = staticCompositionLocalOf { pkColors() } -------------------------------------------------------------------------------- /library/src/main/java/com/peakmain/compose/theme/PkIndication.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.theme 2 | 3 | import androidx.compose.foundation.Indication 4 | import androidx.compose.foundation.IndicationInstance 5 | import androidx.compose.foundation.interaction.InteractionSource 6 | import androidx.compose.foundation.interaction.collectIsFocusedAsState 7 | import androidx.compose.foundation.interaction.collectIsHoveredAsState 8 | import androidx.compose.foundation.interaction.collectIsPressedAsState 9 | import androidx.compose.runtime.Composable 10 | import androidx.compose.runtime.State 11 | import androidx.compose.runtime.remember 12 | import androidx.compose.ui.graphics.Color 13 | import androidx.compose.ui.graphics.drawscope.ContentDrawScope 14 | 15 | /** 16 | * author :Peakmain 17 | * createTime:2025/4/22 18 | * mail:2726449200@qq.com 19 | * describe: 20 | */ 21 | open class PkIndication(private val drawColor: Color = Color.Black.copy(0.3f)) : Indication { 22 | 23 | private class DefaultDebugIndicationInstance( 24 | private val isPressed: State, 25 | private val isHovered: State, 26 | private val isFocused: State, 27 | private val drawColor: Color, 28 | ) : IndicationInstance { 29 | override fun ContentDrawScope.drawIndication() { 30 | drawContent() 31 | if (isPressed.value) { 32 | drawRect(color = drawColor, size = size) 33 | } else if (isHovered.value || isFocused.value) { 34 | drawRect(color = drawColor, size = size) 35 | } 36 | } 37 | } 38 | 39 | @Composable 40 | override fun rememberUpdatedInstance(interactionSource: InteractionSource): IndicationInstance { 41 | val isPressed = interactionSource.collectIsPressedAsState() 42 | val isHovered = interactionSource.collectIsHoveredAsState() 43 | val isFocused = interactionSource.collectIsFocusedAsState() 44 | return remember(interactionSource) { 45 | DefaultDebugIndicationInstance(isPressed, isHovered, isFocused, drawColor) 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /library/src/main/java/com/peakmain/compose/theme/PkTheme.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.theme 2 | 3 | import androidx.compose.material.Colors 4 | import androidx.compose.runtime.Composable 5 | import androidx.compose.runtime.ReadOnlyComposable 6 | import com.peakmain.compose.ui.button.LocalPkShapes 7 | import com.peakmain.compose.ui.button.PkShapes 8 | 9 | /** 10 | * author :Peakmain 11 | * createTime:2025/4/10 12 | * mail:2726449200@qq.com 13 | * describe: 14 | */ 15 | object PkTheme { 16 | val colors: Colors 17 | @Composable 18 | @ReadOnlyComposable 19 | get() = LocalPkColors.current 20 | 21 | val shapes: PkShapes 22 | @Composable 23 | @ReadOnlyComposable 24 | get() = LocalPkShapes.current 25 | } -------------------------------------------------------------------------------- /library/src/main/java/com/peakmain/compose/theme/PkTranslateIndication.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.theme 2 | 3 | import androidx.compose.foundation.IndicationInstance 4 | import androidx.compose.foundation.interaction.InteractionSource 5 | import androidx.compose.foundation.interaction.collectIsFocusedAsState 6 | import androidx.compose.foundation.interaction.collectIsHoveredAsState 7 | import androidx.compose.foundation.interaction.collectIsPressedAsState 8 | import androidx.compose.runtime.Composable 9 | import androidx.compose.runtime.State 10 | import androidx.compose.runtime.remember 11 | import androidx.compose.ui.graphics.Color 12 | import androidx.compose.ui.graphics.drawscope.ContentDrawScope 13 | 14 | /** 15 | * author :Peakmain 16 | * createTime:2025/4/22 17 | * mail:2726449200@qq.com 18 | * describe:透明 19 | */ 20 | object PkTranslateIndication : PkIndication() { 21 | 22 | private class DefaultDebugIndicationInstance( 23 | private val isPressed: State, 24 | private val isHovered: State, 25 | private val isFocused: State, 26 | ) : IndicationInstance { 27 | override fun ContentDrawScope.drawIndication() { 28 | drawContent() 29 | if (isPressed.value) { 30 | drawRect(color = Color.Transparent, size = size) 31 | } else if (isHovered.value || isFocused.value) { 32 | drawRect(color = Color.Transparent, size = size) 33 | } 34 | } 35 | } 36 | 37 | @Composable 38 | override fun rememberUpdatedInstance(interactionSource: InteractionSource): IndicationInstance { 39 | val isPressed = interactionSource.collectIsPressedAsState() 40 | val isHovered = interactionSource.collectIsHoveredAsState() 41 | val isFocused = interactionSource.collectIsFocusedAsState() 42 | return remember(interactionSource) { 43 | DefaultDebugIndicationInstance(isPressed, isHovered, isFocused) 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /library/src/main/java/com/peakmain/compose/ui/PkGridLayout.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.ui 2 | 3 | import androidx.annotation.IntRange 4 | import androidx.compose.foundation.layout.Arrangement 5 | import androidx.compose.foundation.layout.Box 6 | import androidx.compose.foundation.layout.Column 7 | import androidx.compose.foundation.layout.Row 8 | import androidx.compose.foundation.layout.Spacer 9 | import androidx.compose.material.TabRowDefaults.Divider 10 | import androidx.compose.runtime.Composable 11 | import androidx.compose.ui.Modifier 12 | import androidx.compose.ui.unit.Dp 13 | import androidx.compose.ui.unit.dp 14 | 15 | /** 16 | * author :Peakmain 17 | * createTime:2022/2/9 18 | * mail:2726449200@qq.com 19 | * describe:GridLayout的实现 20 | */ 21 | /** 22 | * @param columns 1行几个 23 | * @param data 源数据 24 | * @param isShowHorizontalDivider 是否显示水平分割线,默认不显示 25 | * @param content The content of the GridLayout 26 | */ 27 | @Composable 28 | fun PkGridLayout( 29 | @IntRange(from = 1) columns: Int, 30 | data: MutableList, 31 | isShowHorizontalDivider: Boolean = false, 32 | divider: @Composable (() -> Unit)? = null, 33 | columnSpacing: Dp = 12.dp, // 新增参数,表示列间距,默认值为 8.dp 34 | content: @Composable (Int, E) -> Unit 35 | ) { 36 | val size = data.size 37 | val rows = (size + columns - 1) / columns 38 | Column { 39 | for (rowIndex in 0 until rows) { 40 | Row(horizontalArrangement = Arrangement.spacedBy(columnSpacing)) { 41 | for (columnIndex in 0 until columns) { 42 | val itemIndex = rowIndex * columns + columnIndex 43 | if (itemIndex < size) { 44 | Box(Modifier.weight(1f)) { 45 | content(itemIndex, data[itemIndex]) 46 | } 47 | } else { 48 | Spacer( 49 | Modifier 50 | .weight(1f) 51 | ) 52 | } 53 | } 54 | } 55 | if (isShowHorizontalDivider && rowIndex < (rows - 1)) { 56 | if (divider != null) { 57 | divider() 58 | } else { 59 | Divider(thickness = 0.5.dp) 60 | } 61 | } 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /library/src/main/java/com/peakmain/compose/ui/basic/PkColumn.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.ui.basic 2 | 3 | /** 4 | * author :Peakmain 5 | * createTime:2025/6/4 6 | * mail:2726449200@qq.com 7 | * describe: 8 | */ 9 | import androidx.compose.foundation.background 10 | import androidx.compose.foundation.layout.Arrangement 11 | import androidx.compose.foundation.layout.Column 12 | import androidx.compose.foundation.layout.ColumnScope 13 | import androidx.compose.runtime.Composable 14 | import androidx.compose.ui.Alignment 15 | import androidx.compose.ui.Modifier 16 | import androidx.compose.ui.graphics.Color 17 | import androidx.compose.ui.tooling.preview.Preview 18 | 19 | @Composable 20 | inline fun PkColumn( 21 | modifier: Modifier = Modifier, 22 | backgroundColor: Color = Color.White, 23 | verticalArrangement: Arrangement.Vertical = Arrangement.Top, 24 | horizontalAlignment: Alignment.Horizontal = Alignment.Start, 25 | content: @Composable ColumnScope.() -> Unit 26 | ) { 27 | Column( 28 | modifier 29 | .background(backgroundColor), 30 | verticalArrangement, 31 | horizontalAlignment, 32 | content 33 | ) 34 | } 35 | 36 | @Preview 37 | @Composable 38 | fun PkColumnPreview() { 39 | PkColumn() { 40 | 41 | } 42 | } 43 | 44 | -------------------------------------------------------------------------------- /library/src/main/java/com/peakmain/compose/ui/button/PkButton.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.ui.button 2 | 3 | import androidx.compose.foundation.BorderStroke 4 | import androidx.compose.foundation.interaction.MutableInteractionSource 5 | import androidx.compose.foundation.layout.PaddingValues 6 | import androidx.compose.foundation.layout.RowScope 7 | import androidx.compose.material.Button 8 | import androidx.compose.material.ButtonColors 9 | import androidx.compose.material.ButtonDefaults 10 | import androidx.compose.material.ButtonElevation 11 | import androidx.compose.runtime.Composable 12 | import androidx.compose.runtime.remember 13 | import androidx.compose.ui.Modifier 14 | import androidx.compose.ui.graphics.Shape 15 | import com.peakmain.compose.theme.PkTheme 16 | 17 | /** 18 | * author :Peakmain 19 | * createTime:2025/4/10 20 | * mail:2726449200@qq.com 21 | * describe: 22 | */ 23 | /** 24 | * 通用按钮组件,支持自定义样式、交互行为与内容布局。 25 | * 26 | * @param onClick 按钮点击事件回调(必填) 27 | * @param modifier 布局修饰符(如尺寸、边距、背景等),默认 [Modifier] 28 | * @param enabled 是否启用按钮,默认 true;禁用时自动降低透明度并屏蔽点击事件 29 | * @param interactionSource 按钮交互状态源(如按压、悬停),默认 `remember { MutableInteractionSource() }` 30 | * @param elevation 按钮阴影效果,默认 [ButtonDefaults.elevation];设置为 null 可移除阴影 31 | * @param shape 按钮形状,默认 [PkTheme.shapes.small],如 `RoundedCornerShape(4.dp)` 32 | * @param border 按钮边框,默认 null,如 `BorderStroke(1.dp, Color.Gray)` 33 | * @param colors 按钮颜色配置,默认 [PkButtonDefault.buttonColors],包含默认、禁用、按压等状态颜色 34 | * @param contentPadding 内容内边距,默认 [PkButtonDefault.BigContentPadding],即 `PaddingValues(horizontal = 16.dp, vertical = 8.dp)` 35 | * @param content 按钮内部内容(必填),支持 [RowScope],可自由组合文本、图标等 36 | */ 37 | @Composable 38 | fun PkButton( 39 | onClick: () -> Unit, 40 | modifier: Modifier = Modifier, 41 | enabled: Boolean = true, 42 | interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, 43 | elevation: ButtonElevation? = ButtonDefaults.elevation(), 44 | shape: Shape = PkTheme.shapes.small, 45 | border: BorderStroke? = null, 46 | colors: ButtonColors = PkButtonDefault.buttonColors(interactionSource), 47 | contentPadding: PaddingValues = PkButtonDefault.BigContentPadding, 48 | content: @Composable RowScope.() -> Unit 49 | ) { 50 | Button( 51 | onClick, 52 | modifier, 53 | enabled, 54 | interactionSource, 55 | elevation, 56 | shape, 57 | border, 58 | colors, 59 | contentPadding, 60 | ) { 61 | content() 62 | } 63 | } -------------------------------------------------------------------------------- /library/src/main/java/com/peakmain/compose/ui/button/PkButtonDefault.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.ui.button 2 | 3 | import androidx.compose.foundation.interaction.InteractionSource 4 | import androidx.compose.foundation.interaction.MutableInteractionSource 5 | import androidx.compose.foundation.interaction.collectIsPressedAsState 6 | import androidx.compose.foundation.layout.PaddingValues 7 | import androidx.compose.material.Button 8 | import androidx.compose.material.ButtonColors 9 | import androidx.compose.material.SnackbarDefaults.backgroundColor 10 | import androidx.compose.material.contentColorFor 11 | import androidx.compose.runtime.Composable 12 | import androidx.compose.runtime.Immutable 13 | import androidx.compose.runtime.State 14 | import androidx.compose.runtime.getValue 15 | import androidx.compose.runtime.remember 16 | import androidx.compose.runtime.rememberUpdatedState 17 | import androidx.compose.ui.graphics.Color 18 | import androidx.compose.ui.unit.dp 19 | import com.peakmain.compose.theme.PkTheme 20 | 21 | /** 22 | * author :Peakmain 23 | * createTime:2025/4/10 24 | * mail:2726449200@qq.com 25 | * describe: 26 | */ 27 | object PkButtonDefault { 28 | private val ButtonBigHorizontalPadding = 24.dp 29 | private val ButtonBigVerticalPadding = 11.dp 30 | 31 | private val ButtonSmallHorizontalPadding = 12.dp 32 | private val ButtonSmallVerticalPadding = 5.dp 33 | 34 | /** 35 | * The default content padding used by [Button] 36 | */ 37 | val BigContentPadding = PaddingValues( 38 | start = ButtonBigHorizontalPadding, 39 | top = ButtonBigVerticalPadding, 40 | end = ButtonBigHorizontalPadding, 41 | bottom = ButtonBigVerticalPadding 42 | ) 43 | 44 | val smallContentPadding = PaddingValues( 45 | start = ButtonSmallHorizontalPadding, 46 | top = ButtonSmallVerticalPadding, 47 | end = ButtonSmallHorizontalPadding, 48 | bottom = ButtonSmallVerticalPadding 49 | ) 50 | 51 | /** 52 | * 默认 53 | */ 54 | @Composable 55 | fun buttonColors( 56 | interactionSource: InteractionSource = remember { MutableInteractionSource() }, 57 | backgroundColor: Color = PkTheme.colors.primary, 58 | contentColor: Color = PkTheme.colors.contentColorFor(backgroundColor), 59 | disabledBackgroundColor: Color = Color(0xFFD4D4D5), 60 | disabledContentColor: Color = PkTheme.colors.onPrimary, 61 | pressedBackgroundColor: Color = backgroundColor, 62 | pressedContentColor: Color = contentColor 63 | ): ButtonColors = PkButtonColors( 64 | backgroundColor = backgroundColor, 65 | contentColor = contentColor, 66 | disabledBackgroundColor = disabledBackgroundColor, 67 | disabledContentColor = disabledContentColor, 68 | interactionSource = interactionSource, 69 | pressedBackgroundColor = pressedBackgroundColor, 70 | pressedContentColor = pressedContentColor 71 | ) 72 | 73 | /** 74 | * 幽灵按钮 75 | */ 76 | @Composable 77 | fun transparentColor( 78 | interactionSource: InteractionSource = remember { MutableInteractionSource() }, 79 | backgroundColor: Color = Color.Transparent, 80 | contentColor: Color = Color(0xFF1F4D1B), 81 | disabledBackgroundColor: Color = Color(0xFFD4D4D5), 82 | disabledContentColor: Color = Color(0xFF677C64), 83 | pressedBackgroundColor: Color = backgroundColor, 84 | pressedContentColor: Color = contentColor 85 | ): ButtonColors = PkButtonColors( 86 | backgroundColor = backgroundColor, 87 | contentColor = contentColor, 88 | disabledBackgroundColor = disabledBackgroundColor, 89 | disabledContentColor = disabledContentColor, 90 | interactionSource = interactionSource, 91 | pressedBackgroundColor = pressedBackgroundColor, 92 | pressedContentColor = pressedContentColor 93 | ) 94 | 95 | } 96 | 97 | @Immutable 98 | class PkButtonColors( 99 | private val backgroundColor: Color, 100 | private val contentColor: Color, 101 | private val pressedContentColor: Color = contentColor, 102 | private val disabledBackgroundColor: Color, 103 | private val disabledContentColor: Color, 104 | private val interactionSource: InteractionSource, 105 | private val pressedBackgroundColor: Color = backgroundColor.copy(0.8f), 106 | ) : ButtonColors { 107 | @Composable 108 | override fun backgroundColor(enabled: Boolean): State { 109 | val isPressed by interactionSource.collectIsPressedAsState() 110 | val color = when { 111 | !enabled -> disabledBackgroundColor 112 | isPressed -> pressedBackgroundColor 113 | else -> backgroundColor 114 | } 115 | return rememberUpdatedState(color) 116 | } 117 | 118 | @Composable 119 | override fun contentColor(enabled: Boolean): State { 120 | val isPressed by interactionSource.collectIsPressedAsState() 121 | val color = when { 122 | !enabled -> disabledContentColor 123 | isPressed -> pressedContentColor 124 | else -> contentColor 125 | } 126 | return rememberUpdatedState(color) 127 | } 128 | 129 | override fun equals(other: Any?): Boolean { 130 | if (this === other) return true 131 | if (other !is PkButtonColors) return false 132 | 133 | return backgroundColor == other.backgroundColor && 134 | pressedBackgroundColor == other.pressedBackgroundColor && 135 | contentColor == other.contentColor && 136 | pressedContentColor == other.pressedContentColor && 137 | disabledBackgroundColor == other.disabledBackgroundColor && 138 | disabledContentColor == other.disabledContentColor 139 | } 140 | 141 | override fun hashCode(): Int { 142 | var result = backgroundColor.hashCode() 143 | result = 31 * result + pressedBackgroundColor.hashCode() 144 | result = 31 * result + contentColor.hashCode() 145 | result = 31 * result + pressedContentColor.hashCode() 146 | result = 31 * result + disabledBackgroundColor.hashCode() 147 | result = 31 * result + disabledContentColor.hashCode() 148 | return result 149 | } 150 | } -------------------------------------------------------------------------------- /library/src/main/java/com/peakmain/compose/ui/button/PkShapes.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.ui.button 2 | 3 | import androidx.compose.foundation.shape.CornerBasedShape 4 | import androidx.compose.foundation.shape.RoundedCornerShape 5 | import androidx.compose.material.Shapes 6 | import androidx.compose.runtime.Immutable 7 | import androidx.compose.runtime.staticCompositionLocalOf 8 | import androidx.compose.ui.unit.dp 9 | 10 | /** 11 | * author :Peakmain 12 | * createTime:2025/4/10 13 | * mail:2726449200@qq.com 14 | * describe: 15 | */ 16 | 17 | @Immutable 18 | class PkShapes( 19 | val none: CornerBasedShape = RoundedCornerShape(0.dp), 20 | val small: CornerBasedShape = RoundedCornerShape(2.dp), 21 | val medium: CornerBasedShape = RoundedCornerShape(4.dp), 22 | val large: CornerBasedShape = RoundedCornerShape(8.dp), 23 | val extraLarge: CornerBasedShape = RoundedCornerShape(12.dp), 24 | val capsule: CornerBasedShape = RoundedCornerShape(percent = 50), // 胶囊型 25 | val circle: CornerBasedShape = RoundedCornerShape(percent = 50) // 圆形,默认是等宽等高的控件,圆形的效果 26 | ) { 27 | 28 | fun copy( 29 | none: CornerBasedShape = this.none, 30 | small: CornerBasedShape = this.small, 31 | medium: CornerBasedShape = this.medium, 32 | large: CornerBasedShape = this.large, 33 | extraLarge: CornerBasedShape = this.extraLarge, 34 | capsule: CornerBasedShape = this.capsule, 35 | circle: CornerBasedShape = this.circle 36 | ): PkShapes = PkShapes( 37 | none = none, 38 | small = small, 39 | medium = medium, 40 | large = large, 41 | extraLarge = extraLarge, 42 | capsule = capsule, 43 | circle = circle 44 | ) 45 | 46 | override fun equals(other: Any?): Boolean { 47 | if (this === other) return true 48 | if (other !is PkShapes) return false 49 | 50 | if (none != other.none) return false 51 | if (small != other.small) return false 52 | if (medium != other.medium) return false 53 | if (large != other.large) return false 54 | if (extraLarge != other.extraLarge) return false 55 | if (capsule != other.capsule) return false 56 | if (circle != other.circle) return false 57 | 58 | return true 59 | } 60 | 61 | override fun hashCode(): Int { 62 | var result = none.hashCode() 63 | result = 31 * result + small.hashCode() 64 | result = 31 * result + medium.hashCode() 65 | result = 31 * result + large.hashCode() 66 | result = 31 * result + extraLarge.hashCode() 67 | result = 31 * result + capsule.hashCode() 68 | result = 31 * result + circle.hashCode() 69 | return result 70 | } 71 | 72 | override fun toString(): String { 73 | return "PkShapes(none=$none, small=$small, medium=$medium, large=$large, extraLarge=$extraLarge, capsule=$capsule, circle=$circle)" 74 | } 75 | } 76 | 77 | internal val LocalPkShapes = staticCompositionLocalOf { PkShapes() } 78 | -------------------------------------------------------------------------------- /library/src/main/java/com/peakmain/compose/ui/cell/PkCell.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.ui.cell 2 | 3 | /** 4 | * author :Peakmain 5 | * createTime:2025/4/17 6 | * mail:2726449200@qq.com 7 | * describe:单元格 8 | */ 9 | import android.text.TextUtils 10 | import androidx.annotation.DrawableRes 11 | import androidx.compose.animation.core.LinearEasing 12 | import androidx.compose.animation.core.animateFloatAsState 13 | import androidx.compose.animation.core.tween 14 | import androidx.compose.foundation.Image 15 | import androidx.compose.foundation.background 16 | import androidx.compose.foundation.clickable 17 | import androidx.compose.foundation.layout.Arrangement 18 | import androidx.compose.foundation.layout.Column 19 | import androidx.compose.foundation.layout.IntrinsicSize 20 | import androidx.compose.foundation.layout.Row 21 | import androidx.compose.foundation.layout.RowScope 22 | import androidx.compose.foundation.layout.fillMaxHeight 23 | import androidx.compose.foundation.layout.fillMaxSize 24 | import androidx.compose.foundation.layout.fillMaxWidth 25 | import androidx.compose.foundation.layout.height 26 | import androidx.compose.foundation.layout.padding 27 | import androidx.compose.foundation.layout.size 28 | import androidx.compose.material3.LocalTextStyle 29 | import androidx.compose.material3.Text 30 | import androidx.compose.runtime.Composable 31 | import androidx.compose.runtime.getValue 32 | import androidx.compose.runtime.mutableStateOf 33 | import androidx.compose.runtime.remember 34 | import androidx.compose.runtime.setValue 35 | import androidx.compose.ui.Alignment 36 | import androidx.compose.ui.Modifier 37 | import androidx.compose.ui.draw.rotate 38 | import androidx.compose.ui.graphics.Color 39 | import androidx.compose.ui.graphics.ColorFilter 40 | import androidx.compose.ui.res.painterResource 41 | import androidx.compose.ui.text.TextStyle 42 | import androidx.compose.ui.text.font.FontStyle 43 | import androidx.compose.ui.text.style.TextAlign 44 | import androidx.compose.ui.text.style.TextOverflow 45 | import androidx.compose.ui.tooling.preview.Preview 46 | import androidx.compose.ui.unit.Dp 47 | import androidx.compose.ui.unit.TextUnit 48 | import androidx.compose.ui.unit.dp 49 | import androidx.compose.ui.unit.sp 50 | import com.peakmain.compose.basic.BasicFont 51 | import com.peakmain.compose.basic.BasicSize 52 | import com.peakmain.compose.library.R 53 | import com.peakmain.compose.ui.title.PkTitle 54 | import com.peakmain.compose.ui.title.PkTitleType 55 | 56 | /** 57 | * 通用可自定义右侧内容的标题组件。 58 | * 59 | * @param text 左侧显示的文本内容(必填) 60 | * @param type 标题样式类型(字体大小、字重等),默认 [PkTitleType.BigTitle1],详见 PkTitleType 文档 61 | * @param modifier 布局修饰符(如尺寸、边距等),作用于整个单元格容器,默认 [Modifier] 62 | * @param color 文本颜色,默认 Color(0xFF333333) 63 | * @param fontStyle 字体风格,如 [FontStyle.Italic],默认 null 64 | * @param textAlign 文本对齐方式,如 [TextAlign.End](右对齐),默认 null(跟随系统) 65 | * @param overflow 文本溢出处理方式,默认 [TextOverflow.Ellipsis] 66 | * @param maxLines 文本最大显示行数,默认 1 67 | * @param style 自定义文本样式,可覆盖 [type] 中的部分属性,默认 [LocalTextStyle.current] 68 | * @param rightContent 右侧自定义内容(必填),支持任意组合(图标、开关等),通过 [RowScope] 提供灵活布局能力 69 | */ 70 | @Composable 71 | fun PkCell( 72 | text: String, 73 | type: PkTitleType = PkTitleType.BigTitle1(), 74 | modifier: Modifier = Modifier, 75 | color: Color = Color(0xFF333333), 76 | fontStyle: FontStyle? = null, 77 | textAlign: TextAlign? = null, 78 | overflow: TextOverflow = TextOverflow.Ellipsis, 79 | maxLines: Int = 1, 80 | style: TextStyle = LocalTextStyle.current, 81 | rightContent: @Composable RowScope.() -> Unit 82 | ) { 83 | Row( 84 | modifier 85 | .height(IntrinsicSize.Min) 86 | .fillMaxWidth(), 87 | horizontalArrangement = Arrangement.SpaceBetween, 88 | verticalAlignment = Alignment.CenterVertically 89 | ) { 90 | PkTitle(text, type, Modifier, color, fontStyle, textAlign, overflow, maxLines, style) 91 | Row( 92 | verticalAlignment = Alignment.CenterVertically,) { 93 | rightContent.invoke(this) 94 | } 95 | } 96 | } 97 | 98 | /** 99 | * 通用标题组件 100 | * 101 | * @param text 左侧主标题文本内容(必填) 102 | * @param type 标题样式类型(字体大小、字重),默认 [PkTitleType.BigTitle1],参考 PkTitleType 文档 103 | * @param modifier 整体容器修饰符(如边距、背景等),默认 [Modifier] 104 | * @param color 左侧标题文本颜色,默认 Color(0xFF333333) 105 | * @param fontStyle 字体风格,如 [FontStyle.Italic],默认 null 106 | * @param textAlign 文本对齐方式,默认 null(跟随系统) 107 | * @param overflow 文本溢出处理方式,默认 [TextOverflow.Ellipsis] 108 | * @param maxLines 文本最大显示行数,默认 1 109 | * @param style 自定义文本样式(覆盖 [type] 属性),默认 [LocalTextStyle.current] 110 | * @param rightText 右侧辅助文本内容(空字符串时不显示),默认 "" 111 | * @param rightTextColor 右侧辅助文本颜色,默认 Color(0xFF666666) 112 | * @param rightTextSize 右侧辅助文本字体大小,默认 12.sp 113 | * @param rightIcon 右侧图标资源 ID(设为 null 时不显示图标),默认 R.drawable.ic_right_arrow 114 | * @param rightIconSize 右侧图标尺寸,默认 12.dp 115 | * @param isRightIconRotated 是否启用图标旋转动画(用于展开/收起状态指示),默认 false 116 | * @param rightClick 点击右侧区域的回调(触发动画和自定义逻辑),默认 null 117 | */ 118 | 119 | @Composable 120 | fun PkCell( 121 | text: String, 122 | type: PkTitleType = PkTitleType.BigTitle1(), 123 | modifier: Modifier = Modifier, 124 | color: Color = Color(0xFF333333), 125 | fontStyle: FontStyle? = null, 126 | textAlign: TextAlign? = null, 127 | overflow: TextOverflow = TextOverflow.Ellipsis, 128 | maxLines: Int = 1, 129 | style: TextStyle = LocalTextStyle.current, 130 | rightText: String = "", 131 | rightTextColor: Color = Color(0xFF666666), 132 | rightTextSize: TextUnit = BasicFont.font_12, 133 | @DrawableRes rightIcon: Int? = R.drawable.ic_right_arrow, 134 | rightIconSize: Dp = BasicSize.size_12, 135 | isRightIconRotated: Boolean = false, 136 | rightClick: (() -> Unit)? = null 137 | ) { 138 | var isRotated by remember { mutableStateOf(false) } 139 | // 创建一个浮动动画状态,从 0f 度旋转到 360f 度 140 | val rotation by animateFloatAsState( 141 | targetValue = if (isRotated) 180f else 0f, 142 | animationSpec = tween( 143 | durationMillis = 1000, 144 | easing = LinearEasing 145 | ) 146 | ) 147 | Row( 148 | modifier 149 | .height(IntrinsicSize.Min) 150 | .fillMaxWidth(), 151 | horizontalArrangement = Arrangement.SpaceBetween, 152 | verticalAlignment = Alignment.CenterVertically 153 | ) { 154 | PkTitle(text, type, Modifier, color, fontStyle, textAlign, overflow, maxLines, style) 155 | Row(verticalAlignment = Alignment.CenterVertically, 156 | modifier = Modifier 157 | .clickable { 158 | isRotated = !isRotated 159 | rightClick?.invoke() 160 | } 161 | .padding(start = BasicSize.size_25) 162 | .fillMaxHeight() 163 | ) { 164 | if (!TextUtils.isEmpty(rightText)) { 165 | Text(rightText, color = rightTextColor, fontSize = rightTextSize) 166 | } 167 | rightIcon?.let { 168 | Image( 169 | painter = painterResource(it), 170 | contentDescription = null, 171 | colorFilter = ColorFilter.tint(rightTextColor), 172 | modifier = Modifier 173 | .size(rightIconSize) 174 | .rotate(if (isRightIconRotated) rotation else 0f) 175 | ) 176 | } 177 | } 178 | } 179 | } 180 | 181 | @Preview 182 | @Composable 183 | fun PkCellPreview() { 184 | Column( 185 | Modifier 186 | .background(Color.White) 187 | .fillMaxSize() 188 | ) { 189 | PkCell( 190 | "常用功能", 191 | PkTitleType.BigTitle3(), 192 | rightText = "展开", 193 | modifier = Modifier.padding(horizontal = 18.dp), 194 | color = Color(0xFF14401B) 195 | ) 196 | } 197 | 198 | 199 | } 200 | 201 | -------------------------------------------------------------------------------- /library/src/main/java/com/peakmain/compose/ui/divier/PkDashDivider.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.ui.divier 2 | 3 | /** 4 | * author :Peakmain 5 | * createTime:2025/3/6 6 | * mail:2726449200@qq.com 7 | * describe: 8 | */ 9 | import androidx.compose.foundation.layout.fillMaxWidth 10 | import androidx.compose.foundation.layout.height 11 | import androidx.compose.foundation.layout.width 12 | import androidx.compose.runtime.Composable 13 | import androidx.compose.ui.Modifier 14 | import androidx.compose.ui.geometry.Offset 15 | import androidx.compose.ui.graphics.Color 16 | import androidx.compose.ui.graphics.PathEffect 17 | import androidx.compose.ui.graphics.drawscope.Stroke 18 | import androidx.compose.ui.tooling.preview.Preview 19 | import androidx.compose.ui.unit.Dp 20 | import androidx.compose.ui.unit.dp 21 | 22 | /** 23 | * 虚线分隔线(支持水平/垂直) 24 | * 25 | * @param modifier 用于添加额外修饰符的 Modifier。 26 | * @param color 虚线的颜色,默认为 0x67272A2B。 27 | * @param height 分割线的高度,垂直方向生效 28 | * @param strokeWidth 虚线的宽度,默认为 0.5.dp。 29 | * @param dashLength 虚线的长度,默认为 2.dp。 30 | * @param gapLength 虚线之间的间隔长度,默认为 2.dp。 31 | * @param isHorizontal 水平分割线(true)/垂直分割线(false),默认是false 32 | */ 33 | @Composable 34 | fun PkDashDivider( 35 | modifier: Modifier = Modifier, 36 | color: Color = Color(0x67272A2B), 37 | height:Dp=28.dp, 38 | strokeWidth: Dp = 0.5.dp, 39 | dashLength: Dp = 2.dp, 40 | gapLength: Dp = 2.dp, 41 | isHorizontal: Boolean = false, 42 | ) { 43 | val newModifier = if (isHorizontal) modifier 44 | .fillMaxWidth() 45 | .height(strokeWidth) else modifier 46 | .height(height) 47 | .width(strokeWidth) 48 | androidx.compose.foundation.Canvas( 49 | newModifier 50 | ) { 51 | val stroke = Stroke( 52 | width = strokeWidth.toPx(), 53 | pathEffect = PathEffect.dashPathEffect( 54 | intervals = floatArrayOf(dashLength.toPx(), gapLength.toPx()) 55 | ) 56 | ) 57 | drawLine( 58 | color = color, 59 | start = Offset(0f, 0f), 60 | end = Offset(size.width, size.height), 61 | strokeWidth = stroke.width, 62 | pathEffect = stroke.pathEffect 63 | ) 64 | } 65 | 66 | } 67 | 68 | @Preview 69 | @Composable 70 | fun DashDividerPreview() { 71 | PkDashDivider() 72 | } 73 | -------------------------------------------------------------------------------- /library/src/main/java/com/peakmain/compose/ui/divier/PkDivider.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.ui.divier 2 | 3 | /** 4 | * author :Peakmain 5 | * createTime:2025/3/15 6 | * mail:2726449200@qq.com 7 | * describe:分割线 8 | */ 9 | import androidx.compose.runtime.Composable 10 | import androidx.compose.ui.Modifier 11 | import androidx.compose.ui.graphics.Color 12 | import androidx.compose.ui.tooling.preview.Preview 13 | import androidx.compose.ui.unit.Dp 14 | import androidx.compose.ui.unit.dp 15 | 16 | /** 17 | * 根据 isDash 参数绘制虚线或完整的分隔线。 18 | * 19 | * @param modifier 用于添加额外修饰符的 Modifier。 20 | * @param color 分隔线的颜色,默认为 0xFFF1EFE9。 21 | * @param height 分隔线的高度,仅在垂直分隔线时生效,默认为 28.dp。 22 | * @param thickness 分隔线的厚度,仅在非虚线时生效,默认为 1.dp。 23 | * @param startIndent 分隔线的起始缩进,仅在非虚线时生效,默认为 0.dp。 24 | * @param isHorizontal 是否为水平分隔线,默认为 false。 25 | * @param isDash 是否绘制虚线分隔线,默认为 false。 26 | * @param strokeWidth 虚线的宽度,仅在绘制虚线时生效,默认为 0.5.dp。 27 | * @param dashLength 虚线的线段长度,仅在绘制虚线时生效,默认为 2.dp。 28 | * @param gapLength 虚线的间隔长度,仅在绘制虚线时生效,默认为 2.dp。 29 | */ 30 | @Composable 31 | fun PkDivider( 32 | modifier: Modifier = Modifier, 33 | color: Color = Color(0xFFF1EFE9), 34 | height: Dp = 28.dp, 35 | thickness: Dp = 1.dp, 36 | startIndent: Dp = 0.dp, 37 | isHorizontal: Boolean = false, 38 | isDash: Boolean = false, 39 | strokeWidth: Dp = 0.5.dp, 40 | dashLength: Dp = 2.dp, 41 | gapLength: Dp = 2.dp, 42 | ) { 43 | if (isDash) { 44 | PkDashDivider( 45 | modifier = modifier, 46 | color = color, 47 | height=height, 48 | strokeWidth = strokeWidth, 49 | dashLength = dashLength, 50 | gapLength = gapLength, 51 | isHorizontal = isHorizontal 52 | ) 53 | } else { 54 | PkFullDivider( 55 | modifier = modifier, 56 | color = color, 57 | height = height, 58 | thickness = thickness, 59 | startIndent = startIndent, 60 | isHorizontal = isHorizontal 61 | ) 62 | } 63 | } 64 | 65 | @Preview 66 | @Composable 67 | fun PkDividerPreview() { 68 | PkDivider() 69 | } 70 | -------------------------------------------------------------------------------- /library/src/main/java/com/peakmain/compose/ui/divier/PkFullDivider.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.ui.divier 2 | 3 | import androidx.compose.foundation.background 4 | import androidx.compose.foundation.layout.Box 5 | import androidx.compose.foundation.layout.fillMaxWidth 6 | import androidx.compose.foundation.layout.height 7 | import androidx.compose.foundation.layout.padding 8 | import androidx.compose.foundation.layout.width 9 | import androidx.compose.runtime.Composable 10 | import androidx.compose.ui.Modifier 11 | import androidx.compose.ui.graphics.Color 12 | import androidx.compose.ui.platform.LocalDensity 13 | import androidx.compose.ui.unit.Dp 14 | import androidx.compose.ui.unit.dp 15 | 16 | /** 17 | * author :Peakmain 18 | * createTime:2025/3/7 19 | * mail:2726449200@qq.com 20 | * describe:垂直分割线 21 | */ 22 | 23 | 24 | /** 25 | * 创建一个实线分隔线组件。 26 | * 27 | * @param modifier 用于添加额外修饰符的 Modifier。 28 | * @param color 分隔线的颜色,默认为 0xFFF1EFE9。 29 | * @param height 分隔线的高度,默认为 28.dp。 30 | * @param thickness 分隔线的厚度,默认为 1.dp。 31 | * @param startIndent 分隔线的起始缩进,默认为 0.dp。 32 | * @param isHorizontal 水平分割线(true)/垂直分割线(false),默认是false 33 | */ 34 | @Composable 35 | fun PkFullDivider( 36 | modifier: Modifier = Modifier, 37 | color: Color = Color(0xFFF1EFE9), 38 | height:Dp=28.dp, 39 | thickness: Dp = 1.dp, 40 | startIndent: Dp = 0.dp, 41 | isHorizontal: Boolean=false 42 | ) { 43 | val indentMod = if (startIndent.value != 0f) { 44 | Modifier.padding(start = startIndent) 45 | } else { 46 | Modifier 47 | } 48 | val targetThickness = if (thickness == Dp.Hairline) { 49 | (1f / LocalDensity.current.density).dp 50 | } else { 51 | thickness 52 | } 53 | if(isHorizontal){ 54 | Box( 55 | modifier.then(indentMod) 56 | .fillMaxWidth() 57 | .height(targetThickness) 58 | .background(color = color) 59 | ) 60 | }else{ 61 | Box( 62 | modifier.then(indentMod) 63 | .height(height) 64 | .width(targetThickness) 65 | .background(color = color) 66 | ) 67 | } 68 | 69 | } -------------------------------------------------------------------------------- /library/src/main/java/com/peakmain/compose/ui/flow/PkFlowRow.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.ui.flow 2 | 3 | /** 4 | * author :Peakmain 5 | * createTime:2025/3/20 6 | * mail:2726449200@qq.com 7 | * describe:限制行数的FlowRow 8 | */ 9 | import androidx.compose.foundation.background 10 | import androidx.compose.foundation.layout.Arrangement 11 | import androidx.compose.foundation.layout.ExperimentalLayoutApi 12 | import androidx.compose.foundation.layout.FlowRow 13 | import androidx.compose.foundation.layout.fillMaxWidth 14 | import androidx.compose.foundation.layout.heightIn 15 | import androidx.compose.foundation.layout.padding 16 | import androidx.compose.foundation.shape.RoundedCornerShape 17 | import androidx.compose.material.Text 18 | import androidx.compose.runtime.Composable 19 | import androidx.compose.runtime.LaunchedEffect 20 | import androidx.compose.runtime.getValue 21 | import androidx.compose.runtime.mutableStateOf 22 | import androidx.compose.runtime.remember 23 | import androidx.compose.runtime.setValue 24 | import androidx.compose.ui.Alignment 25 | import androidx.compose.ui.Modifier 26 | import androidx.compose.ui.draw.clipToBounds 27 | import androidx.compose.ui.graphics.Color 28 | import androidx.compose.ui.layout.SubcomposeLayout 29 | import androidx.compose.ui.platform.LocalDensity 30 | import androidx.compose.ui.text.style.TextOverflow 31 | import androidx.compose.ui.tooling.preview.Preview 32 | import androidx.compose.ui.unit.Dp 33 | import androidx.compose.ui.unit.dp 34 | import androidx.compose.ui.unit.max 35 | 36 | @OptIn(ExperimentalLayoutApi::class) 37 | @Composable 38 | fun PkFlowRow( 39 | modifier: Modifier = Modifier, // 布局修饰符 40 | horizontalSpacing: Dp = 0.dp, // 子项水平间距 41 | verticalSpacing: Dp = 0.dp, // 行间垂直间距 42 | maxLine: Int = 2, // 最大显示行数 43 | onLineCountChanged: ((Int) -> Unit)? = null, // 行数变化回调 44 | content: @Composable () -> Unit // 子组件内容 45 | ) { 46 | val density = LocalDensity.current 47 | //当前行数的状态 48 | var lineCountState by remember { mutableStateOf(0) } 49 | 50 | //生命周期感知调用 51 | LaunchedEffect(lineCountState) { 52 | onLineCountChanged?.invoke(lineCountState) 53 | } 54 | SubcomposeLayout { constraints -> 55 | //测量所有的子View的测量数据 56 | val measurables = subcompose("measure", content) 57 | val hSpacingPx = with(density) { horizontalSpacing.roundToPx() } 58 | val vSpacingPx = with(density) { verticalSpacing.roundToPx() } 59 | //获取到所有测量结果 60 | val placeables = 61 | measurables.map { it.measure(constraints = constraints.copy(minWidth = 0)) } 62 | var currentLine = 0 63 | var currentRowWidth = 0 64 | var totalHeight = 0 65 | var currentRowHeight = 0 66 | placeables.forEachIndexed { index, placeable -> 67 | val itemWidth = placeable.width + if (index > 0) hSpacingPx else 0 68 | 69 | if (currentRowWidth + itemWidth > constraints.maxWidth) { 70 | currentLine++ 71 | if (currentLine >= maxLine) return@forEachIndexed 72 | totalHeight += currentRowHeight + vSpacingPx 73 | currentRowWidth = 0 74 | currentRowHeight = 0 75 | } 76 | currentRowWidth += itemWidth 77 | currentRowHeight = maxOf(currentRowHeight, placeable.height) 78 | } 79 | lineCountState= if (currentRowWidth > 0) currentLine + 1 else currentLine 80 | //获取最大高度 81 | val maxHeight = totalHeight + currentRowHeight 82 | 83 | // 第二阶段:实际布局 84 | subcompose("content") { 85 | FlowRow( 86 | modifier = modifier 87 | .heightIn(max = with(density) { maxHeight.toDp() }) 88 | .clipToBounds(), 89 | horizontalArrangement = Arrangement.spacedBy(horizontalSpacing), 90 | verticalArrangement = Arrangement.spacedBy(verticalSpacing) 91 | ) { 92 | content() 93 | } 94 | }.first().measure(constraints).let { placeable -> 95 | // 正确使用layout作用域 96 | layout(constraints.maxWidth, maxHeight) { 97 | placeable.place(0, 0) 98 | } 99 | } 100 | } 101 | } 102 | 103 | @Preview 104 | @Composable 105 | fun PkFlowRowPreview() { 106 | val tags = listOf("Android", "Kotlin", "Jetpack Compose", "KMP","Material Design", "UI", "Development") 107 | 108 | PkFlowRow( 109 | horizontalSpacing = 8.dp, 110 | verticalSpacing = 12.dp, 111 | maxLine = 2 112 | ) { 113 | tags.forEach { tag -> 114 | Text( 115 | text = tag, 116 | modifier = Modifier 117 | .background(Color.LightGray, RoundedCornerShape(16.dp)) 118 | .padding(horizontal = 12.dp, vertical = 8.dp) 119 | ) 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /library/src/main/java/com/peakmain/compose/ui/grid/PkStaggeredVerticalGrid.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.ui.grid 2 | 3 | import androidx.compose.foundation.layout.PaddingValues 4 | import androidx.compose.runtime.Composable 5 | import androidx.compose.ui.Modifier 6 | import androidx.compose.ui.layout.Layout 7 | import androidx.compose.ui.unit.Dp 8 | import androidx.compose.ui.unit.dp 9 | 10 | /** 11 | * author :Peakmain 12 | * createTime:2025/6/21 13 | * mail:2726449200@qq.com 14 | * describe:瀑布流,非懒加载版 15 | */ 16 | /** 17 | * 适合中小数据(<50项),若超过50,请用LazyVerticalStaggeredGrid 18 | * @param columns 网格列数(必须 >0) 19 | * @param modifier 容器修饰符(背景、尺寸等) 20 | * @param contentPadding 内容区域的内边距 21 | * @param verticalItemSpacing 垂直方向(行间)间距,默认是8.dp 22 | * @param horizontalItemSpacing 水平方向(列间)间距,默认是8.dp 23 | * @param content 网格项内容(任意 Composable 组件) 24 | */ 25 | @Composable 26 | fun PkStaggeredVerticalGrid( 27 | columns: Int, 28 | modifier: Modifier = Modifier, 29 | contentPadding: PaddingValues = PaddingValues(0.dp), 30 | verticalItemSpacing: Dp = 8.dp, 31 | horizontalItemSpacing: Dp = 8.dp, 32 | content: @Composable () -> Unit 33 | ) { 34 | require(columns > 0) { "列数必须大于0" } 35 | 36 | Layout( 37 | content = content, 38 | modifier = modifier 39 | ) { measurables, constraints -> 40 | // 计算内容区域宽度(减去内边距) 41 | val horizontalPadding = contentPadding.calculateLeftPadding(layoutDirection) + 42 | contentPadding.calculateRightPadding(layoutDirection) 43 | val contentWidth = (constraints.maxWidth - horizontalPadding.roundToPx()).coerceAtLeast(0) 44 | 45 | // 计算列宽(减去水平间距) 46 | val columnWidth = ((contentWidth - (columns - 1) * horizontalItemSpacing.roundToPx()) / columns) 47 | .coerceAtLeast(0) 48 | 49 | // 初始化列高度数组 50 | val columnHeights = IntArray(columns) { contentPadding.calculateTopPadding().roundToPx() } 51 | 52 | // 测量所有子项 53 | val placeables = measurables.map { measurable -> 54 | // 约束子项宽度为列宽 55 | val placeable = measurable.measure( 56 | constraints.copy( 57 | minWidth = columnWidth, 58 | maxWidth = columnWidth 59 | ) 60 | ) 61 | placeable 62 | } 63 | 64 | // 计算每个子项的位置 65 | val positions = mutableListOf>() 66 | 67 | placeables.forEach { placeable -> 68 | // 找到当前高度最小的列 69 | val minColumn = columnHeights.withIndex().minByOrNull { it.value }?.index ?: 0 70 | val x = contentPadding.calculateLeftPadding(layoutDirection).roundToPx() + 71 | minColumn * (columnWidth + horizontalItemSpacing.roundToPx()) 72 | val y = columnHeights[minColumn] 73 | 74 | // 更新列高度(加上当前项高度和垂直间距) 75 | columnHeights[minColumn] = y + placeable.height + verticalItemSpacing.roundToPx() 76 | 77 | positions.add(x to y) 78 | } 79 | 80 | // 计算总高度(最高列的高度 + 底部内边距) 81 | val totalHeight = (columnHeights.maxOrNull() ?: 0) + 82 | contentPadding.calculateBottomPadding().roundToPx() - 83 | verticalItemSpacing.roundToPx() // 减去最后一项的额外间距 84 | 85 | layout(constraints.maxWidth, totalHeight) { 86 | placeables.forEachIndexed { index, placeable -> 87 | val (x, y) = positions[index] 88 | placeable.place(x, y) 89 | } 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /library/src/main/java/com/peakmain/compose/ui/image/PkImageView.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.ui.image 2 | 3 | /** 4 | * author :Peakmain 5 | * createTime:2025/4/17 6 | * mail:2726449200@qq.com 7 | * describe: 8 | */ 9 | import androidx.compose.foundation.Image 10 | import androidx.compose.runtime.Composable 11 | import androidx.compose.ui.Alignment 12 | import androidx.compose.ui.Modifier 13 | import androidx.compose.ui.graphics.Color 14 | import androidx.compose.ui.graphics.ColorFilter 15 | import androidx.compose.ui.graphics.DefaultAlpha 16 | import androidx.compose.ui.graphics.painter.Painter 17 | import androidx.compose.ui.layout.ContentScale 18 | import androidx.compose.ui.tooling.preview.Preview 19 | 20 | 21 | @Composable 22 | fun PkImageView( 23 | painter: Painter, 24 | modifier: Modifier = Modifier, 25 | alignment: Alignment = Alignment.Center, 26 | contentScale: ContentScale = ContentScale.Crop, 27 | alpha: Float = DefaultAlpha, 28 | tintColor: Color? = null 29 | ) { 30 | Image( 31 | painter = painter, 32 | contentDescription = null, 33 | modifier, alignment, 34 | contentScale = contentScale, 35 | alpha = alpha, 36 | colorFilter = if (tintColor != null) ColorFilter.tint(tintColor) else null, 37 | ) 38 | } 39 | -------------------------------------------------------------------------------- /library/src/main/java/com/peakmain/compose/ui/progress/RoundedLinearProgressIndicator.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.ui.progress 2 | 3 | 4 | import androidx.compose.foundation.Canvas 5 | import androidx.compose.foundation.layout.fillMaxWidth 6 | import androidx.compose.foundation.layout.height 7 | import androidx.compose.runtime.Composable 8 | import androidx.compose.ui.Modifier 9 | import androidx.compose.ui.geometry.Offset 10 | import androidx.compose.ui.geometry.Size 11 | import androidx.compose.ui.graphics.Color 12 | import androidx.compose.ui.graphics.drawscope.DrawScope 13 | import androidx.compose.ui.graphics.drawscope.Stroke 14 | import androidx.compose.ui.unit.Dp 15 | import androidx.compose.ui.unit.dp 16 | import com.peakmain.compose.basic.BasicColor 17 | /** 18 | * author :Peakmain 19 | * createTime:2025/6/11 20 | * mail:2726449200@qq.com 21 | * describe:圆角进度条 22 | */ 23 | @Composable 24 | fun RoundedLinearProgressIndicator( 25 | progress: Float, 26 | modifier: Modifier = Modifier, 27 | color: Color = BasicColor.color_1F401B, 28 | backgroundColor: Color = BasicColor.color_EBEBF0, 29 | height: Dp = 4.dp, 30 | cornerRadius: Dp = 2.dp 31 | ) { 32 | Canvas( 33 | modifier = modifier 34 | .fillMaxWidth() 35 | .height(height) 36 | ) { 37 | // 绘制背景 38 | drawRoundedRect( 39 | color = backgroundColor, 40 | size = Size(size.width, size.height), 41 | cornerRadius = cornerRadius.toPx() 42 | ) 43 | 44 | // 绘制进度条 45 | if (progress > 0) { 46 | val progressWidth = size.width * progress.coerceIn(0f, 1f) 47 | drawRoundedRect( 48 | color = color, 49 | topLeft = Offset(0f, 0f), 50 | size = Size(progressWidth, size.height), 51 | cornerRadius = cornerRadius.toPx() 52 | ) 53 | } 54 | } 55 | } 56 | 57 | // 在 DrawScope 中扩展绘制圆角矩形的函数 58 | private fun DrawScope.drawRoundedRect( 59 | color: Color, 60 | topLeft: Offset = Offset.Zero, 61 | size: Size, 62 | cornerRadius: Float 63 | ) { 64 | drawRoundRect( 65 | color = color, 66 | topLeft = topLeft, 67 | size = size, 68 | cornerRadius = androidx.compose.ui.geometry.CornerRadius(cornerRadius, cornerRadius) 69 | ) 70 | } -------------------------------------------------------------------------------- /library/src/main/java/com/peakmain/compose/ui/text/PkHighlightText.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.ui.text 2 | 3 | /** 4 | * author :Peakmain 5 | * createTime:2025/4/25 6 | * mail:2726449200@qq.com 7 | * describe:高亮文本 8 | */ 9 | import androidx.compose.foundation.background 10 | import androidx.compose.foundation.layout.Column 11 | import androidx.compose.material.MaterialTheme 12 | import androidx.compose.material.Text 13 | import androidx.compose.material3.LocalTextStyle 14 | import androidx.compose.runtime.Composable 15 | import androidx.compose.runtime.remember 16 | import androidx.compose.ui.Modifier 17 | import androidx.compose.ui.graphics.Color 18 | import androidx.compose.ui.text.SpanStyle 19 | import androidx.compose.ui.text.TextStyle 20 | import androidx.compose.ui.text.buildAnnotatedString 21 | import androidx.compose.ui.text.withStyle 22 | import androidx.compose.ui.tooling.preview.Preview 23 | 24 | /** 25 | * author :Peakmain 26 | * createTime:2025/4/25 27 | * mail:2726449200@qq.com 28 | * describe:高亮关键词的文本组件 29 | */ 30 | 31 | /** 32 | * 高亮关键词的文本组件。 33 | * 34 | * @param text 需要处理的原始文本。 35 | * @param keywords 高亮关键字列表(为空时不进行高亮)。 36 | * @param highlightColor 高亮文本颜色,默认值为 [Color.Red]。 37 | * @param style 基础文本样式,默认值为 [LocalTextStyle.current],高亮部分继承此样式并叠加颜色。 38 | */ 39 | @Composable 40 | fun PkHighlightText( 41 | text: String, 42 | keywords: List, 43 | highlightColor: Color = Color.Red, 44 | style: TextStyle = LocalTextStyle.current 45 | ) { 46 | val annotatedString = remember(text, keywords) { 47 | buildAnnotatedString { 48 | if (keywords.isEmpty()) { 49 | append(text) // 无关键字直接返回原文本 50 | return@buildAnnotatedString 51 | } 52 | 53 | // 1. 生成正则表达式模式(处理特殊字符) 54 | val pattern = keywords 55 | .filter { it.isNotEmpty() } // 过滤空关键字 56 | .distinct() // 去重 57 | .joinToString("|") { Regex.escape(it) } // 转义正则特殊字符 58 | .takeIf { it.isNotEmpty() } ?: run { 59 | append(text) 60 | return@buildAnnotatedString 61 | } 62 | 63 | // 2. 创建不区分大小写的正则表达式 64 | val regex = try { 65 | Regex(pattern, RegexOption.IGNORE_CASE) 66 | } catch (e: Exception) { 67 | // 处理非法正则表达式(如空模式) 68 | append(text) 69 | return@buildAnnotatedString 70 | } 71 | 72 | // 3. 查找所有匹配区间并合并重叠 73 | val matches = regex.findAll(text) 74 | .map { it.range.first to it.range.last + 1 } // 转换为前闭后开区间 75 | .toList() 76 | 77 | val mergedRanges = mergeIntervals(matches) 78 | 79 | // 4. 构建带高亮的字符串 80 | var currentIndex = 0 81 | for ((start, end) in mergedRanges) { 82 | if (start > currentIndex) { 83 | // 添加非高亮部分 84 | append(text.substring(currentIndex, start)) 85 | } 86 | // 添加高亮部分(保留原文字大小写) 87 | withStyle(SpanStyle(color = highlightColor)) { 88 | append(text.substring(start, end)) 89 | } 90 | currentIndex = end 91 | } 92 | // 添加剩余文本 93 | if (currentIndex < text.length) { 94 | append(text.substring(currentIndex)) 95 | } 96 | } 97 | } 98 | Text(text = annotatedString, style = style) 99 | } 100 | 101 | /** 102 | * 合并重叠区间算法 103 | * 输入示例:[(0,3), (2,5), (6,7)] → 输出:[(0,5), (6,7)] 104 | */ 105 | private fun mergeIntervals(intervals: List>): List> { 106 | if (intervals.isEmpty()) return emptyList() 107 | 108 | val sorted = intervals.sortedBy { it.first } 109 | val merged = mutableListOf>() 110 | var current = sorted.first() 111 | 112 | for (next in sorted) { 113 | if (next.first <= current.second) { 114 | // 区间重叠/相邻,合并 115 | current = current.first to maxOf(current.second, next.second) 116 | } else { 117 | merged.add(current) 118 | current = next 119 | } 120 | } 121 | merged.add(current) 122 | 123 | return merged 124 | } 125 | 126 | @Preview 127 | @Composable 128 | fun PkHighlightTextPreview() { 129 | Column(modifier = Modifier.background(Color.White)) { 130 | // 示例1:基本用法(多个关键字) 131 | PkHighlightText( 132 | text = "Jetpack Compose 是 Android 的现代 UI 工具包", 133 | keywords = listOf("compose", "android"), 134 | highlightColor = Color.Blue, 135 | style = MaterialTheme.typography.body1 136 | ) 137 | 138 | // 示例2:含特殊字符的关键字 139 | PkHighlightText( 140 | text = "价格:$199 (限时优惠)", 141 | keywords = listOf("$199", "(限时优惠)"), 142 | highlightColor = Color(0xFF4CAF50) 143 | ) 144 | 145 | // 示例3:无关键字/空列表 146 | PkHighlightText( 147 | text = "Hello World", 148 | keywords = emptyList() // 显示普通文本 149 | ) 150 | } 151 | } 152 | 153 | -------------------------------------------------------------------------------- /library/src/main/java/com/peakmain/compose/ui/title/PkNavBar.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.ui.title 2 | 3 | import android.app.Activity 4 | import androidx.annotation.DrawableRes 5 | import androidx.compose.foundation.background 6 | import androidx.compose.foundation.clickable 7 | import androidx.compose.foundation.layout.Box 8 | import androidx.compose.foundation.layout.fillMaxWidth 9 | import androidx.compose.foundation.layout.height 10 | import androidx.compose.foundation.layout.padding 11 | import androidx.compose.foundation.layout.size 12 | import androidx.compose.foundation.layout.statusBarsPadding 13 | import androidx.compose.material.Text 14 | import androidx.compose.runtime.Composable 15 | import androidx.compose.runtime.SideEffect 16 | import androidx.compose.ui.Alignment 17 | import androidx.compose.ui.Modifier 18 | import androidx.compose.ui.graphics.Color 19 | import androidx.compose.ui.platform.LocalConfiguration 20 | import androidx.compose.ui.platform.LocalContext 21 | import androidx.compose.ui.platform.LocalDensity 22 | import androidx.compose.ui.res.painterResource 23 | import androidx.compose.ui.text.font.FontWeight 24 | import androidx.compose.ui.tooling.preview.Preview 25 | import androidx.compose.ui.unit.Dp 26 | import androidx.compose.ui.unit.TextUnit 27 | import androidx.compose.ui.unit.dp 28 | import com.google.accompanist.systemuicontroller.rememberSystemUiController 29 | import com.peakmain.compose.basic.BasicFont 30 | import com.peakmain.compose.basic.BasicSize 31 | import com.peakmain.compose.basic.BasicSpace 32 | import com.peakmain.compose.library.R 33 | import com.peakmain.compose.ui.image.PkImageView 34 | 35 | /** 36 | * author :Peakmain 37 | * createTime:2025/6/26 38 | * mail:2726449200@qq.com 39 | * describe:自定义顶部标题栏 40 | */ 41 | 42 | /** 43 | * 顶部导航栏组件,支持自定义标题、返回按钮、右侧按钮、沉浸式状态栏等功能。 44 | * 45 | * @param title 标题,必填,导航栏标题文本 46 | * @param backgroundColor 导航栏背景色,默认 #FFFFFEFA 47 | * @param horizontalContentPadding 水平方向内边距,默认 BasicSpace.space_18 48 | * @param verticalContentPadding 垂直方向内边距,默认 BasicSpace.space_10 49 | * @param backResource 返回图标资源 ID,默认 R.drawable.compose_icon_retrun 50 | * @param backResourceSize 返回图标尺寸,默认 BasicSize.size_24 51 | * @param showBack 是否显示返回按钮,默认 true 52 | * @param onBackClick 返回按钮点击事件,默认 null(null 时点击返回关闭当前 Activity) 53 | * @param titleFontSize 标题文字大小,默认 BasicFont.font_18 54 | * @param titleColor 标题文字颜色,默认 #1F401B 55 | * @param isImmersive 是否沉浸式状态栏,默认 true 56 | * @param darkIcons 状态栏图标是否使用深色,默认 true 57 | * @param rightResource 右侧图标资源 ID,默认为 null 表示不显示 58 | * @param onRightClick 右侧图标点击事件,默认 null(null 时不显示或不响应) 59 | */ 60 | @Composable 61 | fun PkNavBar( 62 | title: String, 63 | backgroundColor: Color = Color(0xFFFFFEFA), 64 | horizontalContentPadding: Dp = BasicSpace.space_18, 65 | @DrawableRes backResource: Int = R.drawable.compose_icon_retrun, 66 | backResourceSize: Dp = BasicSize.size_24, 67 | showBack: Boolean = true, 68 | onBackClick: (() -> Unit)? = null, 69 | titleFontSize: TextUnit = BasicFont.font_18, 70 | titleColor: Color = Color(0xFF1F401B), 71 | isImmersive: Boolean = true, 72 | darkIcons: Boolean = true, 73 | @DrawableRes rightResource: Int? = null, 74 | onRightClick: (() -> Unit)? = null 75 | ) { 76 | val context = LocalContext.current 77 | if (isImmersive) { 78 | val systemUiController = rememberSystemUiController() 79 | SideEffect { 80 | systemUiController.setSystemBarsColor( 81 | color = backgroundColor, 82 | darkIcons = darkIcons 83 | ) 84 | } 85 | } 86 | Box( 87 | modifier = Modifier 88 | .fillMaxWidth() 89 | .background(backgroundColor) 90 | .statusBarsPadding() 91 | .height(44.dp) 92 | .padding(horizontal = horizontalContentPadding), 93 | contentAlignment = Alignment.Center 94 | ) { 95 | if (showBack) { 96 | PkImageView( 97 | painter = painterResource(backResource), 98 | modifier = Modifier 99 | .size(backResourceSize) 100 | .align(Alignment.CenterStart) 101 | .clickable { 102 | if (onBackClick == null && context is Activity) { 103 | context.finish() 104 | } else { 105 | onBackClick?.invoke() 106 | } 107 | }) 108 | } 109 | 110 | Text( 111 | text = title, 112 | fontSize = titleFontSize, 113 | fontWeight = FontWeight.W500, 114 | color = titleColor, 115 | modifier = Modifier 116 | .align(Alignment.Center) 117 | ) 118 | 119 | if (rightResource != null) { 120 | PkImageView( 121 | painter = painterResource(rightResource), 122 | modifier = Modifier 123 | .size(24.dp) 124 | .align(Alignment.CenterEnd) 125 | .clickable { onRightClick?.invoke() }) 126 | } 127 | } 128 | } 129 | 130 | -------------------------------------------------------------------------------- /library/src/main/java/com/peakmain/compose/ui/title/PkTitle.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.ui.title 2 | 3 | /** 4 | * author :Peakmain 5 | * createTime:2025/4/2 6 | * mail:2726449200@qq.com 7 | * describe: 8 | */ 9 | import androidx.compose.foundation.layout.Column 10 | import androidx.compose.material3.LocalTextStyle 11 | import androidx.compose.material3.Text 12 | import androidx.compose.runtime.Composable 13 | import androidx.compose.ui.Modifier 14 | import androidx.compose.ui.graphics.Color 15 | import androidx.compose.ui.text.TextStyle 16 | import androidx.compose.ui.text.font.FontStyle 17 | import androidx.compose.ui.text.font.FontWeight 18 | import androidx.compose.ui.text.style.TextAlign 19 | import androidx.compose.ui.text.style.TextOverflow 20 | import androidx.compose.ui.tooling.preview.Preview 21 | import androidx.compose.ui.unit.TextUnit 22 | import androidx.compose.ui.unit.sp 23 | 24 | sealed class PkTitleType { 25 | abstract val fontSize: TextUnit 26 | abstract val fontWeight: FontWeight 27 | 28 | /** 29 | * 大标题1 30 | */ 31 | data class BigTitle1( 32 | override val fontSize: TextUnit = 24.sp, 33 | override val fontWeight: FontWeight = FontWeight.W500 34 | ) : PkTitleType() 35 | 36 | /** 37 | * 大标题2 38 | */ 39 | data class BigTitle2( 40 | override val fontSize: TextUnit = 22.sp, 41 | override val fontWeight: FontWeight = FontWeight.W500 42 | ) : PkTitleType() 43 | 44 | /** 45 | * 大标题3 46 | */ 47 | data class BigTitle3( 48 | override val fontSize: TextUnit = 18.sp, 49 | override val fontWeight: FontWeight = FontWeight.W500 50 | ) : PkTitleType() 51 | 52 | /** 53 | * 标题1 加粗 54 | */ 55 | data class TitleBold1( 56 | override val fontSize: TextUnit = 16.sp, 57 | override val fontWeight: FontWeight = FontWeight.W500 58 | ) : PkTitleType() 59 | 60 | /** 61 | * 标题1 常规 62 | */ 63 | data class TitleNormal1( 64 | override val fontSize: TextUnit = 16.sp, 65 | override val fontWeight: FontWeight = FontWeight.W400 66 | ) : PkTitleType() 67 | 68 | /** 69 | * 标题2 加粗 70 | */ 71 | data class TitleBold2( 72 | override val fontSize: TextUnit = 15.sp, 73 | override val fontWeight: FontWeight = FontWeight.W500 74 | ) : PkTitleType() 75 | 76 | /** 77 | * 标题2 常规 78 | */ 79 | data class TitleNormal2( 80 | override val fontSize: TextUnit = 15.sp, 81 | override val fontWeight: FontWeight = FontWeight.W400 82 | ) : PkTitleType() 83 | 84 | /** 85 | * 小标题 加粗 86 | */ 87 | data class SmallTitleBold( 88 | override val fontSize: TextUnit = 14.sp, 89 | override val fontWeight: FontWeight = FontWeight.W500 90 | ) : PkTitleType() 91 | 92 | /** 93 | * 小标题 常规 94 | */ 95 | data class SmallTitleNormal( 96 | override val fontSize: TextUnit = 14.sp, 97 | override val fontWeight: FontWeight = FontWeight.W400 98 | ) : PkTitleType() 99 | 100 | /** 101 | * 内文1加粗 102 | */ 103 | data class TextBold1( 104 | override val fontSize: TextUnit = 12.sp, 105 | override val fontWeight: FontWeight = FontWeight.W500 106 | ) : PkTitleType() 107 | /** 108 | * 内文1常规 109 | */ 110 | data class TextNormal1( 111 | override val fontSize: TextUnit = 12.sp, 112 | override val fontWeight: FontWeight = FontWeight.W400 113 | ) : PkTitleType() 114 | /** 115 | * 内文2加粗 116 | */ 117 | data class TextBold2( 118 | override val fontSize: TextUnit = 11.sp, 119 | override val fontWeight: FontWeight = FontWeight.W500 120 | ) : PkTitleType() 121 | 122 | /** 123 | * 内文2常规 124 | */ 125 | data class TextNormal2( 126 | override val fontSize: TextUnit = 11.sp, 127 | override val fontWeight: FontWeight = FontWeight.W400 128 | ) : PkTitleType() 129 | } 130 | @Composable 131 | fun PkTitle( 132 | text: String, 133 | type: PkTitleType = PkTitleType.BigTitle1(), 134 | modifier: Modifier = Modifier, 135 | color: Color = Color(0xFF333333), 136 | fontStyle: FontStyle? = null, 137 | textAlign: TextAlign? = null, 138 | overflow: TextOverflow = TextOverflow.Ellipsis, 139 | maxLines: Int =1, 140 | style: TextStyle = LocalTextStyle.current 141 | ) { 142 | Text( 143 | text, 144 | modifier, 145 | color, 146 | type.fontSize, 147 | fontStyle, 148 | type.fontWeight, 149 | textAlign = textAlign, 150 | overflow = overflow, 151 | maxLines = maxLines, 152 | style = style 153 | ) 154 | } 155 | 156 | @Preview 157 | @Composable 158 | fun PkTitleComposablePreview() { 159 | Column { 160 | PkTitle("大标题1",PkTitleType.BigTitle1()) 161 | PkTitle("大标题2",PkTitleType.BigTitle2()) 162 | PkTitle("大标题3",PkTitleType.BigTitle3()) 163 | PkTitle("标题1加粗",PkTitleType.TitleBold1()) 164 | PkTitle("标题1常规",PkTitleType.TitleNormal1()) 165 | PkTitle("标题2加粗",PkTitleType.TitleBold2()) 166 | PkTitle("标题2常规",PkTitleType.TitleNormal2()) 167 | PkTitle("小标题加粗",PkTitleType.SmallTitleBold()) 168 | PkTitle("小标题常规",PkTitleType.SmallTitleNormal()) 169 | PkTitle("内文1加粗",PkTitleType.TextBold1()) 170 | PkTitle("内文1正常",PkTitleType.TextNormal1()) 171 | PkTitle("内文2加粗",PkTitleType.TextBold2()) 172 | PkTitle("内文2正常",PkTitleType.TextNormal2()) 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /library/src/main/java/com/peakmain/compose/utils/ImagePainterUtils.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.utils 2 | 3 | import android.content.Context 4 | import android.graphics.Insets.add 5 | import android.os.Build.VERSION.SDK_INT 6 | import android.text.TextUtils 7 | import androidx.annotation.DrawableRes 8 | import androidx.compose.foundation.Image 9 | import androidx.compose.foundation.lazy.rememberLazyListState 10 | import androidx.compose.runtime.Composable 11 | import androidx.compose.runtime.derivedStateOf 12 | import androidx.compose.runtime.mutableStateOf 13 | import androidx.compose.runtime.remember 14 | import androidx.compose.ui.platform.LocalContext 15 | import coil.ImageLoader 16 | import coil.compose.AsyncImagePainter 17 | import coil.compose.rememberAsyncImagePainter 18 | import coil.decode.ImageDecoderDecoder 19 | import coil.decode.SvgDecoder 20 | import coil.request.ImageRequest 21 | import com.peakmain.compose.library.R 22 | 23 | /** 24 | * author :Peakmain 25 | * createTime:2025/3/6 26 | * mail:2726449200@qq.com 27 | * describe:图片加载工具类 28 | */ 29 | object ImagePainterUtils { 30 | /** 31 | * 根据图片 URL 获取 AsyncImagePainter 对象。 32 | * 33 | * @param imageUrl 图片的 URL,如果为空则显示占位图。 34 | * @param errorDrawableResId 图片加载失败时显示的 Drawable 资源 ID,默认为 R.drawable.icon_loading。 35 | * @param placeDrawableResId 图片加载过程中显示的占位图 Drawable 资源 ID,默认为 R.drawable.icon_loading。 36 | * @return 返回一个 AsyncImagePainter 对象。 37 | */ 38 | @Composable 39 | fun getPainter( 40 | imageUrl: String?, 41 | @DrawableRes errorDrawableResId: Int = R.drawable.icon_loading, 42 | @DrawableRes placeDrawableResId: Int = R.drawable.icon_loading, 43 | imageLoader: ImageLoader = getImageLoader(LocalContext.current) 44 | ): AsyncImagePainter { 45 | 46 | return if (!TextUtils.isEmpty(imageUrl)) 47 | rememberAsyncImagePainter( 48 | model = ImageRequest.Builder(LocalContext.current) 49 | .data(imageUrl) 50 | .error(errorDrawableResId) 51 | .placeholder(placeDrawableResId) 52 | .build(), 53 | imageLoader =imageLoader 54 | ) else 55 | rememberAsyncImagePainter( 56 | model = ImageRequest.Builder(LocalContext.current) 57 | .data(placeDrawableResId) 58 | .build(), 59 | imageLoader =imageLoader 60 | ) 61 | 62 | } 63 | 64 | private fun getImageLoader(context: Context): ImageLoader { 65 | return ImageLoader.Builder(context).components { 66 | if (SDK_INT > 28) { 67 | add(ImageDecoderDecoder.Factory()) 68 | } else { 69 | add(coil.decode.GifDecoder.Factory()) 70 | } 71 | add(SvgDecoder.Factory()) 72 | }.build() 73 | } 74 | } -------------------------------------------------------------------------------- /library/src/main/res/drawable/compose_icon_retrun.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /library/src/main/res/drawable/ic_right_arrow.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /library/src/main/res/drawable/icon_loading.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /library/src/test/java/com/peakmain/compose/library/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.peakmain.compose.library 2 | 3 | import org.junit.Test 4 | 5 | import org.junit.Assert.* 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | class ExampleUnitTest { 13 | @Test 14 | fun addition_isCorrect() { 15 | assertEquals(4, 2 + 2) 16 | } 17 | } -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | dependencyResolutionManagement { 2 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 3 | repositories { 4 | mavenCentral() 5 | google() 6 | jcenter() // Warning: this repository is going to shut down soon 7 | } 8 | } 9 | rootProject.name = "ComposeUI" 10 | include ':app' 11 | include ':library' 12 | --------------------------------------------------------------------------------