前言

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

在开源鸿蒙(OpenHarmony)生态快速普及的今天,跨平台开发已经成为移动端开发的主流趋势。但对于绝大多数初学者来说,跨平台开发依然被贴上“复杂、难上手、环境难配、学习成本高”的标签。很多同学在学习过程中都会遇到同一个困境:理论知识看了一大堆,真正动手写项目时却完全不知道从哪里开始,随便一个小问题就能卡住半天,最后只能放弃。

为了让所有想要学习开源鸿蒙跨平台开发的同学都能轻松入门,这篇文章采用全程零跳步、纯实操、保姆级教学的方式,带你从空白项目开始,一步步完成一个功能完整、界面美观、可以直接在Android手机与开源鸿蒙设备上运行的Todo待办清单应用。

整篇教程不要求你学习任何额外语言,不需要Java基础,不需要GS,不需要TS,你只需要会复制粘贴代码、会点击鼠标、会连接手机,就能完整做出可以正常使用的跨平台应用。

文章所有步骤均经过实测验证,所有代码均可直接复制运行,所有报错都提供对应的解决方案,哪怕你是第一次接触移动端开发,也能轻松跟着完成全部内容。

目录(严格按照顺序操作,任何一步都不要跳过)

  1. 关于KuiklyUI框架与本次实战说明
  2. 开发前必备环境与工具准备(最详细版本)
  3. 下载KuiklyTodo项目并正确解压与导入
  4. 第一步:编写TodoItem.kt——定义待办事项数据结构
  5. 第二步:编写TodoPage.kt——实现应用全部业务逻辑
  6. 第三步:编写TodoPageUI.kt——构建双端通用界面布局
  7. 第四步:Android端完整运行教程(真机+调试全流程)
  8. 第五步:开源鸿蒙(OpenHarmony)端编译与安装教程
  9. 双端功能完整测试与效果展示
  10. 新手99%会遇到的问题一站式排查
  11. 项目功能扩展与进阶优化方向
  12. 学习总结与KuiklyUI后续学习建议

1. 关于KuiklyUI框架与本次实战说明

1.1 什么是KuiklyUI

KuiklyUI是一款专门面向Android + 开源鸿蒙的轻量级高性能跨平台UI框架,它的核心优势是:

  • 一套代码,同时运行在Android与OpenHarmony设备上
  • 原生渲染性能,无WebView,无冗余性能损耗
  • 纯Kotlin编写,语法简洁,学习成本极低
  • 数据自动响应,数据改变界面自动刷新
  • 配置简单,无需复杂工程搭建

1.2 本次实战我们要做什么

我们将从零完成一款标准Todo待办应用,具备以下完整功能:

  1. 输入待办内容并添加
  2. 标记待办为已完成/未完成
  3. 删除单条待办事项
  4. 一键清空所有已完成待办
  5. 实时统计未完成待办数量
  6. 双端界面样式完全统一
  7. 操作流畅,无卡顿、无延迟

整个应用只需要修改3个文件,不需要改动任何配置文件,不需要添加任何依赖,非常适合新手入门。

1.3 学习本篇文章你能获得什么

  1. 掌握KuiklyUI框架的基本使用方式
  2. 学会数据结构、业务逻辑、界面分离的开发思想
  3. 独立完成一款可上线的双端应用
  4. 掌握Android与鸿蒙真机调试、安装、运行流程
  5. 具备独立排查新手常见报错的能力
  6. 拥有属于自己的第一个鸿蒙跨平台作品

2. 开发前必备环境与工具准备

在正式开始写代码之前,我们必须把环境准备到位,这是项目能够成功运行的基础。

2.1 电脑系统要求

  • Windows 10 或 Windows 11 64位系统(推荐使用)
  • macOS 12及以上版本(苹果电脑也可正常操作)

注意:电脑磁盘至少保留10GB以上空闲空间,保证编译正常运行。

2.2 必须安装的工具

(1)Android Studio

作用:用于打开项目、编写代码、运行Android端应用

下载:直接搜索官网下载最新稳定版即可

安装:全程默认下一步,安装过程中勾选Android SDK

(2)DevEco Studio(可选)

作用:用于编译、打包、安装开源鸿蒙应用

如果你暂时没有鸿蒙设备,可以先不安装,只完成Android端即可。

(3)JDK 17

KuiklyUI框架必须使用JDK 17版本,Android Studio新版本会自带,无需单独安装。

2.3 手机准备

Android手机

  1. 打开手机「设置」→ 找到「关于手机」
  2. 连续点击「版本号」5~7次,开启「开发者选项」
  3. 回到设置 → 进入开发者选项
  4. 打开「USB调试」
  5. 用数据线连接电脑,选择「文件传输模式」

开源鸿蒙设备

  1. 打开设置 → 关于本机
  2. 连续点击版本号开启开发者模式
  3. 打开USB调试与允许外部安装应用

2.4 最重要的注意事项

项目路径绝对不能出现中文、空格、特殊字符!

错误路径:C:\用户\桌面\我的项目\KuiklyTodo

正确路径:E:\kuikly\KuiklyTodo-main

这是新手90%编译失败的核心原因。

3. 下载KuiklyTodo项目并正确解压与导入

3.1 下载项目源码

  1. 打开电脑浏览器
  2. 进入AtomGit或GitCode平台  KuiklyTodo - AtomGit | GitCodehttps://gitcode.com/Goway_Hui/KuiklyTodo/tree/main
  3. 在顶部搜索框输入:KuiklyTodo
  4. 找到官方认证的KuiklyUI入门模板项目
  5. 进入项目主页后,找到右上角的「Code」按钮
  6. 点击「Download ZIP」下载项目压缩包
  7. 等待下载完成,压缩包大小约5MB左右

3.2 解压项目文件

  1. 在电脑D盘或E盘根目录新建文件夹,命名为kuikly_workspace
  2. 将下载好的KuiklyTodo-main.zip复制到这个文件夹里
  3. 右键点击压缩包,选择「解压到当前文件夹」
  4. 解压完成后,会出现KuiklyTodo-main文件夹
  5. 打开文件夹,确认里面包含commonandroidAppohosApp等目录

3.3 使用Android Studio打开项目

  1. 启动Android Studio
  2. 在欢迎界面点击「Open an Existing Project」
  3. 在弹出的窗口中找到并选中KuiklyTodo-main文件夹
  4. 点击「OK」开始导入项目
  5. 第一次导入会自动下载依赖、构建工程,耐心等待3~5分钟
  6. 当右上角出现绿色运行按钮,且底部无红色报错,说明导入成功

4. 第一步:修改TodoItem.kt——定义待办事项数据结构

4.1 这个文件的作用

TodoItem.kt是整个应用的数据模板,用来规定一条待办事项包含哪些内容

每条待办必须拥有:

  • 唯一ID:区分不同待办
  • 待办内容:显示的文字
  • 完成状态:标记是否已完成

4.2 精准找到文件位置

在Android Studio左侧展开项目结构,按照以下路径查找:

KuiklyTodo-main/common/src/main/java/com/kuikly/todo/TodoItem.kt

依次点开:

common → src → main → java → com → kuikly → todo

就能看到TodoItem.kt文件。

4.3 替换完整代码

  1. 双击打开TodoItem.kt文件
  2. 使用快捷键Ctrl+A全选原有代码
  3. 删除所有内容
  4. 复制下方代码,直接粘贴进去
  5. 按下Ctrl+S保存文件

package com.kuikly.todo

/**

 * 待办事项数据结构

 * 每条待办固定包含:编号、内容、完成状态

 */

data class TodoItem(

    // 唯一编号,用于区分不同待办

    val id: Long,

    // 待办显示的文字内容

    val content: String,

    // 完成状态,默认未完成

    val isCompleted: Boolean = false

)

4.4 代码逐行详细解释

  • package com.kuikly.todo:声明文件所在位置,必须与文件夹路径一致
  • data class:Kotlin数据类,专门用于存储数据,自动生成通用方法
  • id: Long:使用时间戳作为唯一编号,永远不会重复
  • content: String:存储待办的文字信息
  • isCompleted: Boolean = false:标记待办是否完成,默认是未完成状态

将代码替换为

package com.tencent.kuikly.demo.pages.todo

/**

 * 待办事项数据实体类

 * 用于存储单个 Todo 的信息

 */

data class TodoItem(

    // 唯一标识 ID

    val id: Long,

    // 待办内容

    var content: String,

    // 是否完成,默认未完成

    var isCompleted: Boolean = false

)

5. 第二步:修改TodoPage.kt——实现应用全部业务逻辑

5.1 这个文件的作用

TodoPage.kt是整个应用的核心逻辑控制中心,所有功能操作都在这里实现,相当于应用的大脑。

我们将在这里实现:

  • 待办列表存储
  • 输入框内容管理
  • 添加待办
  • 切换完成状态
  • 删除待办
  • 清空已完成待办
  • 统计未完成待办数量

5.2 找到文件

TodoPage.kt与TodoItem.kt在同一个文件夹下,直接在左侧找到即可。

5.3 全量替换代码

  1. 打开TodoPage.kt
  2. Ctrl+A全选 → 删除
  3. 粘贴下方完整代码
  4. Ctrl+S保存

package com.kuikly.todo

import com.kuikly.core.observable

import com.kuikly.core.observableList

class TodoPage {

    /**

     * 待办列表

     * 使用observableList:数据改变时,界面自动刷新

     */

    val todoList = observableList<TodoItem>()

    /**

     * 输入框双向绑定数据

     * 输入框内容变化 → 变量自动更新

     * 变量变化 → 输入框自动更新

     */

    val inputText = observable("")

    /**

     * 添加待办方法

     * 1. 获取输入框内容并去除空格

     * 2. 判断内容不为空才添加

     * 3. 使用时间戳作为唯一ID

     * 4. 添加完成后清空输入框

     */

    fun addTodo() {

        val content = inputText.value.trim()

        if (content.isNotEmpty()) {

            todoList.add(

                TodoItem(

                    id = System.currentTimeMillis(),

                    content = content

                )

            )

            // 清空输入框

            inputText.value = ""

        }

    }

    /**

     * 切换待办完成状态

     * 未完成 → 已完成

     * 已完成 → 未完成

     */

    fun toggleTodo(index: Int) {

        val currentItem = todoList[index]

        todoList[index] = currentItem.copy(

            isCompleted = !currentItem.isCompleted

        )

    }

    /**

     * 删除指定位置的待办

     */

    fun deleteTodo(index: Int) {

        todoList.removeAt(index)

    }

    /**

     * 清空所有已完成的待办

     */

    fun clearCompleted() {

        todoList.removeAll { item ->

            item.isCompleted

        }

    }

    /**

     * 统计未完成待办的数量

     */

    fun getUndoneCount(): Int {

        return todoList.count { item ->

            !item.isCompleted

        }

    }

}

5.4 核心功能详细说明

  1. todoList:存储所有待办事项,数据变化后界面会自动刷新,不需要手动更新
  2. inputText:与输入框双向绑定,输入和展示完全同步
  3. addTodo():只有输入内容不为空时才会添加,添加后自动清空输入框
  4. toggleTodo():点击即可切换完成状态,操作极简
  5. deleteTodo():根据位置删除对应待办
  6. clearCompleted():一键清理已完成待办,保持界面整洁
  7. getUndoneCount():实时计算未完成数量,展示给用户

将代码替换为这个

/**

 * @ProjectName : KuiklyUI

 * @Author : GuoJiaHui

 * @Time : 2026年01月29日 17:30 PM

 * @Description : 待办事项页面逻辑控制器

 * 负责管理待办事项列表的数据状态、增删改查操作

 */

package com.tencent.kuikly.demo.pages.todo

import com.tencent.kuikly.core.KuiklyPage

import com.tencent.kuikly.core.observable

import com.tencent.kuikly.core.observableList

class TodoPage : KuiklyPage() {

    // 待办列表(响应式,数据变化自动刷新界面)

    val todoList = observableList<TodoItem>()

    // 输入框内容(双向绑定)

    val inputText = observable("")

    // 自增 ID,保证每条待办的唯一性

    private var autoId = 0L

    /**

     * 添加新的待办事项

     */

    fun addTodo() {

        val content = inputText.value.trim()

        if (content.isEmpty()) return

        todoList.add(

            TodoItem(

                id = autoId++,

                content = content

            )

        )

        inputText.value = ""

    }

    /**

     * 切换待办的完成状态

     */

    fun toggleTodo(item: TodoItem) {

        val index = todoList.indexOf(item)

        if (index != -1) {

            todoList[index] = item.copy(isCompleted = !item.isCompleted)

        }

    }

    /**

     * 删除指定待办

     */

    fun deleteTodo(item: TodoItem) {

        todoList.remove(item)

    }

    /**

     * 清空所有已完成的待办

     */

    fun clearCompleted() {

        todoList.removeAll { it.isCompleted }

    }

    /**

     * 统计未完成的待办数量

     */

    fun getUndoneCount(): Int {

        return todoList.count { !it.isCompleted }

    }

}

6. 第三步:修改TodoPageUI.kt——构建双端通用界面布局

6.1 这个文件的作用

TodoPageUI.kt是应用的界面展示文件,用户看到的所有内容:标题、输入框、按钮、列表、文字全部在这里编写。

KuiklyUI的布局采用代码编写,一套代码同时适配Android与鸿蒙,不需要分别写两套界面。

6.2 找到文件

依然在com.kuikly.todo文件夹下,找到TodoPageUI.kt。

6.3 粘贴完整界面代码

  1. 打开文件
  2. 全选删除原有内容
  3. 粘贴下方代码
  4. 保存文件

package com.kuikly.todo

import com.kuikly.ui.*

import com.kuikly.ui.colors.Color

import com.kuikly.ui.unit.dp

/**

 * 主页面整体布局

 */

fun TodoPageUI(page: TodoPage) = pageView {

    // 垂直布局

    column {

        // 设置页面背景色

        backgroundColor = Color(0xFFF7F8FA)

        // ====================== 页面标题 ======================

        text {

            text = "KuiklyUI 待办清单"

            textSize = 24.dp

            marginStart = 16.dp

            marginTop = 20.dp

            marginBottom = 10.dp

            textColor = Color(0xFF333333)

        }

        // ====================== 输入框 + 添加按钮 ======================

        row {

            padding = 16.dp

            verticalAlignment = Alignment.Center

            // 输入框

            input {

                text = page.inputText

                placeholder = "请输入待办事项"

                height = 44.dp

                weight = 1f

                radius = 8.dp

                backgroundColor = Color.White

                paddingHorizontal = 12.dp

            }

            // 添加按钮

            button {

                text = "添加"

                width = 70.dp

                height = 44.dp

                marginLeft = 10.dp

                radius = 8.dp

                backgroundColor = Color(0xFF409AFF)

                textColor = Color.White

                // 点击事件

                onClick {

                    page.addTodo()

                }

            }

        }

        // ====================== 待办列表 ======================

        list {

            items(page.todoList) { index, item ->

                // 单条待办布局

                row {

                    padding = 14.dp

                    marginHorizontal = 16.dp

                    marginVertical = 5.dp

                    backgroundColor = Color.White

                    radius = 10.dp

                    verticalAlignment = Alignment.Center

                    // 完成状态按钮

                    button {

                        text = if (item.isCompleted) "✓" else "○"

                        width = 36.dp

                        height = 36.dp

                        radius = 18.dp

                        backgroundColor = if (item.isCompleted) Color(0xFF409AFF) else Color(0xFFEEEEEE)

                        textColor = if (item.isCompleted) Color.White else Color(0xFF999999)

                        onClick {

                            page.toggleTodo(index)

                        }

                    }

                    // 待办内容文字

                    text {

                        text = item.content

                        weight = 1f

                        marginHorizontal = 12.dp

                        textSize = 16.dp

                        textColor = if (item.isCompleted) Color(0xFF999999) else Color(0xFF333333)

                        // 已完成添加删除线

                        strikeThrough = item.isCompleted

                    }

                    // 删除按钮

                    button {

                        text = "删除"

                        width = 60.dp

                        height = 36.dp

                        radius = 8.dp

                        backgroundColor = Color(0xFFFF6B6B)

                        textColor = Color.White

                        onClick {

                            page.deleteTodo(index)

                        }

                    }

                }

            }

        }

        // ====================== 统计区域 ======================

        text {

            text = "未完成待办:${page.getUndoneCount()} 项"

            marginStart = 16.dp

            marginTop = 10.dp

            textSize = 14.dp

            textColor = Color(0xFF666666)

        }

        // ====================== 清空已完成按钮 ======================

        button {

            text = "清空已完成"

            height = 42.dp

            margin = 16.dp

            radius = 8.dp

            backgroundColor = Color(0xFFE6E6E6)

            textColor = Color(0xFF333333)

            onClick {

                page.clearCompleted()

            }

        }

    }

}

将代码替换

/**

 * @ProjectName : KuiklyUI

 * @Author : GuoJiaHui

 * @Time : 2026年01月29日 17:30 PM

 * @Description : 待办事项页面UI构建逻辑

 * 包含整体布局、样式定义及事件绑定

 */

package com.tencent.kuikly.demo.pages.todo

import com.tencent.kuikly.core.*

import com.tencent.kuikly.core.extensions.*

fun TodoPage.pageView() = column {

    // 顶部标题

    text("Todo 待办清单") {

        textSize(24)

        textBold()

        margin(20)

        centerHorizontal()

    }

    // 统计栏:未完成数量 + 清空按钮

    row {

        text("未完成:") {

            textSize(14)

            marginLeft(20)

        }

        text {

            textSize(14)

            textColor(0xFFFF5722)

            bindText { page.getUndoneCount().toString() }

        }

        space(weight = 1f)

        button("清空已完成") {

            marginRight(20)

            onClick {

                page.clearCompleted()

            }

        }

    }

    // 待办列表

    list {

        items(page.todoList) { item ->

            todoItem(item)

        }

    }.weight(1f)

    // 底部输入栏

    row {

        input {

            hint("请输入待办事项")

            weight(1f)

            margin(10)

            bindText(page.inputText)

        }

        button("添加") {

            marginRight(10)

            onClick {

                page.addTodo()

            }

        }

    }

}

/**

 * 单条待办项的UI布局

 */

fun ViewScope.todoItem(item: TodoItem) {

    row {

        checkBox {

            checked(item.isCompleted)

            onCheckedChange {

                page.toggleTodo(item)

            }

            margin(10)

        }

        text(item.content) {

            textSize(16)

            marginVertical(14)

            if (item.isCompleted) {

                textColor(0xFF999999)

                strikeThrough()

            } else {

                textColor(0xFF333333)

            }

        }

        space(weight = 1f)

        image {

            res("ic_delete")

            size(24)

            margin(10)

            onClick {

                page.deleteTodo(item)

            }

        }

        onClick {

            page.toggleTodo(item)

        }

        onLongClick {

            page.deleteTodo(item)

            true

        }

    }

    divider()

}

6.4 界面结构说明

整个页面分为5个部分:

  1. 页面标题:展示应用名称
  2. 输入区域:输入框+添加按钮
  3. 待办列表:展示所有待办事项
  4. 统计文字:显示未完成数量
  5. 清空按钮:一键清理已完成待办

每一个控件都支持:颜色、大小、圆角、边距、点击事件,完全满足日常使用需求。

7. 第四步:Android端完整运行教程

7.1 确认项目准备完成

  1. 三个文件已全部替换并保存
  2. Android Studio无红色报错
  3. 手机已开启USB调试并连接电脑

7.2 选择运行模块

在Android Studio右上角找到模块选择框,选择androidApp

7.3 运行应用

  1. 点击绿色三角形运行按钮
  2. 等待编译、打包、安装
  3. 手机上会弹出安装提示,点击允许
  4. 安装完成后,应用自动打开

7.4 功能测试

打开应用后,你可以:

  1. 在输入框输入文字
  2. 点击添加,待办出现在列表
  3. 点击左侧圆圈,标记完成/未完成
  4. 点击删除按钮,移除对应待办
  5. 点击清空已完成,清理所有完成项
  6. 顶部实时显示未完成数量

8. 第五步:开源鸿蒙(OpenHarmony)端编译与安装教程

8.1 配置SDK环境

Windows系统:

  1. 右键此电脑 → 属性 → 高级系统设置 → 环境变量
  2. 新建系统变量:DEVECO_SDK_HOME
  3. 值填写你的DevEco Studio的OpenHarmony SDK路径

8.2 一键编译鸿蒙安装包

  1. 打开项目根目录
  2. Windows系统双击运行:2.0_ohos_demo_build.bat
  3. 等待脚本自动执行,出现BUILD SUCCESSFUL代表编译成功
  4. 生成的.hap文件在:ohosApp/build/outputs/目录下

8.3 安装到鸿蒙设备

  1. 使用DevEco Studio连接鸿蒙设备
  2. 直接把.hap包拖入设备窗口
  3. 等待安装完成
  4. 打开应用,体验与Android完全一致
  5. 实现 Native Bridge (可选但推荐)
    如果你的应用需要跳转页面或调用原生能力,需要配置 Bridge。
     打开ohosApp/entry/src/main/ets/kuikly/modules/KRBridgeModule.ets ,完善  openPage  方法:

// KRBridgeModule.ets

import router from '@ohos.router';

// ...

// TODO open new page

private openPage(params: KRAny) {

  console.info('KRBridgeModule: openPage method execution started');

  try {

    let args: Record<string, Object>;

    if (typeof params === 'string') {

      args = JSON.parse(params) as Record<string, Object>;

    } else {

      args = params as Record<string, Object>;

    }

    const url = args['url'] as string;

    

    // 使用鸿蒙原生路由跳转

    router.pushUrl({

      url: 'pages/Index',

      params: {

        pageName: url // 将目标页面名传给 Index 页面

      }

    });

  } catch (e) {

    console.error(`KRBridgeModule: openPage error: ${JSON.stringify(e)}`);

  }

}

9. 常见问题一站式排查

9.1 项目导入失败

  • 路径包含中文 → 移动到纯英文路径
  • 依赖下载失败 → 检查网络,重新同步
  • 磁盘空间不足 → 清理空间后重试

9.2 手机连接不上

  • 未开启USB调试 → 重新开启
  • 数据线损坏 → 更换数据线
  • 未允许调试 → 手机弹窗点击允许

9.3 应用运行闪退

  • 代码未保存 → 重新保存所有文件
  • 代码复制不完整 → 重新全量复制
  • 包名错误 → 不要修改package声明

9.4 界面不刷新

  • 必须使用observable/observableList
  • 不要直接修改数据,使用框架提供的方法

9.5 鸿蒙编译失败

  • 环境变量配置错误
  • SDK版本过低
  • 重新运行编译脚本

10. 项目扩展与优化方向

完成基础版本后,你可以继续扩展功能,让应用更加强大:

  1. 数据持久化:应用关闭重启后,待办不会消失
  2. 待办编辑:点击待办文字可以修改内容
  3. 任务分类:添加工作、生活、学习等分类标签
  4. 排序功能:按完成状态、时间进行排序
  5. 深色模式:支持白天/黑夜模式自动切换
  6. 任务提醒:设置时间,到点提醒待办
  7. 列表动画:添加、删除时加入流畅动画
  8. 数据导出:将待办数据导出为文件保存

11. 结束语

通过本篇教程,你已经从零完成了一款可以同时运行在Android与开源鸿蒙上的跨平台Todo应用

你不需要学习复杂的语言,不需要配置繁琐的环境,只需要跟着步骤操作,就能拥有属于自己的第一个鸿蒙跨平台项目。这也证明了:鸿蒙跨平台开发并没有想象中难,KuiklyUI让每个人都能轻松入门。

一套代码、双端运行、极简开发、原生性能,这就是KuiklyUI带来的全新开发体验。

如果你在操作过程中遇到任何问题,欢迎随时交流学习。后续我们将继续带来KuiklyUI进阶教程,带你实现更复杂、更强大的跨平台应用。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐