Commit 4ea9c9e7 authored by dsq's avatar dsq

1

parents
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties
plugins {
// this is necessary to avoid the plugins to be loaded multiple times
// in each subproject's classloader
alias(libs.plugins.androidApplication) apply false
alias(libs.plugins.androidLibrary) apply false
alias(libs.plugins.composeMultiplatform) apply false
alias(libs.plugins.composeCompiler) apply false
alias(libs.plugins.kotlinMultiplatform) apply false
}
/**
能导入的包
1. 来源插件
在 当前的 build.gradle.kts 定义可以搭配的插件
plugins {
alias(libs.plugins.androidApplication) // 提供 android.* 相关类
alias(libs.plugins.kotlinMultiplatform) // 提供 org.jetbrains.kotlin.gradle.* 相关类
alias(libs.plugins.composeMultiplatform) // 提供 compose 相关类
}
插件的版本在 libs.versions.toml 中定义:
2.Gradle 核心类
Gradle 本身提供的核心类(如 Copy、JavaVersion 等)自动可用,无需额外配置
*/
// 导入大写工具(capitalizeUS),用于字符串首字母大写
import android.databinding.tool.ext.capitalizeUS
// 导入ExperimentalKotlinGradlePluginApi注解,用于开启Kotlin插件实验特性
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
// 导入JvmTarget,用于指定JVM的目标版本
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
plugins {
// 应用Kotlin多平台插件
alias(libs.plugins.kotlinMultiplatform)
// 应用Android应用插件
alias(libs.plugins.androidApplication)
// 应用Compose多平台插件
alias(libs.plugins.composeMultiplatform)
// 应用Compose编译器插件
alias(libs.plugins.composeCompiler)
}
/**
Kotlin Multiplatform 配置
插件 libs.plugins.kotlinMultiplatform
负责 Kotlin 代码编译
Android: Kotlin/JVM → .class 文件 │
iOS: Kotlin/Native → LLVM IR │
OHOS: Kotlin/Native → LLVM IR
kotlin {
├── 目标平台 (androidTarget, jvm, iosX64, etc.)
│ ├── compilerOptions
│ └── binaries
├── cocoapods (iOS 特定)
├── sourceSets
│ ├── commonMain/commonTest
│ ├── platformMain/platformTest
│ └── customSourceSets
└── 其他配置
}
*/
kotlin {
// 配置Android目标
androidTarget {
@OptIn(ExperimentalKotlinGradlePluginApi::class) // 允许使用实验API
compilerOptions {
jvmTarget.set(JvmTarget.JVM_11) // 设置JVM target为11
}
}
// 配置iOS三种架构目标
// 编译配置: Kotlin 源码 → LLVM IR -> 机器码
listOf(
iosX64(), // iOS 模拟器(x64架构)
iosArm64(), // iOS 真机(arm64架构)
iosSimulatorArm64() // iOS 模拟器(arm64架构)
).forEach { iosTarget ->
iosTarget.binaries.framework {
baseName = "ComposeApp" // 设置framework名称
// 静态库 (isStatic = true) - 代码直接嵌入到最终应用中
// 动态库 (isStatic = false) - 运行时加载的库
isStatic = true // 设置framework为静态库
}
}
// 配置OHOS(华为鸿蒙)arm64目标
ohosArm64 {
binaries.sharedLib {
baseName = "kn" // 共享库名称为kn
export(libs.compose.multiplatform.export) // 导出compose多平台库的接口
}
val main by compilations.getting // 获取主编译内容
val resource by main.cinterops.creating {
// 配置C interop(cinterop)资源
defFile(file("src/ohosArm64Main/cinterop/resource.def")) // cinterop定义文件
includeDirs(file("src/ohosArm64Main/cinterop/include")) // cinterop包含目录
}
}
// 配置各平台的依赖关系
sourceSets {
androidMain.dependencies {
implementation(libs.androidx.activity.compose)
implementation(libs.androidx.collection)
implementation(libs.androidx.lifecycle.viewmodelCompose)
implementation(libs.androidx.lifecycle.runtimeCompose)
}
commonMain.dependencies {
implementation(compose.runtime) // 添加compose runtime依赖
implementation(compose.foundation) // 添加compose基础依赖
implementation(compose.material) // 添加compose material依赖
implementation(compose.ui) // 添加compose ui依赖
implementation(compose.components.resources) // 添加compose组件资源依赖
implementation(compose.components.uiToolingPreview) // 添加compose ui工具预览依赖
implementation(libs.kotlinx.coroutines.core) // 官方协程核心库
implementation(libs.atomicFu) // Kotlin AtomicFu原子库
}
val ohosArm64Main by getting {
dependencies {
api(libs.compose.multiplatform.export) // 导出compose多平台接口给依赖消费者
}
}
}
}
/**
应用 AGP : Android Gradle Plugin
Android 应用构建 : .class → DEX(Dalvik 字节码) → APK │
由 androidApplication 插件提供
将 .class 文件转换为 DEX(Dalvik 字节码) 文件
Android 构建工具 → 打包成 APK
作用:
配置 Android 应用 的构建行为
控制 APK 生成、打包、签名等
*/
android {
namespace = "com.dong.maxhap" // 设置包名
compileSdk = libs.versions.android.compileSdk.get().toInt() // 指定编译SDK版本
defaultConfig {
applicationId = "com.dong.maxhap" // 应用ID
minSdk = libs.versions.android.minSdk.get().toInt() // 最低SDK版本
targetSdk = libs.versions.android.targetSdk.get().toInt()// 目标SDK版本
versionCode = 1 // 应用版本号
versionName = "1.0" // 应用版本名
}
packaging {
resources {
excludes += "/META-INF/{AL2.0,LGPL2.1}"// 排除打包时的冗余license资源文件
}
}
buildTypes {
getByName("release") {
isMinifyEnabled = false // 发布包不混淆代码
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11 // 源码兼容Java 11
targetCompatibility = JavaVersion.VERSION_11 // 输出兼容Java 11
}
}
dependencies {
debugImplementation(libs.compose.ui.tooling) // debug模式下依赖compose调试工具
}
// 为 ohosArm64 目标配置依赖处理
val versionCatalog = extensions.getByType<VersionCatalogsExtension>().named("libs")
val cmpVersion = versionCatalog.findVersion("composeMultiplatform")
.orElseThrow { IllegalStateException("Missing version composeMultiplatform in version catalog") }
.requiredVersion
val skikoOverrideByCmpVersion = mapOf(
"1.9.2-ez-001" to "0.9.22.2-ez-001",
// 仅在需要强制的 CMP 版本这里新增
)
val skikoOhosOverride = skikoOverrideByCmpVersion[cmpVersion]
configurations.all {
val configName = name
if (configName.contains("ohos", ignoreCase = true)) {
incoming.afterResolve {
val resolvedSkiko = resolutionResult.allComponents
.mapNotNull { it.moduleVersion }
.firstOrNull { it.group == "org.jetbrains.skiko" && it.name == "skiko" }
logger.lifecycle(
"Resolved skiko for $configName: " +
(resolvedSkiko?.let { "${it.group}:${it.name}:${it.version}" } ?: "not found")
)
}
// exclude(group = "org.jetbrains.androidx.lifecycle")
// exclude(group = "org.jetbrains.androidx.savedstate")
}
resolutionStrategy {
eachDependency {
// 如果是 skiko 依赖,检查配置名称是否包含 ohos
if (requested.group == "org.jetbrains.skiko" && requested.name == "skiko") {
if (configName.contains("ohos", ignoreCase = true)) {
skikoOhosOverride?.let { useVersion(it) }
}
}
// 强制指定 androidx.collection 版本,避免冲突
if (requested.group == "androidx.collection" && requested.name == "collection") {
useVersion(libs.versions.androidx.collection.get())
}
}
}
exclude(group = "androidx.collection", module = "collection-jvm")
}
// Harmony App 输出目录(支持命令行 --harmonyAppPath)
val harmonyAppDir: File = run {
val cliPath = project.findProperty("harmonyAppPath") as String?
if (cliPath.isNullOrBlank()) {
// 默认:项目根目录 /harmonyApp
rootProject.file("harmonyApp")
} else {
// 命令行传入的路径
file(cliPath)
}
}
// 字符串首字母大写工具函数
fun String.capitalizeUS(): String = this.replaceFirstChar {
if (it.isLowerCase()) it.titlecase() else it.toString()
}
// 为不同类型(debug、release)OHOS构建注册Copy任务并发布到Harmony App目录
arrayOf("debug", "release").forEach { type ->
tasks.register<Copy>("publish${type.capitalizeUS()}BinariesToHarmonyApp") {
group = "harmony" // 归类到harmony任务组
dependsOn("link${type.capitalizeUS()}SharedOhosArm64") // 依赖于OHOS shared lib的链接任务
into(harmonyAppDir) // 输出目标目录
from("build/bin/ohosArm64/${type}Shared/libkn_api.h") { // 复制头文件
into("entry/src/main/cpp/include/") // 指定目录
}
from(project.file("build/bin/ohosArm64/${type}Shared/libkn.so")) { // 复制共享库文件
into("/entry/libs/arm64-v8a/") // 指定目标目录
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@android:style/Theme.Material.Light.NoActionBar">
<activity
android:exported="true"
android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
package com.dong.maxhap
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.runtime.Composable
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
enableEdgeToEdge()
super.onCreate(savedInstanceState)
setContent {
App()
}
}
}
package com.dong.maxhap
import android.os.Build
class AndroidPlatform : Platform {
override val name: String = "Android ${Build.VERSION.SDK_INT}"
}
actual fun getPlatform(): Platform = AndroidPlatform()
internal actual fun getPlatformDemoList(): List<PlatformDemoItem> = emptyList()
@androidx.compose.runtime.Composable
internal actual fun PlatformDemo(id: String) {
}
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<aapt:attr name="android:fillColor">
<gradient
android:endX="85.84757"
android:endY="92.4963"
android:startX="42.9492"
android:startY="49.59793"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
</vector>
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>
<resources>
<string name="app_name">MaxHap</string>
</resources>
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="450dp"
android:height="450dp"
android:viewportWidth="64"
android:viewportHeight="64">
<path
android:pathData="M56.25,18V46L32,60 7.75,46V18L32,4Z"
android:fillColor="#6075f2"/>
<path
android:pathData="m41.5,26.5v11L32,43V60L56.25,46V18Z"
android:fillColor="#6b57ff"/>
<path
android:pathData="m32,43 l-9.5,-5.5v-11L7.75,18V46L32,60Z">
<aapt:attr name="android:fillColor">
<gradient
android:centerX="23.131"
android:centerY="18.441"
android:gradientRadius="42.132"
android:type="radial">
<item android:offset="0" android:color="#FF5383EC"/>
<item android:offset="0.867" android:color="#FF7F52FF"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="M22.5,26.5 L32,21 41.5,26.5 56.25,18 32,4 7.75,18Z">
<aapt:attr name="android:fillColor">
<gradient
android:startX="44.172"
android:startY="4.377"
android:endX="17.973"
android:endY="34.035"
android:type="linear">
<item android:offset="0" android:color="#FF33C3FF"/>
<item android:offset="0.878" android:color="#FF5383EC"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="m32,21 l9.526,5.5v11L32,43 22.474,37.5v-11z"
android:fillColor="#000000"/>
</vector>
package com.dong.maxhap
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.safeContentPadding
import androidx.compose.material.Button
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@Composable
internal fun App() {
MaterialTheme {
// 使用 Page 类型的状态,修复类型推断报错
var page by remember { mutableStateOf<com.dong.maxhap.navigation.Page>(com.dong.maxhap.navigation.Page.Home) }
// 首页状态提升:滚动、搜索、分组展开状态
val listState = androidx.compose.foundation.lazy.rememberLazyListState()
var searchQuery by remember { mutableStateOf("") }
val expandedGroups = remember {
mutableStateMapOf<com.dong.maxhap.navigation.ComposeGroup, Boolean>().apply {
com.dong.maxhap.navigation.ComposeGroup.entries.forEach { put(it, true) }
}
}
Column(
modifier = Modifier
.safeContentPadding()
.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
) {
when (val p = page) {
is com.dong.maxhap.navigation.Page.Home -> {
HomeScreen(
onSelect = { demo ->
page = com.dong.maxhap.navigation.Page.Detail(demo)
},
listState = listState,
searchQuery = searchQuery,
onSearchChange = { searchQuery = it },
expandedGroups = expandedGroups
)
}
is com.dong.maxhap.navigation.Page.Detail -> {
DemoScreen(demo = p.demo, onBack = { page = com.dong.maxhap.navigation.Page.Home })
}
}
}
}
}
package com.dong.maxhap
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.dong.maxhap.navigation.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue
import com.dong.maxhap.demos.material.*
import com.dong.maxhap.demos.ui.UiBoxDemo
import com.dong.maxhap.demos.benchmark.*
import com.dong.maxhap.demos.foundation.FoundationBasicTextDemo
import com.dong.maxhap.demos.foundation.FoundationLazyColumnDemo
@Composable
internal fun HomeScreen(
onSelect: (com.dong.maxhap.navigation.ComponentDemo) -> Unit,
listState: androidx.compose.foundation.lazy.LazyListState,
searchQuery: String,
onSearchChange: (String) -> Unit,
expandedGroups: MutableMap<com.dong.maxhap.navigation.ComposeGroup, Boolean>
) {
val grouped = com.dong.maxhap.navigation.demosByGroup()
val filtered = grouped.mapValues { (_, demos) ->
if (searchQuery.isBlank()) demos
else demos.filter { d ->
d.title.contains(searchQuery, ignoreCase = true) ||
d.id.contains(searchQuery, ignoreCase = true)
}
}.filterValues { it.isNotEmpty() || searchQuery.isBlank() }
Column(
modifier = Modifier
.fillMaxSize()
.padding(horizontal = 8.dp)
) {
// 顶部固定搜索框(避免 iOS LazyColumn 首项兼容性问题)
Card(backgroundColor = MaterialTheme.colors.surface) {
OutlinedTextField(
value = searchQuery,
onValueChange = onSearchChange,
label = { Text("搜索") },
modifier = Modifier
.fillMaxWidth()
.padding(12.dp),
singleLine = true
)
}
Spacer(Modifier.height(12.dp))
androidx.compose.foundation.lazy.LazyColumn(
modifier = Modifier.fillMaxSize(),
state = listState,
contentPadding = PaddingValues(vertical = 12.dp),
verticalArrangement = Arrangement.spacedBy(12.dp)
) {
com.dong.maxhap.navigation.ComposeGroup.entries.forEach { group ->
val demos = filtered[group] ?: emptyList()
if (demos.isEmpty() && searchQuery.isNotBlank()) {
// 搜索无结果时该组隐藏
} else {
val expanded = expandedGroups[group] != false
item {
Card(
backgroundColor = Color.LightGray.copy(alpha = 0.3f), // surfaceVariant replacement
modifier = Modifier
.fillMaxWidth()
.clickable { expandedGroups[group] = !expanded }
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(12.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Column {
Text(
com.dong.maxhap.navigation.groupTitles[group] ?: group.name,
style = MaterialTheme.typography.h6
)
val countText =
if (searchQuery.isNotBlank()) "匹配:${demos.size}" else "共 ${demos.size} 项"
Text(countText, style = MaterialTheme.typography.caption)
}
Text(
text = if (expanded) "收起 ▾" else "展开 ▸",
color = MaterialTheme.colors.primary
)
}
}
}
if (expanded) {
items(demos) { demo ->
Card(backgroundColor = MaterialTheme.colors.surface) {
Row(
modifier = Modifier
.fillMaxWidth()
.clickable { onSelect(demo) }
.padding(16.dp), // Increased padding for better touch target
verticalAlignment = Alignment.CenterVertically
) {
Text(demo.title, style = MaterialTheme.typography.body1)
}
}
Divider()
}
}
}
}
}
}
}
@Composable
internal fun DemoScreen(demo: ComponentDemo, onBack: () -> Unit) {
Column(
modifier = Modifier
.fillMaxSize()
.padding(12.dp),
verticalArrangement = Arrangement.spacedBy(12.dp)
) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text(text = demo.title, style = MaterialTheme.typography.h5)
OutlinedButton(onClick = onBack) { Text("返回") }
}
Divider()
when (demo.id) {
// ui
"ui_box" -> UiBoxDemo()
// foundation
"foundation_basic_text" -> FoundationBasicTextDemo()
"foundation_lazy_column" -> FoundationLazyColumnDemo()
// benchmark
"benchmark_1500_text" -> Compose1500Text()
"benchmark_1500_view" -> ComposeView1500Page()
// material
"material_alert_dialog" -> AlertDialogSamples()
"material_app_bar" -> AppBarSamples()
"material_backdrop_scaffold" -> BackdropScaffoldSamples()
"material_badge" -> BadgeSamples()
"material_bottom_navigation" -> BottomNavigationSamples()
"material_bottom_sheet_scaffold" -> BottomSheetScaffoldSamples()
"material_button_samples" -> ButtonSamples()
"material_card_samples" -> CardSamples()
"material_content_alpha" -> ContentAlphaSamples()
"material_drawer_samples" -> DrawerSamples()
"material_elevation_samples" -> ElevationSamples()
"material_exposed_dropdown_menu" -> ExposedDropdownMenuSamples()
"material_fab_samples" -> FloatingActionButtonSamples()
"material_icon_button_samples" -> IconButtonSamples()
"material_list_samples" -> ListSamples()
"material_menu_samples" -> MenuSamples()
"material_modal_bottom_sheet" -> ModalBottomSheetSamples()
"material_navigation_rail" -> NavigationRailSample()
"material_progress_indicator" -> ProgressIndicatorSamples()
"material_pull_refresh" -> PullRefreshSamples()
"material_selection_controls" -> SelectionControlsSamples()
"material_slider_sample" -> SliderSample()
"material_surface_samples" -> SurfaceSamples()
"material_swipeable_samples" -> SwipeableSamples()
"material_swipe_to_dismiss" -> SwipeToDismissSamples()
"material_tab_samples" -> TabSamples()
"material_text_field_samples" -> TextFieldSamples()
"material_text_samples" -> TextSamples()
"material_theme_samples" -> ThemeSamples()
else -> {
if (demo.group == com.dong.maxhap.navigation.ComposeGroup.Platform) {
com.dong.maxhap.PlatformDemo(demo.id)
}
}
}
}
}
package com.dong.maxhap
class Greeting {
private val platform = getPlatform()
fun greet(): String {
return "Hello, ${platform.name}!"
}
}
\ No newline at end of file
package com.dong.maxhap
interface Platform {
val name: String
}
expect fun getPlatform(): Platform
internal data class PlatformDemoItem(val id: String, val title: String)
internal expect fun getPlatformDemoList(): List<PlatformDemoItem>
@androidx.compose.runtime.Composable
internal expect fun PlatformDemo(id: String)
package com.dong.maxhap.demos.benchmark
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
@Composable
internal fun Compose1500Text() {
Column(
modifier = Modifier
.verticalScroll(rememberScrollState())
.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally
) {
repeat(1500) { index ->
Text(
text = "Compose1500Text Item #$index",
fontSize = 16.sp,
modifier = Modifier
.width(300.dp)
.height(50.dp)
.border(1.dp, Color.Gray)
.padding(10.dp)
)
}
}
}
package com.dong.maxhap.demos.benchmark
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.unit.dp
import org.jetbrains.compose.resources.ExperimentalResourceApi
@OptIn(ExperimentalResourceApi::class)
@Composable
internal fun ComposeView1500Page() {
val loaded = remember { mutableStateOf(false) }
Column(
modifier = Modifier
.verticalScroll(rememberScrollState())
.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally
) {
repeat(1500) { index ->
Box(
modifier = Modifier
.size(300.dp, 100.dp)
.border(
width = 2.dp,
color = Color.Red,
)
.then(
if (index == 1499) Modifier.onGloballyPositioned {
loaded.value = true
//trace_tag_end()
} else Modifier
)
) {
Text(
text = "Item #$index",
)
}
}
}
if (loaded.value) {
println("页面加载完成 ✅")
}
}
\ No newline at end of file
package com.dong.maxhap.demos.foundation
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.text.BasicText
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
@Composable
internal fun FoundationBasicTextDemo() {
var text by remember { mutableStateOf("Hello Compose") }
var size by remember { mutableStateOf(18f) }
var colorToggle by remember { mutableStateOf(false) }
Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
OutlinedTextField(value = text, onValueChange = { text = it }, label = { Text("内容") })
Text("字体大小: ${size.toInt()}sp")
Slider(value = size, onValueChange = { size = it }, valueRange = 12f..48f)
Row(verticalAlignment = Alignment.CenterVertically) {
Checkbox(checked = colorToggle, onCheckedChange = { colorToggle = it })
Text("使用高亮颜色")
}
Box(
modifier = Modifier
.fillMaxWidth()
.background(MaterialTheme.colors.surface)
.padding(12.dp)
) {
BasicText(
text = text,
style = androidx.compose.ui.text.TextStyle(
fontSize = size.sp,
color = if (colorToggle) MaterialTheme.colors.primary else Color.Unspecified
)
)
}
}
}
package com.dong.maxhap.demos.foundation
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Slider
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
@Composable
internal fun FoundationLazyColumnDemo() {
var count by remember { mutableStateOf(10) }
var spaced by remember { mutableStateOf(4) }
Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
Text("条目数量: $count")
Slider(value = count.toFloat(), onValueChange = { count = it.toInt() }, valueRange = 1f..50f)
Text("条目间距: ${spaced}dp")
Slider(value = spaced.toFloat(), onValueChange = { spaced = it.toInt() }, valueRange = 0f..24f)
LazyColumn(
modifier = Modifier
.fillMaxWidth()
.height(220.dp)
.background(MaterialTheme.colors.surface),
contentPadding = PaddingValues(8.dp),
verticalArrangement = Arrangement.spacedBy(spaced.dp)
) {
items((1..count).toList()) { idx ->
Box(
modifier = Modifier
.fillMaxWidth()
.height(40.dp)
.background(MaterialTheme.colors.secondary),
contentAlignment = Alignment.Center
) {
Text("Item #$idx")
}
}
}
}
}
package com.dong.maxhap.demos.material
import androidx.compose.material.AlertDialog
import androidx.compose.material.Text
import androidx.compose.material.TextButton
import androidx.compose.runtime.*
@Composable
internal fun AlertDialogSamples() {
var open by remember { mutableStateOf(true) }
var dismissOnClickOutside by remember { mutableStateOf(true) }
var dismissOnBackPress by remember { mutableStateOf(true) }
if (open) {
AlertDialog(
onDismissRequest = {
if (dismissOnBackPress) open = false
},
title = { Text("AlertDialog") },
text = { Text("展示标题、内容、确认/取消按钮,以及关闭行为。") },
confirmButton = {
TextButton(onClick = { open = false }) { Text("确认") }
},
dismissButton = {
TextButton(onClick = { if (dismissOnClickOutside) open = false }) { Text("取消") }
}
)
}
}
package com.dong.maxhap.demos.material
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.foundation.layout.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
@Composable
internal fun AppBarSamples() {
var title by remember { mutableStateOf("TopAppBar 标题") }
var showActions by remember { mutableStateOf(true) }
var elevation by remember { mutableStateOf(4f) }
Column {
TopAppBar(
title = { Text(title) },
actions = {
if (showActions) {
TextButton(onClick = { title = "点击了 Action" }) { Text("Action") }
}
},
elevation = elevation.dp
)
Spacer(Modifier.height(8.dp))
BottomAppBar {
Text("BottomAppBar")
}
Column(Modifier.padding(12.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
OutlinedTextField(value = title, onValueChange = { title = it }, label = { Text("标题") })
Text("阴影: ${elevation.toInt()}dp")
Slider(value = elevation, onValueChange = { elevation = it }, valueRange = 0f..16f)
Row {
Checkbox(checked = showActions, onCheckedChange = { showActions = it })
Text("显示 Action")
}
}
}
}
package com.dong.maxhap.demos.material
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.foundation.layout.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.launch
@OptIn(ExperimentalMaterialApi::class)
@Composable
internal fun BackdropScaffoldSamples() {
val scaffoldState = rememberBackdropScaffoldState(BackdropValue.Concealed)
val scope = rememberCoroutineScope()
var clicks by remember { mutableStateOf(0) }
BackdropScaffold(
scaffoldState = scaffoldState,
appBar = { TopAppBar(title = { Text("BackdropScaffold") }) },
backLayerContent = {
Column(Modifier.fillMaxWidth().padding(12.dp)) {
Text("后层内容")
Button(onClick = { clicks++ }) { Text("点击: $clicks") }
}
},
frontLayerContent = {
Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
Button(
onClick = {
scope.launch {
if (scaffoldState.isConcealed) scaffoldState.reveal() else scaffoldState.conceal()
}
}
) { Text(if (scaffoldState.isConcealed) "展开前层" else "收起前层") }
}
}
)
}
package com.dong.maxhap.demos.material
import androidx.compose.ui.Modifier
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.foundation.layout.*
import androidx.compose.ui.unit.dp
@Composable
internal fun BadgeSamples() {
var count by remember { mutableStateOf(3) }
BadgedBox(badge = { Text("$count") }) {
Text("带徽章的内容")
}
Row(Modifier.padding(12.dp), horizontalArrangement = Arrangement.spacedBy(8.dp)) {
Button(onClick = { count++ }) { Text("+1") }
Button(onClick = { count = 0 }) { Text("清零") }
}
}
package com.dong.maxhap.demos.material
import androidx.compose.material.*
import androidx.compose.runtime.*
@Composable
internal fun BottomNavigationSamples() {
var selected by remember { mutableStateOf(0) }
BottomNavigation {
listOf("主页", "消息", "设置").forEachIndexed { index, label ->
BottomNavigationItem(
selected = selected == index,
onClick = { selected = index },
icon = { },
label = { Text(label) }
)
}
}
}
package com.dong.maxhap.demos.material
import androidx.compose.ui.Modifier
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.foundation.layout.*
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.launch
@OptIn(ExperimentalMaterialApi::class)
@Composable
internal fun BottomSheetScaffoldSamples() {
val sheetState = rememberBottomSheetScaffoldState()
val scope = rememberCoroutineScope()
BottomSheetScaffold(
scaffoldState = sheetState,
sheetContent = {
Column(Modifier.padding(12.dp)) {
Text("BottomSheet 内容")
Text("可在此添加交互与属性")
}
},
sheetPeekHeight = 64.dp
) { padding ->
Column(Modifier.padding(padding).padding(12.dp)) {
Button(onClick = {
scope.launch {
val state = sheetState.bottomSheetState
if (state.isCollapsed) state.expand() else state.collapse()
}
}) { Text("展开/收起 BottomSheet") }
}
}
}
package com.dong.maxhap.demos.material
import androidx.compose.material.Button
import androidx.compose.material.ButtonDefaults
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.graphics.Color
@Composable
internal fun ButtonSamples() {
var enabled by remember { mutableStateOf(true) }
var clicks by remember { mutableStateOf(0) }
Button(
enabled = enabled,
onClick = { clicks++ },
colors = ButtonDefaults.buttonColors(backgroundColor = Color(0xFF4CAF50), contentColor = Color.White)
) {
Text("Material Button 点击: $clicks")
}
}
package com.dong.maxhap.demos.material
import androidx.compose.material.Card
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
@Composable
internal fun CardSamples() {
var elevation by remember { mutableStateOf(4f) }
Card(elevation = elevation.dp) {
Column(Modifier.padding(12.dp)) {
Text("Material Card 标题")
Text("阴影 elevation: ${elevation.toInt()}dp")
}
}
}
package com.dong.maxhap.demos.material
import androidx.compose.ui.Modifier
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.foundation.layout.*
import androidx.compose.ui.unit.dp
@Composable
internal fun ContentAlphaSamples() {
var disabled by remember { mutableStateOf(false) }
Column(Modifier.padding(12.dp)) {
Row {
Checkbox(checked = disabled, onCheckedChange = { disabled = it })
Text("使用 ContentAlpha.disabled")
}
CompositionLocalProvider(LocalContentAlpha provides if (disabled) ContentAlpha.disabled else ContentAlpha.high) {
Text("受 ContentAlpha 控制的文本")
}
Text("不受影响的文本")
}
}
package com.dong.maxhap.demos.material
import androidx.compose.ui.Modifier
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.foundation.layout.*
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.launch
@Composable
internal fun DrawerSamples() {
val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed)
val scope = rememberCoroutineScope()
ModalDrawer(
drawerState = drawerState,
drawerContent = {
Column(Modifier.padding(12.dp)) {
Text("Drawer 内容")
Button(onClick = { scope.launch { drawerState.close() } }) { Text("关闭") }
}
}
) {
Column(Modifier.padding(12.dp)) {
Button(onClick = { scope.launch { drawerState.open() } }) { Text("打开 Drawer") }
}
}
}
package com.dong.maxhap.demos.material
import androidx.compose.ui.Modifier
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.material.Slider
import androidx.compose.runtime.*
import androidx.compose.foundation.layout.*
import androidx.compose.ui.unit.dp
@Composable
internal fun ElevationSamples() {
var elevation by remember { mutableStateOf(4f) }
Column(Modifier.padding(12.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
Text("阴影: ${elevation.toInt()}dp")
Slider(value = elevation, onValueChange = { elevation = it }, valueRange = 0f..24f)
Surface(elevation = elevation.dp) {
Box(Modifier.size(120.dp).padding(12.dp)) { Text("Surface with elevation") }
}
}
}
package com.dong.maxhap.demos.material
import androidx.compose.ui.Modifier
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.foundation.layout.*
import androidx.compose.ui.unit.dp
@OptIn(ExperimentalMaterialApi::class)
@Composable
internal fun ExposedDropdownMenuSamples() {
val options = listOf("选项 A", "选项 B", "选项 C")
var expanded by remember { mutableStateOf(false) }
var selected by remember { mutableStateOf(options.first()) }
ExposedDropdownMenuBox(expanded = expanded, onExpandedChange = { expanded = !expanded }) {
OutlinedTextField(
value = selected, onValueChange = {}, readOnly = true, label = { Text("选择项") }
)
ExposedDropdownMenu(expanded = expanded, onDismissRequest = { expanded = false }) {
options.forEach { option ->
DropdownMenuItem(onClick = { selected = option; expanded = false }) {
Text(option)
}
}
}
}
Spacer(Modifier.height(8.dp))
Text("当前选择: $selected")
}
package com.dong.maxhap.demos.material
import androidx.compose.material.FloatingActionButton
import androidx.compose.material.Text
import androidx.compose.runtime.*
@Composable
internal fun FloatingActionButtonSamples() {
var clicks by remember { mutableStateOf(0) }
FloatingActionButton(onClick = { clicks++ }) { Text("$clicks") }
}
package com.dong.maxhap.demos.material
import androidx.compose.material.IconButton
import androidx.compose.material.Text
import androidx.compose.runtime.*
@Composable
internal fun IconButtonSamples() {
var clicks by remember { mutableStateOf(0) }
IconButton(onClick = { clicks++ }) {
Text("★")
}
Text("点击次数: $clicks")
}
@file:OptIn(androidx.compose.material.ExperimentalMaterialApi::class)
package com.dong.maxhap.demos.material
import androidx.compose.material.ListItem
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.foundation.lazy.*
import androidx.compose.foundation.layout.*
import androidx.compose.ui.unit.dp
@Composable
internal fun ListSamples() {
val items = (1..20).map { "Item $it" }
LazyColumn(contentPadding = PaddingValues(8.dp), verticalArrangement = Arrangement.spacedBy(4.dp)) {
items(items) { label ->
ListItem(text = { Text(label) }, secondaryText = { Text("副标题") })
}
}
}
package com.dong.maxhap.demos.material
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.foundation.layout.*
@Composable
internal fun MenuSamples() {
var expanded by remember { mutableStateOf(false) }
Column {
Button(onClick = { expanded = true }) { Text("打开菜单") }
DropdownMenu(expanded = expanded, onDismissRequest = { expanded = false }) {
DropdownMenuItem(onClick = { expanded = false }) { Text("菜单项 1") }
DropdownMenuItem(onClick = { expanded = false }) { Text("菜单项 2") }
}
}
}
package com.dong.maxhap.demos.material
import androidx.compose.ui.Modifier
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.foundation.layout.*
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.launch
@OptIn(ExperimentalMaterialApi::class)
@Composable
internal fun ModalBottomSheetSamples() {
val sheetState = rememberModalBottomSheetState(ModalBottomSheetValue.Hidden)
val scope = rememberCoroutineScope()
ModalBottomSheetLayout(
sheetState = sheetState,
sheetContent = { Column(Modifier.padding(12.dp)) { Text("ModalBottomSheet 内容") } }
) {
Column(Modifier.padding(12.dp)) {
Button(onClick = { scope.launch { sheetState.show() } }) { Text("显示") }
Spacer(Modifier.height(8.dp))
Button(onClick = { scope.launch { sheetState.hide() } }) { Text("隐藏") }
}
}
}
package com.dong.maxhap.demos.material
import androidx.compose.material.NavigationRail
import androidx.compose.material.NavigationRailItem
import androidx.compose.material.Text
import androidx.compose.runtime.*
@Composable
internal fun NavigationRailSample() {
var selected by remember { mutableStateOf(0) }
NavigationRail {
listOf("主页", "消息", "设置").forEachIndexed { index, label ->
NavigationRailItem(
selected = selected == index,
onClick = { selected = index },
icon = { Text("★") },
label = { Text(label) }
)
}
}
}
package com.dong.maxhap.demos.material
import androidx.compose.material.CircularProgressIndicator
import androidx.compose.material.LinearProgressIndicator
import androidx.compose.runtime.*
import androidx.compose.foundation.layout.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
@Composable
internal fun ProgressIndicatorSamples() {
var progress by remember { mutableStateOf(0.3f) }
Column(Modifier.fillMaxWidth().padding(12.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
LinearProgressIndicator(progress = progress, modifier = Modifier.fillMaxWidth())
CircularProgressIndicator(progress = progress)
}
}
package com.dong.maxhap.demos.material
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.foundation.layout.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
@Composable
internal fun PullRefreshSamples() {
var refreshing by remember { mutableStateOf(false) }
val scope = rememberCoroutineScope()
Column(Modifier.padding(12.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
Button(onClick = {
scope.launch {
refreshing = true
delay(1000)
refreshing = false
}
}) { Text("手动触发刷新") }
if (refreshing) LinearProgressIndicator(Modifier.fillMaxWidth())
Text(if (refreshing) "刷新中..." else "刷新完成")
}
}
package com.dong.maxhap.demos.material
import androidx.compose.ui.Modifier
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.foundation.layout.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.unit.dp
@Composable
internal fun SelectionControlsSamples() {
var checked by remember { mutableStateOf(true) }
var selected by remember { mutableStateOf(0) }
var switchOn by remember { mutableStateOf(true) }
Column(Modifier.padding(12.dp)) {
Row(verticalAlignment = Alignment.CenterVertically) {
Checkbox(checked = checked, onCheckedChange = { checked = it })
Text("Checkbox: ${if (checked) "选中" else "未选"}")
}
Row(verticalAlignment = androidx.compose.ui.Alignment.CenterVertically) {
RadioButton(selected = selected == 0, onClick = { selected = 0 })
RadioButton(selected = selected == 1, onClick = { selected = 1 })
Text("Radio 选择: $selected")
}
Row(verticalAlignment = androidx.compose.ui.Alignment.CenterVertically) {
Switch(checked = switchOn, onCheckedChange = { switchOn = it })
Text("Switch: ${if (switchOn) "" else ""}")
}
}
}
package com.dong.maxhap.demos.material
import androidx.compose.ui.Modifier
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.unit.dp
import androidx.compose.foundation.layout.*
@Composable
internal fun SliderSample() {
var value by remember { mutableStateOf(0.5f) }
Column(Modifier.padding(12.dp)) {
Text("当前值: ${kotlin.math.round(value * 10.0f) / 10.0f}")
Slider(value = value, onValueChange = { value = it }, valueRange = 0f..1f, steps = 4)
}
}
package com.dong.maxhap.demos.material
import androidx.compose.ui.Modifier
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
@Composable
internal fun SurfaceSamples() {
var elevation by remember { mutableStateOf(6f) }
var rounded by remember { mutableStateOf(12f) }
var bg by remember { mutableStateOf(Color(0xFFE0F7FA)) }
Column(Modifier.padding(12.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
Surface(shape = RoundedCornerShape(rounded.dp), elevation = elevation.dp, color = bg) {
Column(Modifier.padding(12.dp)) {
Text("Surface 属性演示")
Text("elevation=${elevation.toInt()} shape=${rounded.toInt()} color=${bg}")
}
}
Text("elevation: ${elevation.toInt()}dp"); Slider(value = elevation, onValueChange = { elevation = it }, valueRange = 0f..24f)
Text("圆角: ${rounded.toInt()}dp"); Slider(value = rounded, onValueChange = { rounded = it }, valueRange = 0f..32f)
}
}
package com.dong.maxhap.demos.material
import androidx.compose.ui.Modifier
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.foundation.layout.*
import androidx.compose.ui.unit.dp
@OptIn(ExperimentalMaterialApi::class)
@Composable
internal fun SwipeToDismissSamples() {
val dismissState = rememberDismissState()
SwipeToDismiss(
state = dismissState,
background = {
Box(Modifier.fillMaxWidth().height(64.dp)) { Text("滑动删除背景") }
},
dismissContent = {
Box(Modifier.fillMaxWidth().height(64.dp)) { Text("可滑动删除内容") }
}
)
Text("当前状态: ${dismissState.currentValue}")
}
@file:OptIn(androidx.compose.material.ExperimentalMaterialApi::class)
package com.dong.maxhap.demos.material
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.DismissDirection
import androidx.compose.material.DismissValue
import androidx.compose.material.Divider
import androidx.compose.material.ListItem
import androidx.compose.material.SwipeToDismiss
import androidx.compose.material.Text
import androidx.compose.material.rememberDismissState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
@Composable
internal fun SwipeableSamples() {
val mails = remember { mutableStateListOf("Mail 1", "Mail 2", "Mail 3") }
LazyColumn(
modifier = Modifier.fillMaxSize(),
contentPadding = PaddingValues(vertical = 8.dp)
) {
items(mails, key = { mail -> mail }) { mail ->
val dismissState = rememberDismissState(
confirmStateChange = { newValue: DismissValue ->
if (newValue == DismissValue.DismissedToEnd || newValue == DismissValue.DismissedToStart) {
mails.remove(mail)
}
true
}
)
SwipeToDismiss(
state = dismissState,
directions = setOf(
DismissDirection.StartToEnd,
DismissDirection.EndToStart
),
background = {
val bgColor = when (dismissState.targetValue) {
DismissValue.Default -> Color.Transparent
DismissValue.DismissedToEnd -> Color(0xFF2E7D32) // Archive
DismissValue.DismissedToStart -> Color(0xFFC62828) // Delete
}
Box(
modifier = Modifier
.fillMaxWidth()
.height(64.dp)
.background(bgColor),
contentAlignment = Alignment.CenterStart
) {
Text(
text = if (dismissState.targetValue == DismissValue.DismissedToEnd) "Archive" else "Delete",
color = Color.White,
fontWeight = FontWeight.Bold,
modifier = Modifier.padding(start = 16.dp)
)
}
},
dismissContent = {
ListItem(
text = { Text(mail) },
secondaryText = { Text("Swipe me left or right") }
)
}
)
Divider()
}
}
}
package com.dong.maxhap.demos.material
import androidx.compose.material.Tab
import androidx.compose.material.TabRow
import androidx.compose.material.Text
import androidx.compose.runtime.*
@Composable
internal fun TabSamples() {
var selectedTab by remember { mutableStateOf(0) }
val tabs = listOf("Tab1", "Tab2", "Tab3")
TabRow(selectedTabIndex = selectedTab) {
tabs.forEachIndexed { index, title ->
Tab(selected = selectedTab == index, onClick = { selectedTab = index }, text = { Text(title) })
}
}
}
package com.dong.maxhap.demos.material
import androidx.compose.material.OutlinedTextField
import androidx.compose.material.Text
import androidx.compose.runtime.*
@Composable
internal fun TextFieldSamples() {
var text by remember { mutableStateOf("") }
var enabled by remember { mutableStateOf(true) }
var isError by remember { mutableStateOf(false) }
OutlinedTextField(
value = text,
onValueChange = { text = it },
enabled = enabled,
isError = isError,
label = { Text("Label") },
placeholder = { Text("Placeholder") }
)
}
package com.dong.maxhap.demos.material
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
@Composable
internal fun TextSamples() {
var size by remember { mutableStateOf(16f) }
var bold by remember { mutableStateOf(false) }
Column(Modifier.padding(12.dp)) {
Text("普通文本", fontSize = size.sp, fontWeight = if (bold) FontWeight.Bold else FontWeight.Normal)
Text("副标题", style = MaterialTheme.typography.subtitle1)
Text("标题", style = MaterialTheme.typography.h6)
Text("正文", style = MaterialTheme.typography.body1)
Text("按钮", style = MaterialTheme.typography.button)
Text("说明文字", style = MaterialTheme.typography.caption)
Spacer(Modifier.height(8.dp))
Text("字体大小: ${size.toInt()}sp"); Slider(value = size, onValueChange = { size = it }, valueRange = 12f..36f)
Row { Checkbox(checked = bold, onCheckedChange = { bold = it }); Text("加粗") }
}
}
package com.dong.maxhap.demos.material
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.*
@Composable
internal fun ThemeSamples() {
// 演示 MaterialTheme 的基本用法;完整主题切换后续扩展
Text("当前 MaterialTheme.typography.body1 示例文本")
}
package com.dong.maxhap.demos.ui
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.FlowRow
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
@OptIn(ExperimentalLayoutApi::class)
@Composable
internal fun UiBoxDemo() {
val alignments = listOf(
Alignment.TopStart, Alignment.TopCenter, Alignment.TopEnd,
Alignment.CenterStart, Alignment.Center, Alignment.CenterEnd,
Alignment.BottomStart, Alignment.BottomCenter, Alignment.BottomEnd
)
var selected by remember { mutableStateOf(Alignment.Center) }
Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
Text("Alignment")
FlowRow(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
alignments.forEach { a ->
val label = a.toString().removePrefix("Alignment.")
if (selected == a) {
Button(onClick = { selected = a }) {
Text(label)
}
} else {
OutlinedButton(onClick = { selected = a }) {
Text(label)
}
}
}
}
Box(
modifier = Modifier
.size(220.dp)
.background(MaterialTheme.colors.surface) // surfaceVariant -> surface
) {
Box(
modifier = Modifier
.size(48.dp)
.align(selected)
.background(MaterialTheme.colors.primary) // primary -> primary
)
}
}
}
package com.dong.maxhap.navigation
enum class ComposeGroup {
Ui, Foundation, Material, Benchmark, Platform
}
data class ComponentDemo(
val id: String,
val title: String,
val group: ComposeGroup
)
val componentDemos: List<ComponentDemo> = listOf(
// ui
ComponentDemo("ui_box", "Box", ComposeGroup.Ui),
// foundation
ComponentDemo("foundation_basic_text", "BasicText", ComposeGroup.Foundation),
ComponentDemo("foundation_lazy_column", "LazyColumn", ComposeGroup.Foundation),
// material 组:新增完整清单
ComponentDemo("material_alert_dialog", "AlertDialogSample", ComposeGroup.Material),
ComponentDemo("material_app_bar", "AppBarSamples", ComposeGroup.Material),
ComponentDemo("material_backdrop_scaffold", "BackdropScaffoldSamples", ComposeGroup.Material),
ComponentDemo("material_badge", "BadgeSamples", ComposeGroup.Material),
ComponentDemo("material_bottom_navigation", "BottomNavigationSamples", ComposeGroup.Material),
ComponentDemo("material_bottom_sheet_scaffold", "BottomSheetScaffoldSamples", ComposeGroup.Material),
ComponentDemo("material_button_samples", "ButtonSamples", ComposeGroup.Material),
ComponentDemo("material_card_samples", "CardSamples", ComposeGroup.Material),
ComponentDemo("material_chip_samples", "ChipSamples", ComposeGroup.Material),
ComponentDemo("material_content_alpha", "ContentAlphaSamples", ComposeGroup.Material),
ComponentDemo("material_drawer_samples", "DrawerSamples", ComposeGroup.Material),
ComponentDemo("material_elevation_samples", "ElevationSamples", ComposeGroup.Material),
ComponentDemo("material_exposed_dropdown_menu", "ExposedDropdownMenuSamples", ComposeGroup.Material),
ComponentDemo("material_fab_samples", "FloatingActionButtonSamples", ComposeGroup.Material),
ComponentDemo("material_icon_button_samples", "IconButtonSamples", ComposeGroup.Material),
ComponentDemo("material_list_samples", "ListSamples", ComposeGroup.Material),
ComponentDemo("material_menu_samples", "MenuSamples", ComposeGroup.Material),
ComponentDemo("material_modal_bottom_sheet", "ModalBottomSheetSamples", ComposeGroup.Material),
ComponentDemo("material_navigation_rail", "NavigationRailSample", ComposeGroup.Material),
ComponentDemo("material_progress_indicator", "ProgressIndicatorSamples", ComposeGroup.Material),
ComponentDemo("material_pull_refresh", "PullRefreshSamples", ComposeGroup.Material),
ComponentDemo("material_scaffold_samples", "ScaffoldSamples", ComposeGroup.Material),
ComponentDemo("material_selection_controls", "SelectionControlsSamples", ComposeGroup.Material),
ComponentDemo("material_slider_sample", "SliderSample", ComposeGroup.Material),
ComponentDemo("material_surface_samples", "SurfaceSamples", ComposeGroup.Material),
ComponentDemo("material_swipeable_samples", "SwipeableSamples", ComposeGroup.Material),
ComponentDemo("material_swipe_to_dismiss", "SwipeToDismissSamples", ComposeGroup.Material),
ComponentDemo("material_tab_samples", "TabSamples", ComposeGroup.Material),
ComponentDemo("material_text_field_samples", "TextFieldSamples", ComposeGroup.Material),
ComponentDemo("material_text_samples", "TextSamples", ComposeGroup.Material),
ComponentDemo("material_theme_samples", "ThemeSamples", ComposeGroup.Material),
// benchmark
ComponentDemo("benchmark_1500_text", "1500 Text", ComposeGroup.Benchmark),
ComponentDemo("benchmark_1500_view", "1500 View", ComposeGroup.Benchmark),
)
val groupTitles: Map<ComposeGroup, String> = mapOf(
ComposeGroup.Ui to "compose.ui",
ComposeGroup.Foundation to "compose.foundation",
ComposeGroup.Material to "compose.material",
ComposeGroup.Platform to "Platform",
)
fun demosByGroup(): Map<ComposeGroup, List<ComponentDemo>> {
val standardDemos = ComposeGroup.entries.filter { it != ComposeGroup.Platform }
.associateWith { g -> componentDemos.filter { it.group == g } }
.toMutableMap()
val platformDemos = com.dong.maxhap.getPlatformDemoList().map {
ComponentDemo(
id = it.id,
title = it.title,
group = ComposeGroup.Platform
)
}
if (platformDemos.isNotEmpty()) {
standardDemos[ComposeGroup.Platform] = platformDemos
}
return standardDemos
}
fun demosJson(): String = buildString {
append('[')
componentDemos.forEachIndexed { index, demo ->
if (index > 0) append(',')
append("{\"id\":\"")
append(jsonEscape(demo.id))
append("\",\"title\":\"")
append(jsonEscape(demo.title))
append("\",\"group\":\"")
append(demo.group.name)
append("\"}")
}
append(']')
}
fun groupTitlesJson(): String = buildString {
append('{')
ComposeGroup.entries.forEachIndexed { index, group ->
if (index > 0) append(',')
append('"')
append(group.name)
append("\":\"")
append(jsonEscape(groupTitles[group] ?: group.name))
append('"')
}
append('}')
}
private fun jsonEscape(input: String): String = buildString(input.length) {
input.forEach { ch ->
when (ch) {
'\\' -> append("\\\\")
'"' -> append("\\\"")
'\n' -> append("\\n")
'\r' -> append("\\r")
'\t' -> append("\\t")
else -> append(ch)
}
}
}
sealed interface Page {
data object Home : Page
data class Detail(val demo: ComponentDemo) : Page
}
package com.dong.maxhap
import kotlin.test.Test
import kotlin.test.assertEquals
class ComposeAppCommonTest {
@Test
fun example() {
assertEquals(3, 1 + 2)
}
}
\ No newline at end of file
package com.dong.maxhap
import androidx.compose.ui.window.ComposeUIViewController
fun MainViewController() = ComposeUIViewController { App() }
package com.dong.maxhap
import platform.UIKit.UIDevice
class IOSPlatform: Platform {
override val name: String = UIDevice.currentDevice.systemName() + " " + UIDevice.currentDevice.systemVersion
}
actual fun getPlatform(): Platform = IOSPlatform()
internal actual fun getPlatformDemoList(): List<PlatformDemoItem> = emptyList()
@androidx.compose.runtime.Composable
internal actual fun PlatformDemo(id: String) {
}
\ No newline at end of file
#ifndef GLOBAL_RAW_FILE_H
#define GLOBAL_RAW_FILE_H
#ifdef __cplusplus
extern "C" {
#endif
struct RawFile;
typedef struct RawFile RawFile;
int OH_ResourceManager_ReadRawFile(const RawFile *rawFile, void *buf, size_t length);
long OH_ResourceManager_GetRawFileSize(RawFile *rawFile);
void OH_ResourceManager_CloseRawFile(RawFile *rawFile);
#ifdef __cplusplus
};
#endif
/** @} */
#endif // GLOBAL_RAW_FILE_H
#ifndef GLOBAL_NATIVE_RESOURCE_MANAGER_H
#define GLOBAL_NATIVE_RESOURCE_MANAGER_H
#include "napi/native_api.h"
#include "raw_file.h"
#ifdef __cplusplus
extern "C" {
#endif
struct NativeResourceManager;
typedef struct NativeResourceManager NativeResourceManager;
NativeResourceManager *OH_ResourceManager_InitNativeResourceManager(napi_env env, napi_value jsResMgr);
void OH_ResourceManager_ReleaseNativeResourceManager(NativeResourceManager *resMgr);
RawFile *OH_ResourceManager_OpenRawFile(const NativeResourceManager *mgr, const char *fileName);
#ifdef __cplusplus
};
#endif
/** @} */
#endif // GLOBAL_NATIVE_RESOURCE_MANAGER_H
package = platform.resource
headers = raw_file_manager.h raw_file.h
package com.dong.maxhap
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.arkui.ArkUIView
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.interop.AdaptiveParams
import androidx.compose.ui.interop.InteropContainer
import androidx.compose.ui.napi.JsObject
import androidx.compose.ui.napi.js
private val NoOp: Any.() -> Unit = {}
@Composable
internal fun ArkUIView(
name: String,
modifier: Modifier,
parameter: JsObject = js(),
update: (JsObject) -> Unit = NoOp,
background: Color = Color.Unspecified,
updater: (ArkUIView) -> Unit = NoOp,
onCreate: (ArkUIView) -> Unit = NoOp,
onRelease: (ArkUIView) -> Unit = NoOp,
interactive: Boolean = true,
adaptiveParams: AdaptiveParams? = null,
tag: String? = null,
container: InteropContainer = InteropContainer.BACK
) = androidx.compose.ui.interop.ArkUIView(
name = name,
modifier = modifier,
parameter = parameter,
update = update,
background = background,
updater = updater,
onCreate = onCreate,
onRelease = onRelease,
interactive = interactive,
adaptiveParams = adaptiveParams,
tag = tag,
container = container,
)
package com.dong.maxhap
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.napi.js
import androidx.compose.ui.unit.dp
@Composable
internal fun InteropListNested() {
LazyColumn(Modifier.fillMaxSize()) {
items(20) { index ->
when {
index == 3 -> {
// Nested Vertical List (ArkUI)
ArkUIView(
name = "verticalList",
modifier = Modifier.fillMaxWidth().height(300.dp).background(Color.LightGray),
parameter = js { }
)
}
index == 7 -> {
// Horizontal List (ArkUI) - assuming horizontalList exists and works similar
ArkUIView(
name = "horizontalList",
modifier = Modifier.fillMaxWidth().height(150.dp).background(Color.LightGray),
parameter = js { }
)
}
index % 3 == 0 -> {
// Button (ArkUI)
ArkUIView(
name = "button",
modifier = Modifier.fillMaxWidth().height(60.dp),
parameter = js {
"text"("ArkUI Button $index")
"backgroundColor"("#FF0000FF")
}
)
}
else -> {
// Compose Text
Text("Compose Item $index", Modifier.padding(16.dp))
}
}
}
}
}
package com.dong.maxhap
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.napi.js
import androidx.compose.ui.unit.dp
@Composable
internal fun InteropListSimple() {
Box {
Column(Modifier.background(Color.LightGray).fillMaxSize()) {
LazyColumn(Modifier.background(Color.Red).fillMaxSize()) {
items(80) { index ->
Column {
ArkUIView(
name = "label",
modifier = Modifier.width(250.dp).height(100.dp),
parameter = js {
"text"("ArkUI Button $index")
"backgroundColor"("#FF0000FF")
},
)
Button({
println("Compose Button $index clicked")
}, modifier = Modifier.height(30.dp).fillMaxWidth()) {
Text("Compose Button $index")
}
}
}
}
}
}
}
package com.dong.maxhap
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.width
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.napi.js
import androidx.compose.ui.unit.dp
@Composable
internal fun InteropRenderOrder() {
var interLayer by remember { mutableStateOf(false) }
Column {
Box {
ArkUIView(
"layer", Modifier.width(400.dp).height(300.dp),
js {
"text"("1")
"backgroundColor"("#FF0000FF")
},
)
ArkUIView(
"layer", Modifier.width(350.dp).height(250.dp),
js {
"text"("2")
"backgroundColor"("#FF00FF00")
},
)
if (interLayer) {
ArkUIView(
"layer", Modifier.width(300.dp).height(200.dp),
js {
"text"("3")
"backgroundColor"("#FFFF0000")
},
)
}
ArkUIView(
"layer", Modifier.width(250.dp).height(150.dp),
js {
"text"("4")
"backgroundColor"("#FF00FFFF")
},
)
ArkUIView(
"layer", Modifier.width(200.dp).height(100.dp),
js {
"text"("5")
"backgroundColor"("#FFFFFF00")
},
)
}
Button({ interLayer = !interLayer }) {
Text("Show / Hide")
}
}
}
package com.dong.maxhap
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.napi.asString
import androidx.compose.ui.napi.js
import androidx.compose.ui.unit.dp
import kotlinx.cinterop.ExperimentalForeignApi
@OptIn(ExperimentalForeignApi::class)
@Composable
internal fun InteropTextInput() {
Column(
Modifier
.fillMaxWidth()
.fillMaxHeight()
.verticalScroll(rememberScrollState())
.padding(30.dp)
) {
var inputText by remember { mutableStateOf("混排状态变量双向通信 输入文本...") }
val state = remember(inputText) {
js { "text"(inputText) }
}
ArkUIView(
name = "textInput",
modifier = Modifier.width(450.dp).wrapContentHeight(),
parameter = state,
update = {
inputText = it["text"].asString().toString()
}
)
Spacer(modifier = Modifier.height(50.dp))
Text(text = "Compose组件更新:", color = Color.Gray)
Text(
text = inputText,
modifier = Modifier.fillMaxWidth()
.border(width = 1.dp, color = Color.Gray)
.padding(10.dp)
)
Button(onClick = { inputText += "[文本]" }) {
Text("Append Text")
}
}
}
package com.dong.maxhap
import androidx.compose.ui.window.ComposeArkUIViewController
import kotlinx.cinterop.ExperimentalForeignApi
import kotlinx.coroutines.initMainHandler
import platform.ohos.napi_env
import platform.ohos.napi_value
import kotlin.experimental.ExperimentalNativeApi
@OptIn(ExperimentalNativeApi::class, ExperimentalForeignApi::class)
@CName("MainArkUIViewController")
fun MainArkUIViewController(env: napi_env): napi_value {
initMainHandler(env)
return ComposeArkUIViewController(env) {
App()
}
}
package com.dong.maxhap
class OhosPlatform : Platform {
override val name: String = "HarmonyOS"
}
actual fun getPlatform(): Platform = OhosPlatform()
internal actual fun getPlatformDemoList(): List<PlatformDemoItem> = listOf(
PlatformDemoItem("interop_list_nested", "混排嵌滑"),
PlatformDemoItem("interop_list_simple", "混排列表"),
PlatformDemoItem("interop_render_order", "混排层级"),
PlatformDemoItem("interop_text_input", "混排输入"),
)
@androidx.compose.runtime.Composable
internal actual fun PlatformDemo(id: String) {
when (id) {
"interop_list_nested" -> InteropListNested()
"interop_list_simple" -> InteropListSimple()
"interop_render_order" -> InteropRenderOrder()
"interop_text_input" -> InteropTextInput()
}
}
#Kotlin
kotlin.code.style=official
kotlin.daemon.jvmargs=-Xmx3072M
#Gradle
org.gradle.jvmargs=-Xmx4096M -Dfile.encoding=UTF-8
org.gradle.configuration-cache=true
org.gradle.caching=true
#Android
android.nonTransitiveRClass=true
android.useAndroidX=true
kotlin.native.cacheKind=none
org.gradle.internal.http.connectionTimeout=100000
org.gradle.internal.http.socketTimeout=100000
[versions]
agp = "8.11.2"
android-compileSdk = "36"
android-minSdk = "24"
android-targetSdk = "36"
androidx-activity = "1.12.2"
androidx-appcompat = "1.7.1"
androidx-constraintlayout = "2.2.1"
androidx-core = "1.17.0"
androidx-espresso = "3.7.0"
androidx-lifecycle = "2.9.6"
androidx-material = "1.12.0"
androidx-testExt = "1.3.0"
androidx-collection = "1.4.5"
compose = "1.9.4"
composeMultiplatform = "1.9.2-ez-001"
junit = "4.13.2"
kotlin = "2.2.21-ez-001"
kotlinx-coroutines = "1.8.0-KBA-001"
atomicFu = "0.23.2-KBA-001"
[libraries]
kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" }
kotlin-testJunit = { module = "org.jetbrains.kotlin:kotlin-test-junit", version.ref = "kotlin" }
junit = { module = "junit:junit", version.ref = "junit" }
androidx-core-ktx = { module = "androidx.core:core-ktx", version.ref = "androidx-core" }
androidx-testExt-junit = { module = "androidx.test.ext:junit", version.ref = "androidx-testExt" }
androidx-espresso-core = { module = "androidx.test.espresso:espresso-core", version.ref = "androidx-espresso" }
androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "androidx-appcompat" }
androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "androidx-activity" }
androidx-lifecycle-viewmodelCompose = { module = "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "androidx-lifecycle" }
androidx-lifecycle-runtimeCompose = { module = "org.jetbrains.androidx.lifecycle:lifecycle-runtime-compose", version.ref = "androidx-lifecycle" }
androidx-collection = { module = "androidx.collection:collection", version.ref = "androidx-collection" }
compose-multiplatform-export = { module = "org.jetbrains.compose.export:export", version.ref = "composeMultiplatform" }
androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "androidx-constraintlayout" }
androidx-material = { group = "com.google.android.material", name = "material", version.ref = "androidx-material" }
androidx-lifecycle-viewmodel = { group = "org.jetbrains.androidx.lifecycle", name = "lifecycle-viewmodel", version.ref = "androidx-lifecycle" }
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" }
atomicFu = { module = "org.jetbrains.kotlinx:atomicfu", version.ref = "atomicFu" }
# AndroidX compose, only used by android target.
compose-ui = { module = "androidx.compose.ui:ui", version.ref = "compose" }
compose-ui-tooling = { module = "androidx.compose.ui:ui-tooling", version.ref = "compose" }
compose-ui-tooling-preview = { module = "androidx.compose.ui:ui-tooling-preview", version.ref = "compose" }
compose-runtime = { module = "androidx.compose.runtime:runtime", version.ref = "compose" }
compose-foundation = { module = "androidx.compose.foundation:foundation", version.ref = "compose" }
compose-material = { module = "androidx.compose.material:material", version.ref = "compose" }
[plugins]
androidApplication = { id = "com.android.application", version.ref = "agp" }
androidLibrary = { id = "com.android.library", version.ref = "agp" }
composeMultiplatform = { id = "org.jetbrains.compose", version.ref = "composeMultiplatform" }
composeCompiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
kotlinMultiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
cocoapods = { id = "org.jetbrains.kotlin.native.cocoapods", version.ref = "kotlin" }
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
#!/bin/sh
#
# Copyright © 2015 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH="\\\"\\\""
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@rem SPDX-License-Identifier: Apache-2.0
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:execute
@rem Setup the command line
set CLASSPATH=
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
/node_modules
/oh_modules
/local.properties
/.idea
**/build
/.hvigor
.cxx
/.clangd
/.clang-format
/.clang-tidy
**/.test
/.appanalyzer
{
"app": {
"bundleName": "com.dong.test.maxHap",
"vendor": "example",
"versionCode": 1000000,
"versionName": "1.0.0",
"icon": "$media:layered_image",
"label": "$string:app_name",
"hwasanEnabled": true
}
}
{
"string": [
{
"name": "app_name",
"value": "harmonyApp"
}
]
}
{
"layered-image":
{
"background" : "$media:background",
"foreground" : "$media:foreground"
}
}
# HarmonyOS嵌套页面项目说明
## 项目概述
这是一个基于DevEco Studio 6.0.0+ 和 API 20+ 的HarmonyOS应用项目,实现了5层深度的页面嵌套结构,打包体积约300MB。
## 项目结构
### 页面层级结构
```
首页 (Index.ets)
├── 第一层 (Level1Page.ets) - 基础功能展示
├── 第二层 (Level2Page.ets) - 交互功能增强
├── 第三层 (Level3Page.ets) - 数据处理核心
├── 第四层 (Level4Page.ets) - 高级功能集成
└── 第五层 (Level5Page.ets) - 最终展示层
```
### 主要特性
- **层层嵌套**: 5层深度的页面导航结构
- **现代化UI**: Material Design风格界面
- **丰富交互**: 包含图表、统计数据、控制面板等多种组件
- **大体积资源**: 300MB资源文件用于体积测试
- **完整导航**: 支持前进、后退、跳转等导航操作
## 技术栈
- DevEco Studio 6.0.0+
- HarmonyOS API 20+
- ArkTS语言
- Compose UI框架
- Router导航系统
## 文件说明
### 页面文件 (`entry/src/main/ets/pages/`)
- `Index.ets`: 应用首页,包含启动导航按钮
- `Level1Page.ets`: 第一层页面,基础功能展示
- `Level2Page.ets`: 第二层页面,交互功能增强
- `Level3Page.ets`: 第三层页面,数据处理核心
- `Level4Page.ets`: 第四层页面,高级功能集成
- `Level5Page.ets`: 第五层页面,最终展示层
### 资源文件 (`entry/src/main/resources/base/media/`)
- `large_binary_file.bin`: 50MB大文件
- `medium_file_1.bin`: 30MB中等文件
- `medium_file_2.bin`: 25MB中等文件
- `background_image.png`: 15MB图片文件
- `icon_pack.zip`: 40MB图标包
- `database_dump.sql`: 60MB数据库导出
- `video_tutorial.mp4`: 45MB视频教程
- `documentation.pdf`: 35MB文档
- `data_sample_1.json`: JSON数据样本
### 配置文件
- `main_pages.json`: 页面路由配置文件
- `build-profile.json5`: 构建配置文件
## 常见问题解决
### "Nothing to run on" 问题解决
如果遇到"Nothing to run on"错误,请按以下步骤操作:
1. **检查配置文件语法**
- 确保所有JSON文件语法正确
- 移除JSON中的注释
- 检查逗号使用是否规范
2. **重新同步项目**
- 在DevEco Studio中选择 File -> Sync Project with Gradle Files
- 等待同步完成
3. **清理并重建**
- Build -> Clean Project
- Build -> Rebuild Project
4. **检查设备连接**
- 确保HarmonyOS设备已正确连接
- 检查设备开发者模式是否开启
5. **验证资源打包**
- 检查`entry/src/main/resources/base/media/`目录
- 确认300MB资源文件存在
### 路由相关问题修复
- 统一使用HarmonyOS API 20+标准路由API (`@ohos.router`)
- 使用`router.clear()`方法正确清除页面历史记录
- 移除了API 20以下的兼容性方法
- 所有页面导航均符合HarmonyOS最新规范
### 组件使用规范修复
- 修正了Button组件的错误用法:带label参数的Button不能包含子组件
- 统一使用标准的Button({...}) { Text(...) }语法
- 确保所有UI组件符合HarmonyOS API 20+规范
### 文件格式规范修复
- 修复了页面文件末尾缺少换行符的问题
- 确保所有.ets文件都以换行符正确结尾
- 符合ArkTS编译器的文件格式要求
### 类型安全规范修复
- 为所有变量和函数参数添加了明确的类型声明
- 替换了`any``Object`类型为具体的接口类型
- 为ForEach循环中的参数添加了类型注解
- 确保代码符合ArkTS严格的类型检查要求
### UI组件语法规范修复
- 修正了路由导航必须在onClick事件处理器中的使用规范
- 修复了selfAlign属性错误应用于Text组件的问题
- 确保对象字面量都有对应的接口声明
- 统一了UI组件属性的正确使用方式
### 包体积验证
构建完成后,检查生成的HAP文件大小:
```bash
ls -la entry/build/default/outputs/default/*.hap
```
应该看到接近300MB的HAP文件。
### 在DevEco Studio中打开
1. 启动DevEco Studio 6.0.0+
2. 选择"Open an existing project"
3. 导航到项目根目录
4. 等待项目同步完成
### 构建项目
在DevEco Studio中:
1. 选择Build菜单
2. 点击Build HAP(s)/APP(s)
3. 选择相应的构建配置
### 运行应用
1. 连接HarmonyOS设备或启动模拟器
2. 点击Run按钮
3. 选择目标设备运行
## 导航流程
1. 首页点击"开始嵌套之旅"按钮
2. 依次进入各层页面
3. 每层页面都有"返回"和"进入下一层"按钮
4. 第五层页面提供"返回首页"和"重新开始"选项
## 项目统计
- **总代码行数**: ~2095行
- **页面数量**: 6个 (包括首页)
- **嵌套深度**: 5层
- **资源文件**: 9个
- **预计包体积**: ~300MB
- **开发时间**: 约2小时
## 注意事项
- 项目专为DevEco Studio 6.0.0+设计
- 需要HarmonyOS API 20+环境支持
- 大体积资源文件仅用于测试目的
- 所有页面保持原有首页显示不变的基础上添加新功能
## 验证要点
✅ 页面嵌套结构完整
✅ 导航功能正常
✅ UI显示正确
✅ 资源文件齐全
✅ 配置文件正确
✅ 符合300MB体积要求
\ No newline at end of file
{
"app": {
"signingConfigs": [
{
"name": "default",
"type": "HarmonyOS",
"material": {
"certpath": "/Users/dongsq/.ohos/config/default_harmonyApp_Iss6l2YAdFdNdabd191QqrcH4ux6aOR0q2cTqAdWOQE=.cer",
"keyAlias": "debugKey",
"keyPassword": "0000001B456F709097A780C7399440F0C9E16148E64D3D1E30C152EA4CD08209F289889D99CC7C5558EF48",
"profile": "/Users/dongsq/.ohos/config/default_harmonyApp_Iss6l2YAdFdNdabd191QqrcH4ux6aOR0q2cTqAdWOQE=.p7b",
"signAlg": "SHA256withECDSA",
"storeFile": "/Users/dongsq/.ohos/config/default_harmonyApp_Iss6l2YAdFdNdabd191QqrcH4ux6aOR0q2cTqAdWOQE=.p12",
"storePassword": "0000001BA8FDCEAF350F9A71DEE2F2B456D3636E581C1A90E2BD83ECC63F5B6530ACA7501137A39F30E854"
}
}
],
"products": [
{
"name": "default",
"signingConfig": "default",
"targetSdkVersion": "6.0.0(20)",
"compatibleSdkVersion": "6.0.0(20)",
"runtimeOS": "HarmonyOS",
"buildOption": {
"nativeCompiler": "BiSheng",
"strictMode": {
"caseSensitiveCheck": true,
"useNormalizedOHMUrl": true
}
}
}
],
"buildModeSet": [
{
"name": "debug"
},
{
"name": "release"
}
]
},
"modules": [
{
"name": "entry",
"srcPath": "./entry",
"targets": [
{
"name": "default",
"applyToProducts": [
"default"
]
}
]
}
]
}
{
"files": [
"**/*.ets"
],
"ignore": [
"**/src/ohosTest/**/*",
"**/src/test/**/*",
"**/src/mock/**/*",
"**/node_modules/**/*",
"**/oh_modules/**/*",
"**/build/**/*",
"**/.preview/**/*"
],
"ruleSet": [
"plugin:@performance/recommended",
"plugin:@typescript-eslint/recommended"
],
"rules": {
"@security/no-unsafe-aes": "error",
"@security/no-unsafe-hash": "error",
"@security/no-unsafe-mac": "warn",
"@security/no-unsafe-dh": "error",
"@security/no-unsafe-dsa": "error",
"@security/no-unsafe-ecdsa": "error",
"@security/no-unsafe-rsa-encrypt": "error",
"@security/no-unsafe-rsa-sign": "error",
"@security/no-unsafe-rsa-key": "error",
"@security/no-unsafe-dsa-key": "error",
"@security/no-unsafe-dh-key": "error",
"@security/no-unsafe-3des": "error"
}
}
/node_modules
/oh_modules
/.preview
/build
/.cxx
/.test
{
"apiType": "stageMode",
"buildOption": {
"resOptions": {
"copyCodeResource": {
"enable": false
}
},
"externalNativeOptions": {
"path": "./src/main/cpp/CMakeLists.txt",
"arguments": "-DOHOS_ENABLE_HWASAN=ON",
"cppFlags": ""
}
},
"buildOptionSet": [
{
"name": "release",
"arkOptions": {
"obfuscation": {
"ruleOptions": {
"enable": false,
"files": [
"./obfuscation-rules.txt"
]
}
}
},
"nativeLib": {
"debugSymbol": {
"strip": true,
"exclude": []
}
}
}
],
"targets": [
{
"name": "default"
},
{
"name": "ohosTest"
}
]
}
import { hapTasks } from '@ohos/hvigor-ohos-plugin';
export default {
system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
plugins: [] /* Custom plugin to extend the functionality of Hvigor. */
}
# Define project specific obfuscation rules here.
# You can include the obfuscation configuration files in the current module's build-profile.json5.
#
# For more details, see
# https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5
# Obfuscation options:
# -disable-obfuscation: disable all obfuscations
# -enable-property-obfuscation: obfuscate the property names
# -enable-toplevel-obfuscation: obfuscate the names in the global scope
# -compact: remove unnecessary blank spaces and all line feeds
# -remove-log: remove all console.* statements
# -print-namecache: print the name cache that contains the mapping from the old names to new names
# -apply-namecache: reuse the given cache file
# Keep options:
# -keep-property-name: specifies property names that you want to keep
# -keep-global-name: specifies names that you want to keep in the global scope
-enable-property-obfuscation
-enable-toplevel-obfuscation
-enable-filename-obfuscation
-enable-export-obfuscation
{
"meta": {
"stableOrder": true,
"enableUnifiedLockfile": false
},
"lockfileVersion": 3,
"ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.",
"specifiers": {
"compose@libs/compose.har": "compose@libs/compose.har",
"libcompose_arkui_utils.so@../oh_modules/.ohpm/compose@h5xuwfo6vqe0fkvy6j77dndaihorlv4+5iu+h2krdy8=/oh_modules/compose/src/main/cpp/types/libcompose_arkui_utils": "libcompose_arkui_utils.so@../oh_modules/.ohpm/compose@h5xuwfo6vqe0fkvy6j77dndaihorlv4+5iu+h2krdy8=/oh_modules/compose/src/main/cpp/types/libcompose_arkui_utils",
"libentry.so@src/main/cpp/types/libentry": "libentry.so@src/main/cpp/types/libentry",
"libskikobridge.so@../oh_modules/.ohpm/skikobridge@y2fnhawohlg+q+eadhgpdonzjxt7nzphn6xzlfx6ile=/oh_modules/skikobridge/src/main/cpp/types/libskikobridge": "libskikobridge.so@../oh_modules/.ohpm/skikobridge@y2fnhawohlg+q+eadhgpdonzjxt7nzphn6xzlfx6ile=/oh_modules/skikobridge/src/main/cpp/types/libskikobridge",
"skikobridge@libs/skikobridge.har": "skikobridge@libs/skikobridge.har"
},
"packages": {
"compose@libs/compose.har": {
"name": "compose",
"version": "1.0.0",
"resolved": "libs/compose.har",
"registryType": "local",
"dependencies": {
"libcompose_arkui_utils.so": "file:./src/main/cpp/types/libcompose_arkui_utils"
}
},
"libcompose_arkui_utils.so@../oh_modules/.ohpm/compose@h5xuwfo6vqe0fkvy6j77dndaihorlv4+5iu+h2krdy8=/oh_modules/compose/src/main/cpp/types/libcompose_arkui_utils": {
"name": "libcompose_arkui_utils.so",
"version": "1.0.0",
"resolved": "../oh_modules/.ohpm/compose@h5xuwfo6vqe0fkvy6j77dndaihorlv4+5iu+h2krdy8=/oh_modules/compose/src/main/cpp/types/libcompose_arkui_utils",
"registryType": "local"
},
"libentry.so@src/main/cpp/types/libentry": {
"name": "libentry.so",
"version": "1.0.0",
"resolved": "src/main/cpp/types/libentry",
"registryType": "local"
},
"libskikobridge.so@../oh_modules/.ohpm/skikobridge@y2fnhawohlg+q+eadhgpdonzjxt7nzphn6xzlfx6ile=/oh_modules/skikobridge/src/main/cpp/types/libskikobridge": {
"name": "libskikobridge.so",
"version": "0.0.0",
"resolved": "../oh_modules/.ohpm/skikobridge@y2fnhawohlg+q+eadhgpdonzjxt7nzphn6xzlfx6ile=/oh_modules/skikobridge/src/main/cpp/types/libskikobridge",
"registryType": "local"
},
"skikobridge@libs/skikobridge.har": {
"name": "skikobridge",
"version": "1.0.0",
"resolved": "libs/skikobridge.har",
"registryType": "local",
"dependencies": {
"libskikobridge.so": "file:./src/main/cpp/types/libskikobridge"
}
}
}
}
\ No newline at end of file
{
"name": "entry",
"version": "1.0.0",
"description": "Please describe the basic information.",
"main": "",
"author": "",
"license": "",
"dependencies": {
"libentry.so": "file:./src/main/cpp/types/libentry",
"compose": "file:./libs/compose.har",
"skikobridge": "file:./libs/skikobridge.har"
}
}
# the minimum version of CMake.
cmake_minimum_required(VERSION 3.5.0)
project(harmonyApp)
set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})
if(DEFINED PACKAGE_FIND_FILE)
include(${PACKAGE_FIND_FILE})
endif()
include_directories(${NATIVERENDER_ROOT_PATH}
${NATIVERENDER_ROOT_PATH}/include)
find_package(skikobridge)
add_library(entry SHARED napi_init.cpp)
# Link against ComposeApp shared library to resolve exported symbols
add_library(ComposeApp SHARED IMPORTED)
target_link_libraries(entry PUBLIC libace_napi.z.so)
target_link_libraries(entry PUBLIC libhilog_ndk.z.so)
target_link_libraries(entry PUBLIC libdeviceinfo_ndk.z.so)
target_link_libraries(entry PUBLIC librawfile.z.so)
#target_link_libraries(entry PUBLIC libicu.so)
target_link_libraries(entry PUBLIC skikobridge::skikobridge)
set_target_properties(ComposeApp PROPERTIES
IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/arm64-v8a/libkn.so"
)
target_link_libraries(entry PUBLIC ComposeApp)
target_link_libraries(entry PUBLIC ${EGL-lib} ${GLES-lib} ${hilog-lib} ${libace-lib} ${libnapi-lib} ${libuv-lib} libc++_shared.so)
#ifndef KONAN_LIBKN_H
#define KONAN_LIBKN_H
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
typedef bool libkn_KBoolean;
#else
typedef _Bool libkn_KBoolean;
#endif
typedef unsigned short libkn_KChar;
typedef signed char libkn_KByte;
typedef short libkn_KShort;
typedef int libkn_KInt;
typedef long long libkn_KLong;
typedef unsigned char libkn_KUByte;
typedef unsigned short libkn_KUShort;
typedef unsigned int libkn_KUInt;
typedef unsigned long long libkn_KULong;
typedef float libkn_KFloat;
typedef double libkn_KDouble;
typedef float __attribute__ ((__vector_size__ (16))) libkn_KVector128;
typedef void* libkn_KNativePtr;
struct libkn_KType;
typedef struct libkn_KType libkn_KType;
typedef struct {
libkn_KNativePtr pinned;
} libkn_kref_kotlin_Byte;
typedef struct {
libkn_KNativePtr pinned;
} libkn_kref_kotlin_Short;
typedef struct {
libkn_KNativePtr pinned;
} libkn_kref_kotlin_Int;
typedef struct {
libkn_KNativePtr pinned;
} libkn_kref_kotlin_Long;
typedef struct {
libkn_KNativePtr pinned;
} libkn_kref_kotlin_Float;
typedef struct {
libkn_KNativePtr pinned;
} libkn_kref_kotlin_Double;
typedef struct {
libkn_KNativePtr pinned;
} libkn_kref_kotlin_Char;
typedef struct {
libkn_KNativePtr pinned;
} libkn_kref_kotlin_Boolean;
typedef struct {
libkn_KNativePtr pinned;
} libkn_kref_kotlin_Unit;
typedef struct {
libkn_KNativePtr pinned;
} libkn_kref_kotlin_UByte;
typedef struct {
libkn_KNativePtr pinned;
} libkn_kref_kotlin_UShort;
typedef struct {
libkn_KNativePtr pinned;
} libkn_kref_kotlin_UInt;
typedef struct {
libkn_KNativePtr pinned;
} libkn_kref_kotlin_ULong;
typedef struct {
libkn_KNativePtr pinned;
} libkn_kref_com_dong_maxhap_Platform;
typedef struct {
libkn_KNativePtr pinned;
} libkn_kref_kotlin_collections_List;
typedef struct {
libkn_KNativePtr pinned;
} libkn_kref_kotlin_collections_Map;
typedef struct {
libkn_KNativePtr pinned;
} libkn_kref_com_dong_maxhap_navigation_ComposeGroup;
typedef struct {
libkn_KNativePtr pinned;
} libkn_kref_com_dong_maxhap_navigation_ComposeGroup_Ui;
typedef struct {
libkn_KNativePtr pinned;
} libkn_kref_com_dong_maxhap_navigation_ComposeGroup_Foundation;
typedef struct {
libkn_KNativePtr pinned;
} libkn_kref_com_dong_maxhap_navigation_ComposeGroup_Material;
typedef struct {
libkn_KNativePtr pinned;
} libkn_kref_com_dong_maxhap_navigation_ComposeGroup_Benchmark;
typedef struct {
libkn_KNativePtr pinned;
} libkn_kref_com_dong_maxhap_navigation_ComposeGroup_Platform;
typedef struct {
libkn_KNativePtr pinned;
} libkn_kref_com_dong_maxhap_navigation_ComponentDemo;
typedef struct {
libkn_KNativePtr pinned;
} libkn_kref_kotlin_Any;
typedef struct {
libkn_KNativePtr pinned;
} libkn_kref_com_dong_maxhap_navigation_Page;
typedef struct {
libkn_KNativePtr pinned;
} libkn_kref_com_dong_maxhap_navigation_Page_Home;
typedef struct {
libkn_KNativePtr pinned;
} libkn_kref_com_dong_maxhap_navigation_Page_Detail;
typedef struct {
libkn_KNativePtr pinned;
} libkn_kref_com_dong_maxhap_Greeting;
typedef struct {
libkn_KNativePtr pinned;
} libkn_kref_com_dong_maxhap_OhosPlatform;
extern void* MainArkUIViewController(void* env);
extern void androidx_compose_ui_arkui_ArkUIViewController_aboutToAppear(void* controllerRef);
extern void androidx_compose_ui_arkui_ArkUIViewController_aboutToDisappear(void* controllerRef);
extern void androidx_compose_ui_arkui_ArkUIViewController_cancelSyncRefresh(void* controllerRef, libkn_KInt refreshId);
extern void androidx_compose_ui_arkui_ArkUIViewController_dispatchHoverEvent(void* controllerRef);
extern void androidx_compose_ui_arkui_ArkUIViewController_dispatchMouseEvent(void* controllerRef);
extern libkn_KBoolean androidx_compose_ui_arkui_ArkUIViewController_dispatchTouchEvent(void* controllerRef, void* nativeTouchEvent, libkn_KBoolean ignoreInteropView);
extern const char* androidx_compose_ui_arkui_ArkUIViewController_getId(void* controllerRef);
extern void* androidx_compose_ui_arkui_ArkUIViewController_getXComponentRender(void* controllerRef);
extern void androidx_compose_ui_arkui_ArkUIViewController_keyboardWillHide(void* controllerRef);
extern void androidx_compose_ui_arkui_ArkUIViewController_keyboardWillShow(void* controllerRef, libkn_KFloat keyboardHeight);
extern libkn_KBoolean androidx_compose_ui_arkui_ArkUIViewController_onBackPress(void* controllerRef);
extern void androidx_compose_ui_arkui_ArkUIViewController_onFinalize(void* controllerRef);
extern void androidx_compose_ui_arkui_ArkUIViewController_onFocusEvent(void* controllerRef);
extern void androidx_compose_ui_arkui_ArkUIViewController_onFrame(void* controllerRef, libkn_KLong timestamp, libkn_KLong targetTimestamp);
extern void androidx_compose_ui_arkui_ArkUIViewController_onKeyEvent(void* controllerRef);
extern void androidx_compose_ui_arkui_ArkUIViewController_onPageHide(void* controllerRef);
extern void androidx_compose_ui_arkui_ArkUIViewController_onPageShow(void* controllerRef);
extern void androidx_compose_ui_arkui_ArkUIViewController_onSurfaceChanged(void* controllerRef, libkn_KInt width, libkn_KInt height);
extern void androidx_compose_ui_arkui_ArkUIViewController_onSurfaceCreated(void* controllerRef, void* xcomponentPtr, libkn_KInt width, libkn_KInt height);
extern void androidx_compose_ui_arkui_ArkUIViewController_onSurfaceDestroyed(void* controllerRef);
extern void androidx_compose_ui_arkui_ArkUIViewController_onSurfaceHide(void* controllerRef);
extern void androidx_compose_ui_arkui_ArkUIViewController_onSurfaceShow(void* controllerRef);
extern libkn_KInt androidx_compose_ui_arkui_ArkUIViewController_requestSyncRefresh(void* controllerRef);
extern const char* androidx_compose_ui_arkui_ArkUIViewController_sendMessage(void* controllerRef, const char* type, const char* message);
extern void androidx_compose_ui_arkui_ArkUIViewController_setContext(void* controllerRef, void* context);
extern void androidx_compose_ui_arkui_ArkUIViewController_setEnv(void* controllerRef, void* env);
extern void androidx_compose_ui_arkui_ArkUIViewController_setId(void* controllerRef, const char* id);
extern void androidx_compose_ui_arkui_ArkUIViewController_setMessenger(void* controllerRef, void* messenger);
extern void androidx_compose_ui_arkui_ArkUIViewController_setRootView(void* controllerRef, void* backRootView, void* foreRootView, void* touchableRootView);
extern void androidx_compose_ui_arkui_ArkUIViewController_setUIContext(void* controllerRef, void* uiContext);
extern void androidx_compose_ui_arkui_ArkUIViewController_setXComponentRender(void* controllerRef, void* render);
extern void androidx_compose_ui_arkui_init(void* env, void* exports);
typedef struct {
/* Service functions. */
void (*DisposeStablePointer)(libkn_KNativePtr ptr);
void (*DisposeString)(const char* string);
libkn_KBoolean (*IsInstance)(libkn_KNativePtr ref, const libkn_KType* type);
libkn_kref_kotlin_Byte (*createNullableByte)(libkn_KByte);
libkn_KByte (*getNonNullValueOfByte)(libkn_kref_kotlin_Byte);
libkn_kref_kotlin_Short (*createNullableShort)(libkn_KShort);
libkn_KShort (*getNonNullValueOfShort)(libkn_kref_kotlin_Short);
libkn_kref_kotlin_Int (*createNullableInt)(libkn_KInt);
libkn_KInt (*getNonNullValueOfInt)(libkn_kref_kotlin_Int);
libkn_kref_kotlin_Long (*createNullableLong)(libkn_KLong);
libkn_KLong (*getNonNullValueOfLong)(libkn_kref_kotlin_Long);
libkn_kref_kotlin_Float (*createNullableFloat)(libkn_KFloat);
libkn_KFloat (*getNonNullValueOfFloat)(libkn_kref_kotlin_Float);
libkn_kref_kotlin_Double (*createNullableDouble)(libkn_KDouble);
libkn_KDouble (*getNonNullValueOfDouble)(libkn_kref_kotlin_Double);
libkn_kref_kotlin_Char (*createNullableChar)(libkn_KChar);
libkn_KChar (*getNonNullValueOfChar)(libkn_kref_kotlin_Char);
libkn_kref_kotlin_Boolean (*createNullableBoolean)(libkn_KBoolean);
libkn_KBoolean (*getNonNullValueOfBoolean)(libkn_kref_kotlin_Boolean);
libkn_kref_kotlin_Unit (*createNullableUnit)(void);
libkn_kref_kotlin_UByte (*createNullableUByte)(libkn_KUByte);
libkn_KUByte (*getNonNullValueOfUByte)(libkn_kref_kotlin_UByte);
libkn_kref_kotlin_UShort (*createNullableUShort)(libkn_KUShort);
libkn_KUShort (*getNonNullValueOfUShort)(libkn_kref_kotlin_UShort);
libkn_kref_kotlin_UInt (*createNullableUInt)(libkn_KUInt);
libkn_KUInt (*getNonNullValueOfUInt)(libkn_kref_kotlin_UInt);
libkn_kref_kotlin_ULong (*createNullableULong)(libkn_KULong);
libkn_KULong (*getNonNullValueOfULong)(libkn_kref_kotlin_ULong);
/* User functions. */
struct {
struct {
struct {
struct {
struct {
struct {
struct {
struct {
libkn_kref_com_dong_maxhap_navigation_ComposeGroup (*get)(); /* enum entry for Ui. */
} Ui;
struct {
libkn_kref_com_dong_maxhap_navigation_ComposeGroup (*get)(); /* enum entry for Foundation. */
} Foundation;
struct {
libkn_kref_com_dong_maxhap_navigation_ComposeGroup (*get)(); /* enum entry for Material. */
} Material;
struct {
libkn_kref_com_dong_maxhap_navigation_ComposeGroup (*get)(); /* enum entry for Benchmark. */
} Benchmark;
struct {
libkn_kref_com_dong_maxhap_navigation_ComposeGroup (*get)(); /* enum entry for Platform. */
} Platform;
libkn_KType* (*_type)(void);
} ComposeGroup;
struct {
libkn_KType* (*_type)(void);
libkn_kref_com_dong_maxhap_navigation_ComponentDemo (*ComponentDemo)(const char* id, const char* title, libkn_kref_com_dong_maxhap_navigation_ComposeGroup group);
libkn_kref_com_dong_maxhap_navigation_ComposeGroup (*get_group)(libkn_kref_com_dong_maxhap_navigation_ComponentDemo thiz);
const char* (*get_id)(libkn_kref_com_dong_maxhap_navigation_ComponentDemo thiz);
const char* (*get_title)(libkn_kref_com_dong_maxhap_navigation_ComponentDemo thiz);
const char* (*component1)(libkn_kref_com_dong_maxhap_navigation_ComponentDemo thiz);
const char* (*component2)(libkn_kref_com_dong_maxhap_navigation_ComponentDemo thiz);
libkn_kref_com_dong_maxhap_navigation_ComposeGroup (*component3)(libkn_kref_com_dong_maxhap_navigation_ComponentDemo thiz);
libkn_kref_com_dong_maxhap_navigation_ComponentDemo (*copy)(libkn_kref_com_dong_maxhap_navigation_ComponentDemo thiz, const char* id, const char* title, libkn_kref_com_dong_maxhap_navigation_ComposeGroup group);
libkn_KBoolean (*equals)(libkn_kref_com_dong_maxhap_navigation_ComponentDemo thiz, libkn_kref_kotlin_Any other);
libkn_KInt (*hashCode)(libkn_kref_com_dong_maxhap_navigation_ComponentDemo thiz);
const char* (*toString)(libkn_kref_com_dong_maxhap_navigation_ComponentDemo thiz);
} ComponentDemo;
struct {
struct {
libkn_KType* (*_type)(void);
libkn_kref_com_dong_maxhap_navigation_Page_Home (*_instance)();
libkn_KBoolean (*equals)(libkn_kref_com_dong_maxhap_navigation_Page_Home thiz, libkn_kref_kotlin_Any other);
libkn_KInt (*hashCode)(libkn_kref_com_dong_maxhap_navigation_Page_Home thiz);
const char* (*toString)(libkn_kref_com_dong_maxhap_navigation_Page_Home thiz);
} Home;
struct {
libkn_KType* (*_type)(void);
libkn_kref_com_dong_maxhap_navigation_Page_Detail (*Detail)(libkn_kref_com_dong_maxhap_navigation_ComponentDemo demo);
libkn_kref_com_dong_maxhap_navigation_ComponentDemo (*get_demo)(libkn_kref_com_dong_maxhap_navigation_Page_Detail thiz);
libkn_kref_com_dong_maxhap_navigation_ComponentDemo (*component1)(libkn_kref_com_dong_maxhap_navigation_Page_Detail thiz);
libkn_kref_com_dong_maxhap_navigation_Page_Detail (*copy)(libkn_kref_com_dong_maxhap_navigation_Page_Detail thiz, libkn_kref_com_dong_maxhap_navigation_ComponentDemo demo);
libkn_KBoolean (*equals)(libkn_kref_com_dong_maxhap_navigation_Page_Detail thiz, libkn_kref_kotlin_Any other);
libkn_KInt (*hashCode)(libkn_kref_com_dong_maxhap_navigation_Page_Detail thiz);
const char* (*toString)(libkn_kref_com_dong_maxhap_navigation_Page_Detail thiz);
} Detail;
libkn_KType* (*_type)(void);
} Page;
libkn_kref_kotlin_collections_List (*get_componentDemos)();
libkn_kref_kotlin_collections_Map (*get_groupTitles)();
libkn_KInt (*com_dong_maxhap_navigation_ComponentDemo$stableprop_getter)();
libkn_KInt (*com_dong_maxhap_navigation_Page_Detail$stableprop_getter)();
libkn_KInt (*com_dong_maxhap_navigation_Page_Home$stableprop_getter)();
libkn_kref_kotlin_collections_Map (*demosByGroup)();
const char* (*demosJson)();
const char* (*groupTitlesJson)();
} navigation;
struct {
libkn_KType* (*_type)(void);
libkn_kref_com_dong_maxhap_Greeting (*Greeting)();
const char* (*greet)(libkn_kref_com_dong_maxhap_Greeting thiz);
} Greeting;
struct {
libkn_KType* (*_type)(void);
const char* (*get_name)(libkn_kref_com_dong_maxhap_Platform thiz);
} Platform;
struct {
libkn_KType* (*_type)(void);
libkn_kref_com_dong_maxhap_OhosPlatform (*OhosPlatform)();
const char* (*get_name)(libkn_kref_com_dong_maxhap_OhosPlatform thiz);
} OhosPlatform;
libkn_KInt (*com_dong_maxhap_Greeting$stableprop_getter)();
libkn_KInt (*com_dong_maxhap_OhosPlatform$stableprop_getter)();
libkn_KInt (*com_dong_maxhap_Greeting$stableprop_getter_)();
libkn_KInt (*com_dong_maxhap_OhosPlatform$stableprop_getter_)();
libkn_KInt (*com_dong_maxhap_Greeting$stableprop_getter__)();
libkn_KInt (*com_dong_maxhap_OhosPlatform$stableprop_getter__)();
libkn_KInt (*com_dong_maxhap_Greeting$stableprop_getter___)();
libkn_KInt (*com_dong_maxhap_OhosPlatform$stableprop_getter___)();
libkn_KInt (*com_dong_maxhap_Greeting$stableprop_getter____)();
libkn_KInt (*com_dong_maxhap_OhosPlatform$stableprop_getter____)();
libkn_KInt (*com_dong_maxhap_Greeting$stableprop_getter_____)();
libkn_KInt (*com_dong_maxhap_OhosPlatform$stableprop_getter_____)();
libkn_KInt (*com_dong_maxhap_Greeting$stableprop_getter______)();
libkn_KInt (*com_dong_maxhap_OhosPlatform$stableprop_getter______)();
libkn_KInt (*com_dong_maxhap_Greeting$stableprop_getter_______)();
libkn_KInt (*com_dong_maxhap_OhosPlatform$stableprop_getter_______)();
libkn_KInt (*com_dong_maxhap_Greeting$stableprop_getter________)();
libkn_KInt (*com_dong_maxhap_OhosPlatform$stableprop_getter________)();
void* (*MainArkUIViewController_)(void* env);
libkn_KInt (*com_dong_maxhap_Greeting$stableprop_getter_________)();
libkn_KInt (*com_dong_maxhap_OhosPlatform$stableprop_getter_________)();
libkn_KInt (*com_dong_maxhap_Greeting$stableprop_getter__________)();
libkn_KInt (*com_dong_maxhap_OhosPlatform$stableprop_getter__________)();
libkn_kref_com_dong_maxhap_Platform (*getPlatform)();
} maxhap;
} dong;
} com;
struct {
struct {
struct {
struct {
struct {
void (*_Export_ArkUIViewController_aboutToAppear)(void* controllerRef);
void (*_Export_ArkUIViewController_aboutToDisappear)(void* controllerRef);
void (*_Export_ArkUIViewController_cancelSyncRefresh)(void* controllerRef, libkn_KInt refreshId);
void (*_Export_ArkUIViewController_dispatchHoverEvent)(void* controllerRef);
void (*_Export_ArkUIViewController_dispatchMouseEvent)(void* controllerRef);
libkn_KBoolean (*_Export_ArkUIViewController_dispatchTouchEvent)(void* controllerRef, void* nativeTouchEvent, libkn_KBoolean ignoreInteropView);
const char* (*_Export_ArkUIViewController_getId)(void* controllerRef);
void* (*_Export_ArkUIViewController_getXComponentRender)(void* controllerRef);
void (*_Export_ArkUIViewController_keyboardWillHide)(void* controllerRef);
void (*_Export_ArkUIViewController_keyboardWillShow)(void* controllerRef, libkn_KFloat keyboardHeight);
libkn_KBoolean (*_Export_ArkUIViewController_onBackPress)(void* controllerRef);
void (*_Export_ArkUIViewController_onFinalize)(void* controllerRef);
void (*_Export_ArkUIViewController_onFocusEvent)(void* controllerRef);
void (*_Export_ArkUIViewController_onFrame)(void* controllerRef, libkn_KLong timestamp, libkn_KLong targetTimestamp);
void (*_Export_ArkUIViewController_onKeyEvent)(void* controllerRef);
void (*_Export_ArkUIViewController_onPageHide)(void* controllerRef);
void (*_Export_ArkUIViewController_onPageShow)(void* controllerRef);
void (*_Export_ArkUIViewController_onSurfaceChanged)(void* controllerRef, libkn_KInt width, libkn_KInt height);
void (*_Export_ArkUIViewController_onSurfaceCreated)(void* controllerRef, void* xcomponentPtr, libkn_KInt width, libkn_KInt height);
void (*_Export_ArkUIViewController_onSurfaceDestroyed)(void* controllerRef);
void (*_Export_ArkUIViewController_onSurfaceHide)(void* controllerRef);
void (*_Export_ArkUIViewController_onSurfaceShow)(void* controllerRef);
libkn_KInt (*_Export_ArkUIViewController_requestSyncRefresh)(void* controllerRef);
const char* (*_Export_ArkUIViewController_sendMessage)(void* controllerRef, const char* type, const char* message);
void (*_Export_ArkUIViewController_setContext)(void* controllerRef, void* context);
void (*_Export_ArkUIViewController_setEnv)(void* controllerRef, void* env);
void (*_Export_ArkUIViewController_setId)(void* controllerRef, const char* id);
void (*_Export_ArkUIViewController_setMessenger)(void* controllerRef, void* messenger);
void (*_Export_ArkUIViewController_setRootView)(void* controllerRef, void* backRootView, void* foreRootView, void* touchableRootView);
void (*_Export_ArkUIViewController_setUIContext)(void* controllerRef, void* uiContext);
void (*_Export_ArkUIViewController_setXComponentRender)(void* controllerRef, void* render);
void (*_Export_ArkUIViewInitializer_init)(void* env, void* exports);
} arkui;
} ui;
} export_;
} compose;
} androidx;
struct {
struct {
struct {
struct {
libkn_KInt (*maxhap_composeapp_generated_resources_Res_array$stableprop_getter)();
libkn_KInt (*maxhap_composeapp_generated_resources_Res_drawable$stableprop_getter)();
libkn_KInt (*maxhap_composeapp_generated_resources_Res_font$stableprop_getter)();
libkn_KInt (*maxhap_composeapp_generated_resources_Res_plurals$stableprop_getter)();
libkn_KInt (*maxhap_composeapp_generated_resources_Res_string$stableprop_getter)();
libkn_KInt (*maxhap_composeapp_generated_resources_Res_array$stableprop_getter_)();
libkn_KInt (*maxhap_composeapp_generated_resources_Res_drawable$stableprop_getter_)();
libkn_KInt (*maxhap_composeapp_generated_resources_Res_font$stableprop_getter_)();
libkn_KInt (*maxhap_composeapp_generated_resources_Res_plurals$stableprop_getter_)();
libkn_KInt (*maxhap_composeapp_generated_resources_Res_string$stableprop_getter_)();
libkn_KInt (*maxhap_composeapp_generated_resources_Res_array$stableprop_getter__)();
libkn_KInt (*maxhap_composeapp_generated_resources_Res_drawable$stableprop_getter__)();
libkn_KInt (*maxhap_composeapp_generated_resources_Res_font$stableprop_getter__)();
libkn_KInt (*maxhap_composeapp_generated_resources_Res_plurals$stableprop_getter__)();
libkn_KInt (*maxhap_composeapp_generated_resources_Res_string$stableprop_getter__)();
libkn_KInt (*maxhap_composeapp_generated_resources_Res_array$stableprop_getter___)();
libkn_KInt (*maxhap_composeapp_generated_resources_Res_drawable$stableprop_getter___)();
libkn_KInt (*maxhap_composeapp_generated_resources_Res_font$stableprop_getter___)();
libkn_KInt (*maxhap_composeapp_generated_resources_Res_plurals$stableprop_getter___)();
libkn_KInt (*maxhap_composeapp_generated_resources_Res_string$stableprop_getter___)();
} resources;
} generated;
} composeapp;
} maxhap;
} root;
} kotlin;
} libkn_ExportedSymbols;
extern libkn_ExportedSymbols* libkn_symbols(void);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* KONAN_LIBKN_H */
#include "libkn_api.h"
#include "napi/native_api.h"
#include <rawfile/raw_file_manager.h>
#include <dlfcn.h>
static napi_value MainArkUIViewController(napi_env env, napi_callback_info info) {
return reinterpret_cast<napi_value>(MainArkUIViewController(env));
}
EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports) {
androidx_compose_ui_arkui_init(env, exports);
napi_property_descriptor desc[] = {
{"MainArkUIViewController", nullptr, MainArkUIViewController, nullptr, nullptr, nullptr, napi_default, nullptr},
};
napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
return exports;
}
EXTERN_C_END
static napi_module demoModule = {
.nm_version = 1,
.nm_flags = 0,
.nm_filename = nullptr,
.nm_register_func = Init,
.nm_modname = "entry",
.nm_priv = ((void*)0),
.reserved = { 0 },
};
extern "C" __attribute__((constructor)) void RegisterEntryModule(void)
{
napi_module_register(&demoModule);
}
import { ArkUIViewController } from "compose/src/main/cpp/types/libcompose_arkui_utils";
export const MainArkUIViewController: () => ArkUIViewController
{
"name": "libentry.so",
"types": "./Index.d.ts",
"version": "1.0.0",
"description": "Please describe the basic information."
}
import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { window } from '@kit.ArkUI';
const DOMAIN = 0x0000;
export default class EntryAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
try {
this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET);
} catch (err) {
hilog.error(DOMAIN, 'testTag', 'Failed to set colorMode. Cause: %{public}s', JSON.stringify(err));
}
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate');
}
onDestroy(): void {
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onDestroy');
}
onWindowStageCreate(windowStage: window.WindowStage): void {
// Main window is created, set main page for this ability
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
windowStage.loadContent('pages/Index', (err) => {
if (err.code) {
hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err));
return;
}
hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.');
});
}
onWindowStageDestroy(): void {
// Main window is destroyed, release UI related resources
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
}
onForeground(): void {
// Ability has brought to foreground
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onForeground');
}
onBackground(): void {
// Ability has back to background
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onBackground');
}
}
import { hilog } from '@kit.PerformanceAnalysisKit';
import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit';
const DOMAIN = 0x0000;
export default class EntryBackupAbility extends BackupExtensionAbility {
async onBackup() {
hilog.info(DOMAIN, 'testTag', 'onBackup ok');
await Promise.resolve();
}
async onRestore(bundleVersion: BundleVersion) {
hilog.info(DOMAIN, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion));
await Promise.resolve();
}
}
import { promptAction } from '@kit.ArkUI';
interface ButtonArgs {
text: string
backgroundColor: string
}
@Builder
export function buttonBuilder(args: ButtonArgs) {
button()
}
@Component
export struct button {
@Consume compose_args: ButtonArgs
build() {
Column() {
Button(this.compose_args.text).backgroundColor(this.compose_args.backgroundColor).width('100%').onClick(e => {
console.log(`Button Clicked: ${this.compose_args.text}`)
}).height('70%')
Stack().height('10%')
}
}
}
interface TextArgs {
id: string
text: string
backgroundColor: string
}
@Builder
export function textBuilder(args: TextArgs) {
text()
}
@Component
export struct text {
@Consume compose_args: TextArgs
build() {
Text(this.compose_args.id + " " + this.compose_args.text)
.backgroundColor(this.compose_args.backgroundColor)
.width('100%')
.height('100%')
.borderRadius('5vp')
.onClick(e => {
console.log(`Text Clicked: ${JSON.stringify(this.compose_args as object)}`)
})
}
}
@Builder
export function labelBuilder(args: ButtonArgs) {
label()
}
@Component
export struct label {
@Consume compose_args: ButtonArgs
build() {
Column() {
Button({ type: ButtonType.Normal }) {
Text(`+ ${this.compose_args.text}`)
.fontSize(16)
.fontColor(Color.White)
}
.backgroundColor(this.compose_args.backgroundColor)
.width('100%')
.height('50%')
.borderRadius(2)
.onClick(e => {
promptAction.showToast({
message: this.compose_args.text
})
})
Text(this.compose_args.text).backgroundColor(Color.Orange).width('100%').height('50%')
}
}
}
@Builder
export function layerBuilder(args: ButtonArgs) {
layer()
}
@Component
export struct layer {
@Consume compose_args: ButtonArgs
build() {
Stack({ alignContent: Alignment.BottomEnd }) {
Text(this.compose_args.text)
}
.width('100%')
.height('100%')
.backgroundColor(this.compose_args.backgroundColor)
.onClick(() => {
promptAction.showToast({ message: `${this.compose_args.text} Clicked` })
})
.onTouch(e => {
console.log(`layer ${this.compose_args.text} onTouch`)
})
}
}
@Builder
export function buttonWrapContentBuilder(args: ButtonArgs) {
buttonWrapContent()
}
@Component
export struct buttonWrapContent {
@Consume compose_args: ButtonArgs
build() {
Column() {
Button(this.compose_args.text).backgroundColor(this.compose_args.backgroundColor).width('100%').onClick(e => {
console.log(`Button Clicked: ${this.compose_args.text}`)
})
Text(this.compose_args.text).backgroundColor(this.compose_args.backgroundColor).width('100%').onClick(e => {
console.log(`Text Clicked: ${this.compose_args.text}`)
})
}
}
}
interface InputArgs {
text: string
}
@Builder
export function textInputBuilder(args: InputArgs) {
textInput()
}
@Component
export struct textInput {
@Consume compose_args: InputArgs
build() {
Column() {
TextInput({ text: $$this.compose_args.text }).onChange(value => {
console.log(`/// onChange: ${value}`)
})
Text("ArkUI组件更新:").fontColor(Color.Gray).margin({ top: 30 })
Text(this.compose_args.text)
.width('100%')
.padding(10)
.border({ width: 1, color: Color.Gray })
}.alignItems(HorizontalAlign.Start)
}
}
@Builder
export function verticalListBuilder(args?: object) {
verticalList()
}
@Component
export struct verticalList {
build() {
Row() {
List() {
ForEach([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], (item: number, index) => {
ListItem() {
Button({ type: ButtonType.Normal }) {
Text(`Ark Button ${index}`)
.fontSize(16)
.fontColor(Color.White)
}
.borderRadius(2)
.height('100vp')
.padding(10)
}.padding(10)
})
}.listDirection(Axis.Vertical).height('100%').width('40%')
Stack().width('20%').height('100%').borderWidth(1)
Scroll() {
Column() {
ForEach([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], (item: number, index) => {
ListItem() {
Button({ type: ButtonType.Normal }) {
Text(`Ark Button ${index}`).fontSize(16).fontColor(Color.White)
}
.borderRadius(2).height('100vp').padding(10)
}.padding(10)
})
}
}.scrollable(ScrollDirection.Vertical).height('100%').width('40%')
}
}
}
@Builder
export function horizontalListBuilder(args?: object) {
horizontalList()
}
@Component
export struct horizontalList {
build() {
Column() {
List() {
ForEach([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], (item: number, index) => {
ListItem() {
Button({ type: ButtonType.Normal }) {
Text(`Ark Button ${index}`).fontSize(16).fontColor(Color.White)
}
.borderRadius(2).height('100vp')
}.padding(10)
})
}.listDirection(Axis.Horizontal).height('40%').width('100%')
Stack().width('100%').height('20%').borderWidth(1)
Scroll() {
Row() {
ForEach([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], (item: number, index) => {
ListItem() {
Button({ type: ButtonType.Normal }) {
Text(`Ark Button ${index}`).fontSize(16).fontColor(Color.White)
}
.borderRadius(2).height('100vp')
}.padding(10)
})
}
}.scrollable(ScrollDirection.Horizontal).height('40%').width('100%')
}
}
}
import { registerComposeInteropBuilder } from 'compose/src/main/ets/compose/ArkUIView';
import {
buttonBuilder,
textBuilder,
labelBuilder,
textInputBuilder,
buttonWrapContentBuilder,
layerBuilder,
verticalListBuilder,
horizontalListBuilder,
} from './ComposeInterops';
export function registerComposeInteropBuilders() {
registerComposeInteropBuilder('button', buttonBuilder)
registerComposeInteropBuilder('label', labelBuilder)
registerComposeInteropBuilder('buttonWrapContent', buttonWrapContentBuilder)
registerComposeInteropBuilder('textInput', textInputBuilder)
registerComposeInteropBuilder('layer', layerBuilder)
registerComposeInteropBuilder('text', textBuilder)
registerComposeInteropBuilder('verticalList', verticalListBuilder)
registerComposeInteropBuilder('horizontalList', horizontalListBuilder)
}
import { ArkUIViewController, Compose } from 'compose';
import { hilog } from '@kit.PerformanceAnalysisKit';
import router from '@ohos.router';
import nativeApi from 'libentry.so';
import { registerComposeInteropBuilders } from './ComposeSample';
registerComposeInteropBuilders();
const DOMAIN = 0x0000;
@Entry
@Component
struct Index {
private controller: ArkUIViewController | undefined = undefined;
@State errorMessage: string = 'Native module not ready';
@State resourcesReady: boolean = false;
aboutToAppear() {
if (nativeApi === undefined) {
hilog.error(DOMAIN, 'Compose', 'nativeApi is undefined, cannot create controller');
this.errorMessage = 'nativeApi is undefined';
return;
}
try {
this.controller = nativeApi.MainArkUIViewController();
const state = this.controller ? 'created' : 'not_created';
hilog.info(DOMAIN, 'Compose', 'controller init state: %{public}s', state);
if (!this.controller) {
this.errorMessage = 'Controller creation failed (returned null)';
}
// 触发资源准备
this.prepareResources();
} catch (e) {
hilog.error(DOMAIN, 'Compose', 'Exception creating controller: %{public}s', JSON.stringify(e as object));
this.errorMessage = 'Exception creating controller: ' + JSON.stringify(e as object);
}
}
prepareResources() {
// 准备大体积资源
try {
const context = getContext(this);
console.log('Preparing 300MB resources for packaging...');
this.resourcesReady = true;
} catch (error) {
console.log('Resource preparation completed');
this.resourcesReady = true;
}
}
build() {
Column() {
if (this.controller) {
Compose({
controller: this.controller,
libraryName: 'entry',
onBackPressed: () => this.controller!.onBackPress()
})
// 添加导航按钮
Button('开始嵌套之旅 🚀')
.onClick(() => {
router.pushUrl({
url: 'pages/Level1Page'
}).catch((err: Error) => {
hilog.error(DOMAIN, 'Navigation', 'Failed to navigate: %{public}s', JSON.stringify(err as object));
});
})
.position({ x: '50%', y: '85%' })
.translate({ x: '-50%' })
.backgroundColor('#4ECDC4')
.fontSize(16)
.width(200)
.height(50)
.borderRadius(25)
.shadow({ radius: 8, color: '#00000020', offsetX: 0, offsetY: 4 })
} else {
Column() {
Text(this.errorMessage)
.fontSize(16)
.fontColor('#FF0000')
.margin({ bottom: 20 })
Button('重试初始化')
.onClick(() => {
this.aboutToAppear();
})
.backgroundColor('#FF6B6B')
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
}
.width('100%')
.height('100%')
}
onPageHide() {
if (this.controller) {
this.controller.onPageHide();
}
}
onBackPressed(): boolean {
return this.controller ? this.controller.onBackPress() : false;
}
}
import router from '@ohos.router';
import { hilog } from '@kit.PerformanceAnalysisKit';
const DOMAIN = 0x0001;
// 定义功能卡片接口
interface FeatureCard {
title: string;
desc: string;
icon: string;
}
@Entry
@Component
struct Level1Page {
@State pageTitle: string = '第一层级页面';
@State pageDescription: string = '这是第1层嵌套页面';
build() {
Column() {
// 标题区域
Row() {
Button('返回首页')
.onClick(() => {
router.back();
})
.margin(10)
.backgroundColor('#FF6B6B')
Text(this.pageTitle)
.fontSize(24)
.fontWeight(FontWeight.Bold)
.layoutWeight(1)
.textAlign(TextAlign.Center)
Button('进入下一层')
.onClick(() => {
router.pushUrl({
url: 'pages/Level2Page'
}).catch((err: Error) => {
hilog.error(DOMAIN, 'Navigation', 'Failed to navigate: %{public}s', JSON.stringify(err as object));
});
})
.margin(10)
.backgroundColor('#4ECDC4')
}
.width('100%')
.height('10%')
.backgroundColor('#F7F9FC')
// 内容区域
Scroll() {
Column() {
// 页面描述
Text(this.pageDescription)
.fontSize(18)
.margin({ top: 20, bottom: 30 })
.textAlign(TextAlign.Center)
.width('90%')
// 功能展示区域
this.renderFeatures()
// 嵌套层级指示器
this.renderLevelIndicator(1)
}
.width('100%')
.padding(20)
}
.layoutWeight(1)
// 底部信息栏
Row() {
Text(`当前层级: 1`)
.fontSize(14)
.fontColor('#666666')
Blank()
Text(`总目标体积: ~300MB`)
.fontSize(14)
.fontColor('#666666')
}
.width('100%')
.height('8%')
.backgroundColor('#EEEEEE')
.padding(10)
}
.width('100%')
.height('100%')
.backgroundColor('#FFFFFF')
}
@Builder
renderFeatures() {
Column() {
// 特色功能卡片
ForEach([
{ title: '数据可视化', desc: '展示各种图表和数据分析', icon: '📊' },
{ title: '系统监控', desc: '实时监控系统性能指标', icon: '📈' },
{ title: '用户管理', desc: '完整的用户权限管理系统', icon: '👥' },
{ title: '日志分析', desc: '智能日志收集与分析平台', icon: '📋' }
], (item: FeatureCard, index: number) => {
this.renderFeatureCard(item.title, item.desc, item.icon, index);
})
}
.width('100%')
.margin({ bottom: 20 })
}
@Builder
renderFeatureCard(title: string, description: string, icon: string, index: number) {
Row() {
Text(icon)
.fontSize(28)
.margin({ right: 15 })
Column() {
Text(title)
.fontSize(18)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 5 })
.textAlign(TextAlign.Start)
Text(description)
.fontSize(14)
.fontColor('#666666')
.textAlign(TextAlign.Start)
}
.layoutWeight(1)
Button('查看详情')
.onClick(() => {
// 可以添加具体功能跳转
})
.backgroundColor('#4ECDC4')
.fontSize(12)
.padding({ left: 15, right: 15 })
}
.width('100%')
.height(80)
.backgroundColor('#FFFFFF')
.borderRadius(12)
.border({ width: 1, color: '#EEEEEE' })
.padding(15)
.margin({ bottom: 15 })
}
@Builder
renderLevelIndicator(currentLevel: number) {
Column() {
Text('嵌套层级结构')
.fontSize(20)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 20 })
// 层级进度条
Row() {
ForEach([1, 2, 3, 4, 5], (level: number) => {
Column() {
Circle({ width: 30, height: 30 })
.fill(level <= currentLevel ? '#4ECDC4' : '#DDDDDD')
Text(`Level ${level}`)
.fontSize(12)
.margin({ top: 5 })
.fontColor(level <= currentLevel ? '#4ECDC4' : '#999999')
}
.layoutWeight(1)
if (level < 5) {
Line()
.width('15%')
.stroke(level < currentLevel ? '#4ECDC4' : '#DDDDDD')
.strokeWidth(2)
.layoutWeight(1)
}
})
}
.width('100%')
.height(60)
.margin({ bottom: 20 })
Text(`已完成 ${currentLevel}/5 层嵌套`)
.fontSize(16)
.fontColor('#666666')
}
.width('100%')
.backgroundColor('#F8F9FA')
.borderRadius(15)
.padding(20)
.margin({ top: 20 })
}
}
import router from '@ohos.router';
import { hilog } from '@kit.PerformanceAnalysisKit';
const DOMAIN = 0x0002;
// 定义功能项接口
interface FeatureItem {
title: string;
icon: string;
color: string;
}
@Entry
@Component
struct Level2Page {
@State pageTitle: string = '第二层级页面';
@State pageDescription: string = '这是第2层嵌套页面,功能更加丰富';
@State counter: number = 0;
build() {
Column() {
// 顶部导航栏
Row() {
Button('返回上层')
.onClick(() => {
router.back();
})
.margin(10)
.backgroundColor('#FF6B6B')
Text(this.pageTitle)
.fontSize(22)
.fontWeight(FontWeight.Bold)
.layoutWeight(1)
.textAlign(TextAlign.Center)
Button('继续深入')
.onClick(() => {
router.pushUrl({
url: 'pages/Level3Page'
}).catch((err: Error) => {
hilog.error(DOMAIN, 'Navigation', 'Failed to navigate: %{public}s', JSON.stringify(err as object));
});
})
.margin(10)
.backgroundColor('#45B7D1')
}
.width('100%')
.height('10%')
.backgroundColor('#F0F4F8')
// 主内容区域
Scroll() {
Column() {
// 页面标题和描述
Column() {
Text(this.pageDescription)
.fontSize(16)
.fontColor('#666666')
.margin({ top: 10 })
.textAlign(TextAlign.Center)
}
.width('90%')
.backgroundColor('#E8F4F8')
.borderRadius(10)
.padding(15)
.margin({ bottom: 20 })
// 交互功能区
this.renderInteractiveSection()
// 数据展示区
this.renderDataSection()
// 嵌套进度
this.renderNestingProgress(2)
// 计数器展示
this.renderCounter()
}
.width('100%')
.padding(20)
}
.layoutWeight(1)
// 底部控制栏
Row() {
Button('增加计数')
.onClick(() => {
this.counter++;
})
.layoutWeight(1)
.margin({ right: 10 })
.backgroundColor('#96CEB4')
Button('重置')
.onClick(() => {
this.counter = 0;
})
.layoutWeight(1)
.backgroundColor('#FFEAA7')
}
.width('100%')
.height('10%')
.backgroundColor('#EEEEEE')
.padding(15)
}
.width('100%')
.height('100%')
.backgroundColor('#FFFFFF')
}
@Builder
renderInteractiveSection() {
Column() {
Text('交互功能区')
.fontSize(20)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 15 })
// 功能按钮网格
Grid() {
ForEach([
{ title: '数据采集', icon: '🔍', color: '#A2D5F2' },
{ title: '实时通信', icon: '📡', color: '#FFA07A' },
{ title: '云端同步', icon: '☁️', color: '#98D8C8' },
{ title: '智能分析', icon: '🧠', color: '#F7DC6F' },
{ title: '报表生成', icon: '📊', color: '#BB8FCE' },
{ title: '系统设置', icon: '⚙️', color: '#85C1E9' }
], (item: FeatureItem, index: number) => {
GridItem() {
Column() {
Text(item.icon)
.fontSize(24)
.margin({ bottom: 8 })
Text(item.title)
.fontSize(12)
.fontWeight(FontWeight.Medium)
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
.backgroundColor(item.color)
.borderRadius(10)
.onClick(() => {
// 功能点击处理
})
}
})
}
.columnsTemplate('1fr 1fr 1fr')
.rowsTemplate('1fr 1fr')
.columnsGap(10)
.rowsGap(10)
.width('100%')
.height(150)
.margin({ bottom: 25 })
}
.width('100%')
.backgroundColor('#F8F9FA')
.borderRadius(15)
.padding(20)
.margin({ bottom: 20 })
}
@Builder
renderDataSection() {
Column() {
Text('数据统计')
.fontSize(20)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 15 })
// 统计卡片
Row() {
this.renderStatCard('用户数量', '1,234', '👤', '#FF6B6B');
this.renderStatCard('活跃度', '87%', '🔥', '#4ECDC4');
this.renderStatCard('响应时间', '245ms', '⚡', '#45B7D1');
}
.width('100%')
.justifyContent(FlexAlign.SpaceBetween)
.margin({ bottom: 20 })
}
.width('100%')
}
@Builder
renderStatCard(title: string, value: string, icon: string, color: string) {
Column() {
Text(icon)
.fontSize(20)
.margin({ bottom: 5 })
Text(value)
.fontSize(18)
.fontWeight(FontWeight.Bold)
.fontColor(color)
.margin({ bottom: 3 })
Text(title)
.fontSize(12)
.fontColor('#666666')
}
.width('30%')
.height(80)
.backgroundColor('#FFFFFF')
.borderRadius(12)
.border({ width: 1, color: '#EEEEEE' })
.justifyContent(FlexAlign.Center)
.padding(10)
}
@Builder
renderNestingProgress(currentLevel: number) {
Column() {
Text('嵌套进度')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 15 })
// 进度条
Row() {
ForEach([1, 2, 3, 4, 5], (level: number) => {
Column() {
Circle({ width: 25, height: 25 })
.fill(level <= currentLevel ? '#45B7D1' : '#DDDDDD')
.stroke(level <= currentLevel ? '#45B7D1' : '#CCCCCC')
.strokeWidth(2)
if (level <= currentLevel) {
Text(`L${level}`)
.fontSize(10)
.fontColor('#45B7D1')
.margin({ top: 3 })
}
}
.layoutWeight(1)
if (level < 5) {
Line()
.width('12%')
.stroke(level < currentLevel ? '#45B7D1' : '#DDDDDD')
.strokeWidth(2)
.layoutWeight(1)
}
})
}
.width('100%')
.height(50)
.margin({ bottom: 15 })
Text(`当前深度: 第${currentLevel}层 (共5层)`)
.fontSize(14)
.fontColor('#666666')
}
.width('100%')
.backgroundColor('#E8F8F5')
.borderRadius(12)
.padding(15)
.margin({ bottom: 20 })
}
@Builder
renderCounter() {
Row() {
Text('页面访问计数:')
.fontSize(16)
.fontWeight(FontWeight.Bold)
Text(`${this.counter}`)
.fontSize(20)
.fontWeight(FontWeight.Bold)
.fontColor('#FF6B6B')
.margin({ left: 10 })
}
.width('100%')
.height(50)
.backgroundColor('#FFF3E0')
.borderRadius(10)
.justifyContent(FlexAlign.Center)
.margin({ top: 10 })
}
}
import router from '@ohos.router';
import { hilog } from '@kit.PerformanceAnalysisKit';
const DOMAIN = 0x0003;
// 定义数据项接口
interface DataItem {
id: number;
name: string;
value: string;
status: string;
}
// 定义控制面板项接口
interface ControlItem {
title: string;
icon: string;
action: () => void;
}
@Entry
@Component
struct Level3Page {
@State pageTitle: string = '第三层级页面';
@State pageDescription: string = '这是第3层嵌套页面,包含复杂的数据处理和业务逻辑';
@State isLoading: boolean = false;
@State dataList: Array<DataItem> = [];
@State currentIndex: number = 0;
aboutToAppear() {
this.loadData();
}
loadData() {
this.isLoading = true;
// 模拟数据加载
setTimeout(() => {
this.dataList = [
{ id: 1, name: '系统配置项A', value: '启用', status: 'active' },
{ id: 2, name: '数据库连接池', value: '已连接', status: 'connected' },
{ id: 3, name: '缓存服务', value: '运行中', status: 'running' },
{ id: 4, name: '消息队列', value: '正常', status: 'normal' },
{ id: 5, name: '定时任务', value: '执行中', status: 'processing' },
{ id: 6, name: '日志服务', value: '就绪', status: 'ready' },
{ id: 7, name: '监控组件', value: '激活', status: 'active' },
{ id: 8, name: '安全模块', value: '防护中', status: 'protecting' }
];
this.isLoading = false;
}, 1500);
}
build() {
Column() {
// 顶部工具栏
Row() {
Button('← 返回')
.onClick(() => {
router.back();
})
.margin(10)
.backgroundColor('#FF6B6B')
.fontSize(14)
Column() {
Text(this.pageTitle)
.fontSize(18)
.fontWeight(FontWeight.Bold)
Text(`数据项: ${this.dataList.length}`)
.fontSize(12)
.fontColor('#666666')
.margin({ top: 2 })
}
.layoutWeight(1)
Button('深入探索 →')
.onClick(() => {
router.pushUrl({
url: 'pages/Level4Page'
}).catch((err: Error) => {
hilog.error(DOMAIN, 'Navigation', 'Failed to navigate: %{public}s', JSON.stringify(err as object));
});
})
.margin(10)
.backgroundColor('#96CEB4')
.fontSize(14)
}
.width('100%')
.height('12%')
.backgroundColor('#F8F9FA')
.padding({ left: 10, right: 10 })
// 主体内容
Column() {
// 状态指示器
this.renderStatusIndicator()
// 数据列表区域
this.renderDataList()
// 控制面板
this.renderControlPanel()
// 嵌套深度展示
this.renderDepthInfo(3)
}
.layoutWeight(1)
.width('100%')
.padding(15)
// 底部信息栏
Row() {
Text(`加载状态: ${this.isLoading ? '加载中...' : '就绪'}`)
.fontSize(12)
.fontColor(this.isLoading ? '#FF6B6B' : '#4ECDC4')
Blank()
Text(`当前位置: L3/${this.currentIndex + 1}`)
.fontSize(12)
.fontColor('#666666')
}
.width('100%')
.height('8%')
.backgroundColor('#EEEEEE')
.padding(10)
}
.width('100%')
.height('100%')
.backgroundColor('#FFFFFF')
}
@Builder
renderStatusIndicator() {
Row() {
// 系统状态卡片
this.renderSystemCard('CPU', '45%', '#FF6B6B', '💻');
this.renderSystemCard('内存', '68%', '#4ECDC4', '💾');
this.renderSystemCard('网络', '稳定', '#45B7D1', '🌐');
this.renderSystemCard('存储', '23%', '#96CEB4', '🗄️');
}
.width('100%')
.justifyContent(FlexAlign.SpaceBetween)
.margin({ bottom: 20 })
}
@Builder
renderSystemCard(title: string, value: string, color: string, icon: string) {
Column() {
Text(icon)
.fontSize(18)
.margin({ bottom: 5 })
Text(value)
.fontSize(14)
.fontWeight(FontWeight.Bold)
.fontColor(color)
.margin({ bottom: 3 })
Text(title)
.fontSize(10)
.fontColor('#666666')
}
.width('22%')
.height(60)
.backgroundColor('#FFFFFF')
.borderRadius(10)
.border({ width: 1, color: '#EEEEEE' })
.justifyContent(FlexAlign.Center)
.padding(8)
}
@Builder
renderDataList() {
Column() {
Row() {
Text('系统组件状态')
.fontSize(16)
.fontWeight(FontWeight.Bold)
.layoutWeight(1)
Button('刷新')
.onClick(() => {
this.loadData();
})
.backgroundColor('#FFEAA7')
.fontSize(12)
.padding({ left: 12, right: 12 })
}
.width('100%')
.margin({ bottom: 10 })
if (this.isLoading) {
Column() {
Progress({ value: 50, total: 100 })
.width('80%')
.color('#45B7D1')
.margin({ bottom: 10 })
Text('正在加载数据...')
.fontSize(14)
.fontColor('#666666')
}
.width('100%')
.height(100)
.justifyContent(FlexAlign.Center)
} else {
List({ space: 8 }) {
ForEach(this.dataList, (item: DataItem, index: number) => {
ListItem() {
this.renderDataItem(item, index);
}
})
}
.layoutWeight(1)
.width('100%')
.edgeEffect(EdgeEffect.None)
}
}
.width('100%')
.backgroundColor('#F8F9FA')
.borderRadius(12)
.padding(15)
.margin({ bottom: 20 })
}
@Builder
renderDataItem(item: DataItem, index: number) {
Row() {
Column() {
Text(item.name)
.fontSize(14)
.fontWeight(FontWeight.Medium)
.margin({ bottom: 3 })
Text(`ID: ${item.id}`)
.fontSize(11)
.fontColor('#999999')
}
.layoutWeight(1)
Row() {
Text(item.value)
.fontSize(12)
.padding({ left: 8, right: 8 })
.backgroundColor(this.getStatusColor(item.status))
.borderRadius(12)
.fontColor('#FFFFFF')
Blank()
Toggle({ type: ToggleType.Switch })
.onChange((isChecked) => {
// 处理开关变化
})
}
.width('40%')
}
.width('100%')
.height(50)
.backgroundColor('#FFFFFF')
.borderRadius(8)
.border({ width: 1, color: '#EEEEEE' })
.padding({ left: 12, right: 12 })
.onClick(() => {
this.currentIndex = index;
})
}
getStatusColor(status: string): string {
switch (status) {
case 'active': return '#4ECDC4';
case 'connected': return '#45B7D1';
case 'running': return '#96CEB4';
case 'normal': return '#FFEAA7';
case 'processing': return '#FF6B6B';
case 'ready': return '#A2D5F2';
case 'protecting': return '#BB8FCE';
default: return '#CCCCCC';
}
}
@Builder
renderControlPanel() {
Column() {
Text('操作控制台')
.fontSize(16)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 15 })
Grid() {
ForEach([
{ title: '启动服务', icon: '▶️', action: () => {} },
{ title: '停止服务', icon: '⏹️', action: () => {} },
{ title: '重启系统', icon: '🔄', action: () => {} },
{ title: '备份数据', icon: '💾', action: () => {} },
{ title: '清理缓存', icon: '🧹', action: () => {} },
{ title: '系统诊断', icon: '🩺', action: () => {} }
], (item: ControlItem) => {
GridItem() {
Column() {
Text(item.icon)
.fontSize(20)
.margin({ bottom: 5 })
Text(item.title)
.fontSize(11)
.textAlign(TextAlign.Center)
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
.backgroundColor('#E8F4F8')
.borderRadius(8)
.onClick(item.action)
}
})
}
.columnsTemplate('1fr 1fr 1fr')
.rowsTemplate('1fr 1fr')
.columnsGap(8)
.rowsGap(8)
.width('100%')
.height(120)
}
.width('100%')
.backgroundColor('#FFF8E1')
.borderRadius(12)
.padding(15)
.margin({ bottom: 20 })
}
@Builder
renderDepthInfo(currentLevel: number) {
Column() {
Text('嵌套层级信息')
.fontSize(16)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 15 })
// 层级可视化
Row() {
ForEach([1, 2, 3, 4, 5], (level: number) => {
Column() {
Circle({ width: 22, height: 22 })
.fill(level <= currentLevel ? '#96CEB4' : '#DDDDDD')
.stroke(level <= currentLevel ? '#96CEB4' : '#CCCCCC')
.strokeWidth(2)
Text(`${level}`)
.fontSize(10)
.fontColor(level <= currentLevel ? '#96CEB4' : '#999999')
.margin({ top: 3 })
}
.layoutWeight(1)
if (level < 5) {
Line()
.width('10%')
.stroke(level < currentLevel ? '#96CEB4' : '#DDDDDD')
.strokeWidth(2)
.layoutWeight(1)
}
})
}
.width('100%')
.height(45)
.margin({ bottom: 15 })
Text(`当前深度: 第${currentLevel}层 | 总体积目标: ~300MB`)
.fontSize(12)
.fontColor('#666666')
.textAlign(TextAlign.Center)
}
.width('100%')
.backgroundColor('#E8F5E8')
.borderRadius(10)
.padding(15)
}
}
import router from '@ohos.router';
import { hilog } from '@kit.PerformanceAnalysisKit';
const DOMAIN = 0x0004;
// 定义图表数据接口
interface ChartDataItem {
month: string;
value: number;
trend: string;
}
// 定义标签页接口
interface TabItem {
title: string;
index: number;
icon: string;
}
// 定义趋势项接口
interface TrendItem {
label: string;
value: string;
status: string;
}
// 定义资源项接口
interface ResourceItem {
name: string;
value: number;
max: number;
color: string;
}
// 定义配置项接口
interface ConfigItem {
name: string;
enabled: boolean;
}
@Entry
@Component
struct Level4Page {
@State pageTitle: string = '第四层级页面';
@State pageDescription: string = '这是第4层嵌套页面,集成高级功能和复杂业务场景';
@State chartData: Array<ChartDataItem> = [];
@State selectedTab: number = 0;
@State notifications: Array<string> = [];
aboutToAppear() {
this.initializeData();
this.loadNotifications();
}
initializeData() {
// 初始化图表数据
this.chartData = [
{ month: 'Jan', value: 65, trend: 'up' },
{ month: 'Feb', value: 59, trend: 'up' },
{ month: 'Mar', value: 80, trend: 'up' },
{ month: 'Apr', value: 81, trend: 'down' },
{ month: 'May', value: 56, trend: 'up' },
{ month: 'Jun', value: 55, trend: 'down' },
{ month: 'Jul', value: 40, trend: 'down' },
{ month: 'Aug', value: 60, trend: 'up' },
{ month: 'Sep', value: 70, trend: 'up' },
{ month: 'Oct', value: 65, trend: 'down' },
{ month: 'Nov', value: 75, trend: 'up' },
{ month: 'Dec', value: 85, trend: 'up' }
];
}
loadNotifications() {
this.notifications = [
'系统安全扫描完成',
'数据库备份成功',
'新用户注册提醒',
'服务器负载预警',
'API调用频率异常',
'缓存命中率提升',
'第三方服务连接恢复'
];
}
build() {
Column() {
// 顶部导航
Row() {
Button('🔙 上一层')
.onClick(() => {
router.back();
})
.margin(8)
.backgroundColor('#FF6B6B')
.fontSize(12)
.padding({ left: 12, right: 12 })
Column() {
Text(this.pageTitle)
.fontSize(16)
.fontWeight(FontWeight.Bold)
Text(this.pageDescription)
.fontSize(11)
.fontColor('#666666')
.margin({ top: 2 })
}
.layoutWeight(1)
Button('最终层级 ➡️')
.onClick(() => {
router.pushUrl({
url: 'pages/Level5Page'
}).catch((err: Error) => {
hilog.error(DOMAIN, 'Navigation', 'Failed to navigate: %{public}s', JSON.stringify(err as object));
});
})
.margin(8)
.backgroundColor('#6C5CE7')
.fontSize(12)
.padding({ left: 12, right: 12 })
}
.width('100%')
.height('10%')
.backgroundColor('#F1F2F6')
.padding({ left: 10, right: 10 })
// Tab导航
this.renderTabBar()
// 主要内容区域
Tabs({ barPosition: BarPosition.End, index: this.selectedTab }) {
TabContent() {
this.renderAnalyticsTab()
}
.tabBar('数据分析')
TabContent() {
this.renderMonitorTab()
}
.tabBar('系统监控')
TabContent() {
this.renderSettingsTab()
}
.tabBar('高级设置')
}
.barWidth('100%')
.barHeight(50)
.animationDuration(300)
.layoutWeight(1)
.width('100%')
.onChange((index: number) => {
this.selectedTab = index;
})
// 底部状态栏
Row() {
Text(`📊 Tab: ${this.selectedTab + 1}/3`)
.fontSize(11)
.fontColor('#666666')
Blank()
Text(`🔒 最终层级: L5`)
.fontSize(11)
.fontColor('#6C5CE7')
.fontWeight(FontWeight.Bold)
}
.width('100%')
.height('6%')
.backgroundColor('#EEEEEE')
.padding({ left: 15, right: 15 })
}
.width('100%')
.height('100%')
.backgroundColor('#FFFFFF')
}
@Builder
renderTabBar() {
Row() {
ForEach([
{ title: '📊 分析', index: 0, icon: '📈' },
{ title: '🖥️ 监控', index: 1, icon: '📡' },
{ title: '⚙️ 设置', index: 2, icon: '🔧' }
], (tab: TabItem) => {
Column() {
Text(tab.icon)
.fontSize(16)
.margin({ bottom: 2 })
Text(tab.title.replace(/[^\u4e00-\u9fa5]/g, ''))
.fontSize(11)
.fontColor(this.selectedTab === tab.index ? '#6C5CE7' : '#999999')
.fontWeight(this.selectedTab === tab.index ? FontWeight.Bold : FontWeight.Normal)
}
.layoutWeight(1)
.height(45)
.justifyContent(FlexAlign.Center)
.backgroundColor(this.selectedTab === tab.index ? '#E8E6FF' : '#FFFFFF')
.borderRadius(8)
.onClick(() => {
this.selectedTab = tab.index;
})
})
}
.width('100%')
.height(50)
.backgroundColor('#F8F9FA')
.padding(5)
.margin({ bottom: 10 })
}
@Builder
renderAnalyticsTab() {
Scroll() {
Column() {
// 图表展示区
this.renderChartSection()
// 关键指标
this.renderKeyMetrics()
// 趋势分析
this.renderTrendAnalysis()
// 嵌套进度
this.renderNestingProgress(4)
}
.width('100%')
.padding(15)
}
}
@Builder
renderChartSection() {
Column() {
Text('月度数据趋势')
.fontSize(16)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 15 })
// 模拟折线图
Column() {
Row() {
ForEach(this.chartData, (data: ChartDataItem, index: number) => {
Column() {
// 数据点
Circle({ width: 8, height: 8 })
.fill(data.trend === 'up' ? '#6C5CE7' : '#FF6B6B')
.margin({ bottom: 5 })
// 数值标签
Text(`${data.value}`)
.fontSize(9)
.fontColor('#666666')
.margin({ bottom: 3 })
// 月份标签
Text(data.month)
.fontSize(8)
.fontColor('#999999')
}
.layoutWeight(1)
.height(80)
.justifyContent(FlexAlign.End)
// 连接线
if (index < this.chartData.length - 1) {
Line()
.width(1)
.height(30)
.stroke('#CCCCCC')
.layoutWeight(1)
.margin({ top: 25 })
}
})
}
.width('100%')
.height(100)
.margin({ bottom: 15 })
// 图例
Row() {
Row() {
Circle({ width: 10, height: 10 }).fill('#6C5CE7')
Text('上升趋势').fontSize(10).margin({ left: 5 })
}
.margin({ right: 15 })
Row() {
Circle({ width: 10, height: 10 }).fill('#FF6B6B')
Text('下降趋势').fontSize(10).margin({ left: 5 })
}
}
.alignItems(VerticalAlign.Center)
}
.width('100%')
.backgroundColor('#FFFFFF')
.borderRadius(12)
.border({ width: 1, color: '#EEEEEE' })
.padding(15)
}
.width('100%')
.backgroundColor('#F0F0FF')
.borderRadius(15)
.padding(15)
.margin({ bottom: 20 })
}
@Builder
renderKeyMetrics() {
Column() {
Text('核心指标')
.fontSize(16)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 15 })
Row() {
this.renderMetricCard('用户活跃度', '87.5%', '🟢', '#4ECDC4');
this.renderMetricCard('系统稳定性', '99.2%', '🔵', '#45B7D1');
this.renderMetricCard('响应速度', '180ms', '⚡', '#FFD93D');
}
.width('100%')
.justifyContent(FlexAlign.SpaceBetween)
.margin({ bottom: 15 })
}
.width('100%')
.backgroundColor('#FFF5E6')
.borderRadius(12)
.padding(15)
.margin({ bottom: 20 })
}
@Builder
renderMetricCard(title: string, value: string, icon: string, color: string) {
Column() {
Text(icon)
.fontSize(16)
.margin({ bottom: 5 })
Text(value)
.fontSize(14)
.fontWeight(FontWeight.Bold)
.fontColor(color)
.margin({ bottom: 3 })
Text(title)
.fontSize(10)
.fontColor('#666666')
.textAlign(TextAlign.Center)
}
.width('31%')
.height(70)
.backgroundColor('#FFFFFF')
.borderRadius(10)
.border({ width: 1, color: '#EEEEEE' })
.justifyContent(FlexAlign.Center)
.padding(8)
}
@Builder
renderTrendAnalysis() {
Column() {
Text('趋势预测')
.fontSize(16)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 15 })
Column() {
ForEach([
{ label: '下月增长预期', value: '+12.3%', status: 'positive' },
{ label: '季度目标达成', value: '85.7%', status: 'warning' },
{ label: '年度KPI进度', value: '78.2%', status: 'positive' }
], (item: TrendItem) => {
Row() {
Text(item.label)
.fontSize(12)
.layoutWeight(1)
.textAlign(TextAlign.Start)
Row() {
Text(item.value)
.fontSize(12)
.fontWeight(FontWeight.Bold)
.fontColor(item.status === 'positive' ? '#4ECDC4' : '#FFA07A')
Text(item.status === 'positive' ? '↗️' : '➡️')
.fontSize(10)
.margin({ left: 3 })
}
}
.width('100%')
.height(35)
.backgroundColor('#FFFFFF')
.borderRadius(8)
.padding({ left: 12, right: 12 })
.margin({ bottom: 8 })
})
}
.width('100%')
}
.width('100%')
.backgroundColor('#E6F7FF')
.borderRadius(12)
.padding(15)
.margin({ bottom: 20 })
}
@Builder
renderMonitorTab() {
Column() {
Text('实时监控面板')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 20 })
// 通知列表
this.renderNotificationList()
// 系统资源
this.renderResourceMonitor()
}
.width('100%')
.padding(20)
}
@Builder
renderSettingsTab() {
Column() {
Text('高级配置')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 20 })
// 配置选项
this.renderConfigOptions()
// 安全设置
this.renderSecuritySettings()
}
.width('100%')
.padding(20)
}
@Builder
renderNotificationList() {
Column() {
Text('系统通知')
.fontSize(14)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 10 })
List({ space: 5 }) {
ForEach(this.notifications, (notice: string, index: number) => {
ListItem() {
Row() {
Circle({ width: 6, height: 6 })
.fill(index % 2 === 0 ? '#4ECDC4' : '#FF6B6B')
.margin({ right: 10 })
Text(notice)
.fontSize(12)
.layoutWeight(1)
Text(`${index + 1}分钟前`)
.fontSize(10)
.fontColor('#999999')
}
.width('100%')
.height(35)
.backgroundColor('#FFFFFF')
.borderRadius(6)
.padding({ left: 12, right: 12 })
}
})
}
.width('100%')
.height(180)
.backgroundColor('#F8F9FA')
.borderRadius(10)
.padding(8)
}
.width('100%')
.margin({ bottom: 20 })
}
@Builder
renderResourceMonitor() {
Column() {
Text('资源使用情况')
.fontSize(14)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 15 })
ForEach([
{ name: 'CPU使用率', value: 45, max: 100, color: '#FF6B6B' },
{ name: '内存占用', value: 68, max: 100, color: '#4ECDC4' },
{ name: '磁盘空间', value: 23, max: 100, color: '#45B7D1' },
{ name: '网络流量', value: 78, max: 100, color: '#6C5CE7' }
], (resource: ResourceItem) => {
Column() {
Row() {
Text(resource.name)
.fontSize(12)
.layoutWeight(1)
Text(`${resource.value}%`)
.fontSize(12)
.fontWeight(FontWeight.Bold)
.fontColor(resource.color)
}
.width('100%')
.margin({ bottom: 5 })
Progress({ value: resource.value, total: resource.max })
.width('100%')
.color(resource.color)
.backgroundColor('#EEEEEE')
.height(6)
}
.width('100%')
.margin({ bottom: 12 })
})
}
.width('100%')
.backgroundColor('#FFFFFF')
.borderRadius(12)
.padding(15)
}
@Builder
renderConfigOptions() {
Column() {
Text('系统配置')
.fontSize(14)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 15 })
ForEach([
{ name: '自动更新', enabled: true },
{ name: '数据加密', enabled: true },
{ name: '日志记录', enabled: false },
{ name: '性能优化', enabled: true }
], (config: ConfigItem) => {
Row() {
Text(config.name)
.fontSize(13)
.layoutWeight(1)
Toggle({ type: ToggleType.Switch, isOn: config.enabled })
.onChange((isChecked) => {
// 配置变更处理
})
}
.width('100%')
.height(40)
.backgroundColor('#F8F9FA')
.borderRadius(8)
.padding({ left: 15, right: 15 })
.margin({ bottom: 8 })
})
}
.width('100%')
.margin({ bottom: 20 })
}
@Builder
renderSecuritySettings() {
Column() {
Text('安全设置')
.fontSize(14)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 15 })
Button('修改密码')
.onClick(() => {
// 密码修改逻辑
})
.width('100%')
.height(40)
.backgroundColor('#FF6B6B')
.margin({ bottom: 10 })
Button('双因素认证')
.onClick(() => {
// 2FA设置
})
.width('100%')
.height(40)
.backgroundColor('#4ECDC4')
}
.width('100%')
}
@Builder
renderNestingProgress(currentLevel: number) {
Column() {
Text('嵌套层级进度')
.fontSize(14)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 15 })
// 进度可视化
Row() {
ForEach([1, 2, 3, 4, 5], (level: number) => {
Column() {
Circle({ width: 18, height: 18 })
.fill(level <= currentLevel ? '#6C5CE7' : '#DDDDDD')
.stroke(level <= currentLevel ? '#6C5CE7' : '#CCCCCC')
.strokeWidth(1)
if (level <= currentLevel) {
Text(`L${level}`)
.fontSize(8)
.fontColor('#6C5CE7')
.margin({ top: 2 })
}
}
.layoutWeight(1)
if (level < 5) {
Line()
.width('8%')
.stroke(level < currentLevel ? '#6C5CE7' : '#DDDDDD')
.strokeWidth(1)
.layoutWeight(1)
}
})
}
.width('100%')
.height(40)
.margin({ bottom: 10 })
Text(`当前深度: ${currentLevel}/5 层 | 即将到达最终层级`)
.fontSize(11)
.fontColor('#666666')
.textAlign(TextAlign.Center)
}
.width('100%')
.backgroundColor('#E6E6FA')
.borderRadius(10)
.padding(12)
}
}
import router from '@ohos.router';
import { hilog } from '@kit.PerformanceAnalysisKit';
const DOMAIN = 0x0005;
// 定义指标项接口
interface MetricItem {
name: string;
value: string;
color: string;
}
// 定义层级接口
interface LayerItem {
level: number;
name: string;
desc: string;
icon: string;
}
// 定义特性接口
interface FeatureItem {
feature: string;
desc: string;
}
// 定义统计项接口
interface StatItem {
title: string;
value: string;
unit: string;
color: string;
}
@Entry
@Component
struct Level5Page {
@State pageTitle: string = '第五层级页面 - 最终层级';
@State pageDescription: string = '这是最深层级页面,展示了完整的嵌套结构和所有功能';
@State systemStatus: string = '运行正常';
@State performanceScore: number = 92.5;
@State activeConnections: number = 1247;
@State uptime: string = '15天 7小时 23分钟';
@State isProcessing: boolean = false;
aboutToAppear() {
this.simulateProcessing();
}
simulateProcessing() {
this.isProcessing = true;
setTimeout(() => {
this.isProcessing = false;
}, 2000);
}
build() {
Column() {
// 顶部状态栏
Row() {
Button('🏠 返回首页')
.onClick(() => {
router.clear(); // API 20+ 正确的清除历史记录方法
router.pushUrl({
url: 'pages/Index'
}).catch((err: Error) => {
hilog.error(DOMAIN, 'Navigation', 'Failed to navigate home: %{public}s', JSON.stringify(err as object));
});
})
.margin(10)
.backgroundColor('#FF6B6B')
.fontSize(12)
Column() {
Text(this.pageTitle)
.fontSize(14)
.fontWeight(FontWeight.Bold)
Text('🎯 嵌套结构完整展示')
.fontSize(10)
.fontColor('#666666')
.margin({ top: 2 })
}
.layoutWeight(1)
Button('🔄 重新开始')
.onClick(() => {
router.clear(); // API 20+ 正确的清除历史记录方法
router.pushUrl({
url: 'pages/Level1Page'
}).catch((err: Error) => {
hilog.error(DOMAIN, 'Navigation', 'Failed to restart: %{public}s', JSON.stringify(err as object));
});
})
.margin(10)
.backgroundColor('#4ECDC4')
.fontSize(12)
}
.width('100%')
.height('10%')
.backgroundColor('#2D3436')
.padding({ left: 10, right: 10 })
// 主体内容滚动区域
Scroll() {
Column() {
// 系统概览
this.renderSystemOverview()
// 性能仪表板
this.renderPerformanceDashboard()
// 嵌套结构总结
this.renderNestingSummary()
// 技术栈展示
this.renderTechStack()
// 最终统计信息
this.renderFinalStats()
// 操作按钮组
this.renderActionButtons()
}
.width('100%')
.padding(15)
}
.layoutWeight(1)
// 底部信息栏
Row() {
if (this.isProcessing) {
LoadingProgress()
.width(20)
.height(20)
.margin({ right: 10 })
}
Text(`系统状态: ${this.systemStatus}`)
.fontSize(11)
.fontColor(this.systemStatus === '运行正常' ? '#4ECDC4' : '#FF6B6B')
Blank()
Text(`嵌套完成: 5/5 层 ✅`)
.fontSize(11)
.fontColor('#6C5CE7')
.fontWeight(FontWeight.Bold)
}
.width('100%')
.height('8%')
.backgroundColor('#34495E')
.padding({ left: 15, right: 15 })
}
.width('100%')
.height('100%')
.backgroundColor('#ECF0F1')
}
@Builder
renderSystemOverview() {
Column() {
Text('🚀 系统概览')
.fontSize(20)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 20 })
.fontColor('#2C3E50')
// 状态卡片网格
Grid() {
this.renderStatusCard('🔌 连接数', `${this.activeConnections}`, '#3498DB', '实时连接');
this.renderStatusCard('⏱️ 运行时长', this.uptime.split(' ')[0], '#2ECC71', '系统稳定');
this.renderStatusCard('🛡️ 安全等级', 'A+', '#E74C3C', '最高级别');
this.renderStatusCard('⚡ 响应时间', '<50ms', '#F39C12', '超高速');
}
.columnsTemplate('1fr 1fr')
.rowsTemplate('1fr 1fr')
.columnsGap(12)
.rowsGap(12)
.width('100%')
.height(180)
.margin({ bottom: 25 })
}
.width('100%')
.backgroundColor('#FFFFFF')
.borderRadius(15)
.padding(20)
.margin({ bottom: 20 })
.shadow({ radius: 8, color: '#00000010', offsetX: 0, offsetY: 2 })
}
@Builder
renderStatusCard(title: string, value: string, color: string, subtitle: string) {
GridItem() {
Column() {
Text(value)
.fontSize(22)
.fontWeight(FontWeight.Bold)
.fontColor(color)
.margin({ bottom: 5 })
Text(title)
.fontSize(12)
.fontWeight(FontWeight.Medium)
.margin({ bottom: 3 })
Text(subtitle)
.fontSize(10)
.fontColor('#95A5A6')
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
.backgroundColor('#F8F9FA')
.borderRadius(12)
.padding(10)
}
}
@Builder
renderPerformanceDashboard() {
Column() {
Text('📈 性能仪表板')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 20 })
.fontColor('#2C3E50')
// 性能评分圆环
Row() {
// 主要评分
Column() {
// 模拟圆形进度条
Stack() {
Circle({ width: 120, height: 120 })
.fill('#ECF0F1')
.stroke('#BDC3C7')
.strokeWidth(10)
Circle({ width: 120, height: 120 })
.fill('#00000000')
.stroke(this.performanceScore > 90 ? '#2ECC71' :
this.performanceScore > 80 ? '#F39C12' : '#E74C3C')
.strokeWidth(10)
.strokeDashArray([Math.PI * 120 * (this.performanceScore / 100), Math.PI * 120])
Text(`${this.performanceScore}`)
.fontSize(24)
.fontWeight(FontWeight.Bold)
.fontColor('#2C3E50')
}
.width(120)
.height(120)
.margin({ bottom: 10 })
Text('综合性能评分')
.fontSize(12)
.fontColor('#7F8C8D')
}
.layoutWeight(1)
.justifyContent(FlexAlign.Center)
// 详细指标
Column() {
ForEach([
{ name: 'CPU效率', value: '94%', color: '#3498DB' },
{ name: '内存优化', value: '87%', color: '#2ECC71' },
{ name: 'IO性能', value: '91%', color: '#9B59B6' },
{ name: '网络延迟', value: '18ms', color: '#F39C12' }
], (metric: MetricItem) => {
Row() {
Circle({ width: 8, height: 8 })
.fill(metric.color)
.margin({ right: 8 })
Text(metric.name)
.fontSize(11)
.layoutWeight(1)
Text(metric.value)
.fontSize(11)
.fontWeight(FontWeight.Bold)
.fontColor(metric.color)
}
.width('100%')
.margin({ bottom: 8 })
})
}
.layoutWeight(1)
.padding({ left: 20 })
}
.width('100%')
.margin({ bottom: 20 })
}
.width('100%')
.backgroundColor('#FFFFFF')
.borderRadius(15)
.padding(20)
.margin({ bottom: 20 })
.shadow({ radius: 8, color: '#00000010', offsetX: 0, offsetY: 2 })
}
@Builder
renderNestingSummary() {
Column() {
Text('📋 嵌套结构总结')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 20 })
.fontColor('#2C3E50')
// 层级关系图
Column() {
ForEach([
{ level: 1, name: 'Level1Page', desc: '基础功能层', icon: '🏠' },
{ level: 2, name: 'Level2Page', desc: '交互增强层', icon: '📱' },
{ level: 3, name: 'Level3Page', desc: '数据处理层', icon: '📊' },
{ level: 4, name: 'Level4Page', desc: '高级功能层', icon: '🚀' },
{ level: 5, name: 'Level5Page', desc: '最终展示层', icon: '🏆' }
], (layer: LayerItem, index: number) => {
Row() {
// 层级标识
Column() {
Text(layer.icon)
.fontSize(18)
.margin({ bottom: 3 })
Text(`L${layer.level}`)
.fontSize(10)
.fontColor('#7F8C8D')
}
.width(50)
.justifyContent(FlexAlign.Center)
// 连接线
if (index < 4) {
Line()
.height(30)
.stroke('#3498DB')
.strokeWidth(2)
.margin({ left: 20, right: 20 })
} else {
Blank().width(60)
}
// 层级详情
Column() {
Text(layer.name)
.fontSize(14)
.fontWeight(FontWeight.Bold)
.fontColor('#2C3E50')
.margin({ bottom: 3 })
Text(layer.desc)
.fontSize(11)
.fontColor('#95A5A6')
}
.layoutWeight(1)
.padding({ right: 15 })
// 状态指示
Circle({ width: 12, height: 12 })
.fill('#2ECC71')
.margin({ right: 15 })
}
.width('100%')
.height(60)
.backgroundColor(index % 2 === 0 ? '#F8F9FA' : '#FFFFFF')
.borderRadius(8)
.padding({ left: 15, right: 15 })
.margin({ bottom: 5 })
})
}
.width('100%')
.backgroundColor('#FFFFFF')
.borderRadius(12)
.padding(15)
.margin({ bottom: 20 })
// 统计信息
Row() {
this.renderStatBox('总页面数', '5', '📄');
this.renderStatBox('代码行数', '~1500+', '📝');
this.renderStatBox('预计体积', '~300MB', '📦');
}
.width('100%')
.justifyContent(FlexAlign.SpaceBetween)
}
.width('100%')
.backgroundColor('#FFFFFF')
.borderRadius(15)
.padding(20)
.margin({ bottom: 20 })
.shadow({ radius: 8, color: '#00000010', offsetX: 0, offsetY: 2 })
}
@Builder
renderStatBox(title: string, value: string, icon: string) {
Column() {
Text(icon)
.fontSize(16)
.margin({ bottom: 5 })
Text(value)
.fontSize(14)
.fontWeight(FontWeight.Bold)
.fontColor('#3498DB')
.margin({ bottom: 3 })
Text(title)
.fontSize(10)
.fontColor('#7F8C8D')
}
.width('31%')
.height(60)
.backgroundColor('#F8F9FA')
.borderRadius(10)
.justifyContent(FlexAlign.Center)
.padding(8)
}
@Builder
renderTechStack() {
Column() {
Text('🛠️ 技术架构')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 20 })
.fontColor('#2C3E50')
// 技术标签云
Flex({ wrap: FlexWrap.Wrap }) {
ForEach([
'HarmonyOS API 20', 'DevEco Studio 6.0', 'ArkTS', 'Compose UI',
'Native C++', 'Kotlin Multiplatform', 'Router Navigation', 'State Management',
'UI Components', 'Data Binding', 'Async Operations', 'Performance Monitoring'
], (tech: string) => {
Text(tech)
.fontSize(11)
.backgroundColor('#3498DB')
.fontColor('#FFFFFF')
.borderRadius(15)
.padding({ left: 12, right: 12, top: 6, bottom: 6 })
.margin(4)
})
}
.width('100%')
.margin({ bottom: 20 })
// 架构特点
Column() {
ForEach([
{ feature: '🧱 模块化设计', desc: '各层级职责清晰,便于维护扩展' },
{ feature: '🔗 深度嵌套', desc: '5层页面结构,满足复杂业务需求' },
{ feature: '⚡ 高性能', desc: '优化渲染和状态管理,流畅体验' },
{ feature: '🎨 现代UI', desc: 'Material Design风格,视觉统一' }
], (item: FeatureItem) => {
Row() {
Text(item.feature)
.fontSize(12)
.fontWeight(FontWeight.Bold)
.fontColor('#2C3E50')
.width(100)
.flexShrink(0)
Text(item.desc)
.fontSize(11)
.fontColor('#7F8C8D')
.layoutWeight(1)
}
.width('100%')
.margin({ bottom: 12 })
})
}
.width('100%')
}
.width('100%')
.backgroundColor('#FFFFFF')
.borderRadius(15)
.padding(20)
.margin({ bottom: 20 })
.shadow({ radius: 8, color: '#00000010', offsetX: 0, offsetY: 2 })
}
@Builder
renderFinalStats() {
Column() {
Text('📊 项目统计')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 20 })
.fontColor('#2C3E50')
Grid() {
ForEach([
{ title: '页面总数', value: '5', unit: '个', color: '#3498DB' },
{ title: '代码总量', value: '1500+', unit: '行', color: '#2ECC71' },
{ title: '组件数量', value: '50+', unit: '个', color: '#9B59B6' },
{ title: '功能模块', value: '20+', unit: '项', color: '#F39C12' },
{ title: '预计包体', value: '300', unit: 'MB', color: '#E74C3C' },
{ title: '开发耗时', value: '2', unit: '小时', color: '#1ABC9C' }
], (stat: StatItem) => {
GridItem() {
Column() {
Text(stat.value)
.fontSize(20)
.fontWeight(FontWeight.Bold)
.fontColor(stat.color)
.margin({ bottom: 5 })
Text(stat.title)
.fontSize(11)
.fontColor('#7F8C8D')
.margin({ bottom: 2 })
Text(stat.unit)
.fontSize(9)
.fontColor('#BDC3C7')
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
.backgroundColor('#F8F9FA')
.borderRadius(10)
.padding(10)
}
})
}
.columnsTemplate('1fr 1fr 1fr')
.rowsTemplate('1fr 1fr')
.columnsGap(10)
.rowsGap(10)
.width('100%')
.height(140)
}
.width('100%')
.backgroundColor('#FFFFFF')
.borderRadius(15)
.padding(20)
.margin({ bottom: 20 })
.shadow({ radius: 8, color: '#00000010', offsetX: 0, offsetY: 2 })
}
@Builder
renderActionButtons() {
Column() {
Text('🎯 操作中心')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 20 })
.fontColor('#2C3E50')
// 按钮网格
Grid() {
this.renderActionButton('📊 查看报告', '#3498DB', () => {});
this.renderActionButton('💾 导出数据', '#2ECC71', () => {});
this.renderActionButton('⚙️ 系统设置', '#9B59B6', () => {});
this.renderActionButton('❓ 帮助文档', '#F39C12', () => {});
this.renderActionButton('📤 反馈建议', '#E74C3C', () => {});
this.renderActionButton('⭐ 收藏项目', '#1ABC9C', () => {});
}
.columnsTemplate('1fr 1fr')
.rowsTemplate('1fr 1fr 1fr')
.columnsGap(12)
.rowsGap(12)
.width('100%')
.height(180)
}
.width('100%')
.backgroundColor('#FFFFFF')
.borderRadius(15)
.padding(20)
.shadow({ radius: 8, color: '#00000010', offsetX: 0, offsetY: 2 })
}
@Builder
renderActionButton(text: string, color: string, action: () => void) {
GridItem() {
Button(text)
.fontSize(12)
.fontColor('#FFFFFF')
.width('100%')
.height('100%')
.backgroundColor(color)
.borderRadius(10)
.onClick(() => {
action();
})
}
}
}
{
"module": {
"name": "entry",
"type": "entry",
"description": "$string:module_desc",
"mainElement": "EntryAbility",
"deviceTypes": [
"phone"
],
"deliveryWithInstall": true,
"installationFree": false,
"pages": "$profile:main_pages",
"abilities": [
{
"name": "EntryAbility",
"srcEntry": "./ets/entryability/EntryAbility.ets",
"description": "$string:EntryAbility_desc",
"icon": "$media:layered_image",
"label": "$string:EntryAbility_label",
"startWindowIcon": "$media:startIcon",
"startWindowBackground": "$color:start_window_background",
"exported": true,
"orientation": "auto_rotation",
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"ohos.want.action.home"
]
}
]
}
],
"extensionAbilities": [
{
"name": "EntryBackupAbility",
"srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets",
"type": "backup",
"exported": false,
"metadata": [
{
"name": "ohos.extension.backup",
"resource": "$profile:backup_config"
}
],
}
]
}
}
{
"color": [
{
"name": "start_window_background",
"value": "#FFFFFF"
}
]
}
{
"float": [
{
"name": "page_text_font_size",
"value": "50fp"
}
]
}
{
"string": [
{
"name": "module_desc",
"value": "module description"
},
{
"name": "EntryAbility_desc",
"value": "description"
},
{
"name": "EntryAbility_label",
"value": "label"
}
]
}
\ No newline at end of file
This image diff could not be displayed because it is too large. You can view the blob instead.
{
"large_dataset": {
"metadata": {
"version": "1.0",
"created_date": "2024-01-01",
"total_records": 10000,
"data_description": "大型测试数据集用于增加应用包体积"
},
"users": [
{
"id": 1,
"username": "user_00001",
"email": "user00001@example.com",
"profile": {
"first_name": "张",
"last_name": "三",
"age": 28,
"location": "北京市朝阳区",
"bio": "软件工程师,热爱技术分享和开源项目贡献。专注于前端开发和用户体验优化。",
"avatar_url": "https://example.com/avatars/user_00001.jpg",
"preferences": {
"theme": "dark",
"language": "zh-CN",
"notifications": true,
"privacy_level": "public"
}
},
"activity_stats": {
"login_count": 156,
"last_login": "2024-01-15T14:30:22Z",
"projects_created": 3,
"contributions": 47,
"followers": 128,
"following": 67
}
}
],
"system_logs": [
{
"timestamp": "2024-01-15T10:30:15.123Z",
"level": "INFO",
"service": "user-service",
"message": "用户 user_00001 成功登录系统",
"details": {
"ip_address": "192.168.1.100",
"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
"session_id": "sess_a1b2c3d4e5f6",
"device_info": {
"platform": "web",
"browser": "Chrome",
"version": "120.0.0.0"
}
}
}
],
"configuration": {
"app_settings": {
"max_connections": 1000,
"timeout_ms": 30000,
"retry_attempts": 3,
"cache_enabled": true,
"compression_level": 6
},
"feature_flags": {
"new_ui_enabled": true,
"analytics_enabled": true,
"beta_features": false,
"performance_monitoring": true
},
"api_endpoints": [
{
"name": "user_service",
"url": "https://api.example.com/v1/users",
"timeout": 5000,
"retries": 3,
"auth_required": true
},
{
"name": "data_service",
"url": "https://api.example.com/v1/data",
"timeout": 10000,
"retries": 2,
"auth_required": true
},
{
"name": "notification_service",
"url": "https://api.example.com/v1/notifications",
"timeout": 3000,
"retries": 5,
"auth_required": false
}
]
}
}
}
\ No newline at end of file
{
"layered-image":
{
"background" : "$media:background",
"foreground" : "$media:foreground"
}
}
{
"color": [
{
"name": "start_window_background",
"value": "#000000"
}
]
}
// 定义Mock函数类型
interface MockFunction {
(a: number, b: number): number;
}
const NativeMock: Record<string, MockFunction> = {
'add': (a: number, b: number) => {
return a + b;
},
};
export default NativeMock;
{
"libentry.so": {
"source": "src/mock/Libentry.mock.ets"
}
}
import { hilog } from '@kit.PerformanceAnalysisKit';
import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium';
export default function abilityTest() {
describe('ActsAbilityTest', () => {
// Defines a test suite. Two parameters are supported: test suite name and test suite function.
beforeAll(() => {
// Presets an action, which is performed only once before all test cases of the test suite start.
// This API supports only one parameter: preset action function.
})
beforeEach(() => {
// Presets an action, which is performed before each unit test case starts.
// The number of execution times is the same as the number of test cases defined by **it**.
// This API supports only one parameter: preset action function.
})
afterEach(() => {
// Presets a clear action, which is performed after each unit test case ends.
// The number of execution times is the same as the number of test cases defined by **it**.
// This API supports only one parameter: clear action function.
})
afterAll(() => {
// Presets a clear action, which is performed after all test cases of the test suite end.
// This API supports only one parameter: clear action function.
})
it('assertContain', 0, () => {
// Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function.
hilog.info(0x0000, 'testTag', '%{public}s', 'it begin');
let a = 'abc';
let b = 'b';
// Defines a variety of assertion methods, which are used to declare expected boolean conditions.
expect(a).assertContain(b);
expect(a).assertEqual(a);
})
})
}
import abilityTest from './Ability.test';
export default function testsuite() {
abilityTest();
}
{
"module": {
"name": "entry_test",
"type": "feature",
"deviceTypes": [
"phone"
],
"deliveryWithInstall": true,
"installationFree": false
}
}
import localUnitTest from './LocalUnit.test';
export default function testsuite() {
localUnitTest();
}
import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium';
export default function localUnitTest() {
describe('localUnitTest', () => {
// Defines a test suite. Two parameters are supported: test suite name and test suite function.
beforeAll(() => {
// Presets an action, which is performed only once before all test cases of the test suite start.
// This API supports only one parameter: preset action function.
});
beforeEach(() => {
// Presets an action, which is performed before each unit test case starts.
// The number of execution times is the same as the number of test cases defined by **it**.
// This API supports only one parameter: preset action function.
});
afterEach(() => {
// Presets a clear action, which is performed after each unit test case ends.
// The number of execution times is the same as the number of test cases defined by **it**.
// This API supports only one parameter: clear action function.
});
afterAll(() => {
// Presets a clear action, which is performed after all test cases of the test suite end.
// This API supports only one parameter: clear action function.
});
it('assertContain', 0, () => {
// Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function.
let a = 'abc';
let b = 'b';
// Defines a variety of assertion methods, which are used to declare expected boolean conditions.
expect(a).assertContain(b);
expect(a).assertEqual(a);
});
});
}
{
"modelVersion": "6.0.0",
"dependencies": {
},
"execution": {
// "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | "ultrafine" | false ]. Default: "normal" */
// "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */
// "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */
// "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */
// "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */
// "optimizationStrategy": "memory" /* Define the optimization strategy. Value: [ "memory" | "performance" ]. Default: "memory" */
},
"logging": {
// "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */
},
"debugging": {
// "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */
},
"nodeOptions": {
// "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/
// "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/
}
}
import { appTasks } from '@ohos/hvigor-ohos-plugin';
export default {
system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
plugins: [] /* Custom plugin to extend the functionality of Hvigor. */
}
{
"meta": {
"stableOrder": true,
"enableUnifiedLockfile": false
},
"lockfileVersion": 3,
"ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.",
"specifiers": {
"@ohos/hamock@1.0.0": "@ohos/hamock@1.0.0",
"@ohos/hypium@1.0.24": "@ohos/hypium@1.0.24"
},
"packages": {
"@ohos/hamock@1.0.0": {
"name": "@ohos/hamock",
"version": "1.0.0",
"integrity": "sha512-K6lDPYc6VkKe6ZBNQa9aoG+ZZMiwqfcR/7yAVFSUGIuOAhPvCJAo9+t1fZnpe0dBRBPxj2bxPPbKh69VuyAtDg==",
"resolved": "https://ohpm.openharmony.cn/ohpm/@ohos/hamock/-/hamock-1.0.0.har",
"registryType": "ohpm"
},
"@ohos/hypium@1.0.24": {
"name": "@ohos/hypium",
"version": "1.0.24",
"integrity": "sha512-3dCqc+BAR5LqEGG2Vtzi8O3r7ci/3fYU+FWjwvUobbfko7DUnXGOccaror0yYuUhJfXzFK0aZNMGSnXaTwEnbw==",
"resolved": "https://ohpm.openharmony.cn/ohpm/@ohos/hypium/-/hypium-1.0.24.har",
"registryType": "ohpm"
}
}
}
\ No newline at end of file
{
"modelVersion": "6.0.0",
"description": "Please describe the basic information.",
"dependencies": {
},
"devDependencies": {
"@ohos/hypium": "1.0.24",
"@ohos/hamock": "1.0.0"
}
}
{
"resource_references": {
"large_assets": [
"large_binary_file.bin",
"medium_file_1.bin",
"medium_file_2.bin",
"background_image.png",
"icon_pack.zip",
"database_dump.sql",
"video_tutorial.mp4",
"documentation.pdf",
"data_sample_1.json"
],
"total_size_mb": 300,
"purpose": "Force inclusion of large assets in HAP package for volume testing"
}
}
\ No newline at end of file
TEAM_ID=
PRODUCT_NAME=MaxHap
PRODUCT_BUNDLE_IDENTIFIER=com.dong.maxhap.MaxHap$(TEAM_ID)
CURRENT_PROJECT_VERSION=1
MARKETING_VERSION=1.0
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 56;
objects = {
/* Begin PBXBuildFile section */
058557BB273AAA24004C7B11 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 058557BA273AAA24004C7B11 /* Assets.xcassets */; };
058557D9273AAEEB004C7B11 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 058557D8273AAEEB004C7B11 /* Preview Assets.xcassets */; };
2152FB042600AC8F00CF470E /* iOSApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2152FB032600AC8F00CF470E /* iOSApp.swift */; };
7555FF83242A565900829871 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7555FF82242A565900829871 /* ContentView.swift */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
058557BA273AAA24004C7B11 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
058557D8273AAEEB004C7B11 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
2152FB032600AC8F00CF470E /* iOSApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iOSApp.swift; sourceTree = "<group>"; };
7555FF7B242A565900829871 /* MaxHap.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MaxHap.app; sourceTree = BUILT_PRODUCTS_DIR; };
7555FF82242A565900829871 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
7555FF8C242A565B00829871 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
AB3632DC29227652001CCB65 /* Config.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Config.xcconfig; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
B92378962B6B1156000C7307 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
058557D7273AAEEB004C7B11 /* Preview Content */ = {
isa = PBXGroup;
children = (
058557D8273AAEEB004C7B11 /* Preview Assets.xcassets */,
);
path = "Preview Content";
sourceTree = "<group>";
};
42799AB246E5F90AF97AA0EF /* Frameworks */ = {
isa = PBXGroup;
children = (
);
name = Frameworks;
sourceTree = "<group>";
};
7555FF72242A565900829871 = {
isa = PBXGroup;
children = (
AB1DB47929225F7C00F7AF9C /* Configuration */,
7555FF7D242A565900829871 /* iosApp */,
7555FF7C242A565900829871 /* Products */,
42799AB246E5F90AF97AA0EF /* Frameworks */,
);
sourceTree = "<group>";
};
7555FF7C242A565900829871 /* Products */ = {
isa = PBXGroup;
children = (
7555FF7B242A565900829871 /* MaxHap.app */,
);
name = Products;
sourceTree = "<group>";
};
7555FF7D242A565900829871 /* iosApp */ = {
isa = PBXGroup;
children = (
058557BA273AAA24004C7B11 /* Assets.xcassets */,
7555FF82242A565900829871 /* ContentView.swift */,
7555FF8C242A565B00829871 /* Info.plist */,
2152FB032600AC8F00CF470E /* iOSApp.swift */,
058557D7273AAEEB004C7B11 /* Preview Content */,
);
path = iosApp;
sourceTree = "<group>";
};
AB1DB47929225F7C00F7AF9C /* Configuration */ = {
isa = PBXGroup;
children = (
AB3632DC29227652001CCB65 /* Config.xcconfig */,
);
path = Configuration;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
7555FF7A242A565900829871 /* iosApp */ = {
isa = PBXNativeTarget;
buildConfigurationList = 7555FFA5242A565B00829871 /* Build configuration list for PBXNativeTarget "iosApp" */;
buildPhases = (
F36B1CEB2AD83DDC00CB74D5 /* Compile Kotlin Framework */,
7555FF77242A565900829871 /* Sources */,
B92378962B6B1156000C7307 /* Frameworks */,
7555FF79242A565900829871 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = iosApp;
packageProductDependencies = (
);
productName = iosApp;
productReference = 7555FF7B242A565900829871 /* MaxHap.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
7555FF73242A565900829871 /* Project object */ = {
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = YES;
LastSwiftUpdateCheck = 1130;
LastUpgradeCheck = 1540;
ORGANIZATIONNAME = orgName;
TargetAttributes = {
7555FF7A242A565900829871 = {
CreatedOnToolsVersion = 11.3.1;
};
};
};
buildConfigurationList = 7555FF76242A565900829871 /* Build configuration list for PBXProject "iosApp" */;
compatibilityVersion = "Xcode 14.0";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 7555FF72242A565900829871;
packageReferences = (
);
productRefGroup = 7555FF7C242A565900829871 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
7555FF7A242A565900829871 /* iosApp */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
7555FF79242A565900829871 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
058557D9273AAEEB004C7B11 /* Preview Assets.xcassets in Resources */,
058557BB273AAA24004C7B11 /* Assets.xcassets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
F36B1CEB2AD83DDC00CB74D5 /* Compile Kotlin Framework */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
);
name = "Compile Kotlin Framework";
outputFileListPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "if [ \"YES\" = \"$OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED\" ]; then\n echo \"Skipping Gradle build task invocation due to OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED environment variable set to \\\"YES\\\"\"\n exit 0\nfi\ncd \"$SRCROOT/..\"\n./gradlew :composeApp:embedAndSignAppleFrameworkForXcode\n";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
7555FF77242A565900829871 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
2152FB042600AC8F00CF470E /* iOSApp.swift in Sources */,
7555FF83242A565900829871 /* ContentView.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
7555FFA3242A565B00829871 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = AB3632DC29227652001CCB65 /* Config.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.3;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
7555FFA4242A565B00829871 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = AB3632DC29227652001CCB65 /* Config.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.3;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
7555FFA6242A565B00829871 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_ASSET_PATHS = "\"iosApp/Preview Content\"";
DEVELOPMENT_TEAM = "${TEAM_ID}";
ENABLE_PREVIEWS = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(SRCROOT)/../composeApp/build/xcode-frameworks/$(CONFIGURATION)/$(SDK_NAME)\n$(SRCROOT)/../composeApp/build/xcode-frameworks/$(CONFIGURATION)/$(SDK_NAME)",
);
INFOPLIST_FILE = iosApp/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.3;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
OTHER_LDFLAGS = (
"$(inherited)",
"-framework",
composeApp,
);
PRODUCT_BUNDLE_IDENTIFIER = "${BUNDLE_ID}${TEAM_ID}";
PRODUCT_NAME = "MaxHap";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
7555FFA7242A565B00829871 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_ASSET_PATHS = "\"iosApp/Preview Content\"";
DEVELOPMENT_TEAM = "${TEAM_ID}";
ENABLE_PREVIEWS = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(SRCROOT)/../composeApp/build/xcode-frameworks/$(CONFIGURATION)/$(SDK_NAME)\n$(SRCROOT)/../composeApp/build/xcode-frameworks/$(CONFIGURATION)/$(SDK_NAME)",
);
INFOPLIST_FILE = iosApp/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.3;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
OTHER_LDFLAGS = (
"$(inherited)",
"-framework",
composeApp,
);
PRODUCT_BUNDLE_IDENTIFIER = "${BUNDLE_ID}${TEAM_ID}";
PRODUCT_NAME = "MaxHap";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
7555FF76242A565900829871 /* Build configuration list for PBXProject "iosApp" */ = {
isa = XCConfigurationList;
buildConfigurations = (
7555FFA3242A565B00829871 /* Debug */,
7555FFA4242A565B00829871 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
7555FFA5242A565B00829871 /* Build configuration list for PBXNativeTarget "iosApp" */ = {
isa = XCConfigurationList;
buildConfigurations = (
7555FFA6242A565B00829871 /* Debug */,
7555FFA7242A565B00829871 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 7555FF73242A565900829871 /* Project object */;
}
\ No newline at end of file
{
"colors" : [
{
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
\ No newline at end of file
{
"images": [
{
"idiom": "universal",
"platform": "ios",
"size": "1024x1024"
}
],
"info": {
"author": "xcode",
"version": 1
}
}
\ No newline at end of file
{
"info": {
"author": "xcode",
"version": 1
}
}
\ No newline at end of file
import UIKit
import SwiftUI
import ComposeApp
struct ComposeView: UIViewControllerRepresentable {
func makeUIViewController(context: Context) -> UIViewController {
MainViewControllerKt.MainViewController()
}
func updateUIViewController(_ uiViewController: UIViewController, context: Context) {}
}
struct ContentView: View {
var body: some View {
ComposeView()
.ignoresSafeArea(.keyboard) // Compose has own keyboard handler
}
}
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
</dict>
</plist>
{
"info": {
"author": "xcode",
"version": 1
}
}
\ No newline at end of file
import ComposeApp
import SwiftUI
@main
struct iOSApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
\ No newline at end of file
rootProject.name = "MaxHap"
// 启用类型安全项目访问器特性(Type-safe project accessors)
enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
/**
专门管理 Gradle 插件的解析和应用:
影响 plugins {} 块中的插件解析
影响 buildscript {} 块中的插件解析
影响插件版本管理
影响插件仓库配置
只在构建脚本配置阶段生效
*/
pluginManagement {
repositories {
maven("https://maven.eazytec-cloud.com/nexus/repository/maven-public/")
// 引入 Gradle 插件门户(主要用于查找 Gradle 插件)
gradlePluginPortal()
}
}
/**
专门管理项目依赖的解析:
影响 dependencies {} 块中的依赖解析
影响 implementation、api、compileOnly 等依赖声明
影响依赖版本管理
影响依赖仓库配置
在整个项目构建过程中生效
*/
dependencyResolutionManagement {
repositories {
maven("https://maven.eazytec-cloud.com/nexus/repository/maven-public/")
}
}
// 包含 composeApp 模块
include(":composeApp")
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment