跳转至

AirUI 组件演示

一、概述

本项目是基于 AirUI 图形用户界面库的完整组件演示程序,展示了多种 UI 组件和功能模块。每个演示模块独立运行,通过主程序 main.lua 统一调度管理。

二、演示功能概述

2.1 核心驱动模块

1、main.lua - 主程序入口

  • 项目初始化和版本定义

  • 系统任务调度和看门狗配置

  • 演示模块的选择和加载

2、lcd_drv.lua - LCD 显示驱动

  • 初始化 LCD 屏幕及背光
  • 配置显示参数和缓冲区
  • 初始化 AirUI 框架

3、tp_drv.lua - 触摸面板驱动

  • 初始化 GT911 触摸控制器
  • 配置 I2C 通信和触摸回调
  • 绑定触摸设备到 AirUI 输入系统

2.2 基础组件演示

  1. airui_label.lua - 标签组件演示
  2. airui_button.lua - 按钮组件演示
  3. airui_image.lua - 图片组件演示
  4. airui_container.lua - 容器组件演示
  5. airui_bar.lua - (动态)进度条组件演示

2.3 交互组件演示

  1. airui_switch.lua - 开关组件演示
  2. airui_dropdown.lua - 下拉框组件演示
  3. airui_input.lua - 输入框和虚拟键盘演示
  4. airui_msgbox.lua - 消息框组件演示

2.4 布局与高级组件演示

  1. airui_table.lua - 表格组件演示
  2. airui_tabview.lua - 选项卡组件演示
  3. airui_win.lua - 窗口组件演示
  4. airui_switch_page.lua - 多页面切换功能演示
  5. airui_all_component.lua - 所有组件综合演示

2.5 字体渲染演示

  1. airui_hzfont.lua - HzFont 矢量字体特性演示

三、准备硬件环境

1、Air780EGH 核心板 × 1

2、AirLCD_1010 触摸配件板 × 1

3、母对母杜邦线 × 17,杜邦线太长的话,会出现 spi 通信不稳定的现象;

4、TYPE-C 数据线 × 1

5、Air780EGH 核心板和 AirLCD_1010 配件板的硬件接线方式为

  • Air780EGH 核心板通过 TYPE-C USB 口供电(核心板正面开关拨到 ON 一端),此种供电方式下,VDD_EXT 引脚为 3.3V,可以直接给 AirLCD_1010 配件板供电;
  • 为了演示方便,所以 Air780EGH 核心板上电后直接通过 VBAT 引脚给 AirLCD_1010 配件板供电;
  • 客户在设计实际项目时,一般来说,需要通过一个 GPIO 来控制 LDO 给配件板供电,这样可以灵活地控制配件板的供电,可以使项目的整体功耗降到最低;

LCD 显示屏接线

Air780EHM/Air780EHV/Air780EGH 核心板 AirLCD_1010配件板
53/LCD_CLK SCLK/CLK
52/LCD_CS CS
49/LCD_RST RES/RST
50/LCD_SDA SDA/MOS
51/LCD_RS DC/RS
22/GPIO1 BLK
VBAT VCC
67/I2C1_SCL SCL
66/I2C1_SDA SDA
20/GPIO24 INT

四、准备软件环境

4.1 软件环境

在开始实践本示例之前,先筹备一下软件环境:

1、烧录工具:Luatools 下载调试工具

2、内核固件:本demo开发测试时使用的固件为LuatOS-SoC_V2024_Air780EGH 14号固件(请选择支持 airui 功能固件),所以你如果要测试本demo时,可以直接使用最新版本支持 airui 功能的内核固件;如果发现最新版本的内核固件测试有问题,可以使用我们开发本demo时使用的内核固件版本来对比测试;

3、脚本文件:https://gitee.com/openLuat/LuatOS/tree/master/module/Air780EHM_Air780EHV_Air780EGH/demo/ui/airui/single

4、lib脚本文件:使用Luatools烧录时,勾选 添加默认lib 选项,使用默认lib脚本文件

准备好软件环境之后,接下来查看如何烧录项目文件到Air780EGH核心板,将本篇文章中演示使用的项目文件烧录到Air780EGH核心板中。

4.2 API 介绍

airui-功能强大的图形化开发:https://docs.openluat.com/osapi/core/airui/

五、程序结构

ui/airui/single
│── main.lua
│── images                    
    │── xxx.jpg                 
│── airui_all_component.lua
│── airui_bar.lua
│── airui_button.lua
│── airui_container.lua
│── airui_dropdown.lua
│── airui_hzfont.lua
│── airui_image.lua
│── airui_input.lua
│── airui_label.lua
│── airui_msgbox.lua
│── airui_switch.lua
│── airui_switch_page.lua
│── airui_table.lua
│── airui_tabview.lua
│── airui_win.lua
│── lcd_drv.lua
│── tp_drv.lua
│── readme.md

5.1 文件说明

1、main.lua:整个项目的入口点。它负责初始化系统环境

2、images

  • xxx.jpg:演示图片文件(和lua脚本文件一起烧录,会自动放置在/luadb/目录下)

3、airui_all_component.lua:所有组件综合演示

4、airui_bar.lua:(动态)进度条组件演示

5、airui_button.lua:按钮组件演示

6、airui_container.lua:容器组件演示

7、airui_dropdown.lua:下拉框组件演示

8、airui_hzfont.lua:HzFont 矢量字体特性演示

9、airui_image.lua:图片组件演示

10、airui_input.lua:输入框和虚拟键盘演示

11、airui_label.lua:标签组件演示

12、airui_msgbox.lua:消息框组件演示

13、airui_switch.lua:开关组件演示

14、airui_switch_page.lua:多页面切换功能演示

15、airui_table.lua:表格组件演示

17、airui_win.lua:窗口组件演示

18、lcd_drv.lua:LCD 显示驱动

19、tp_drv.lua:触摸面板驱动

六、代码详解

6.1 main.lua

主程序文件 main.lua 是整个项目的入口点。它负责初始化系统环境。

-- 加载显示驱动
require("lcd_drv")
-- 加载触摸驱动
require("tp_drv")

-- 引入演示模块(每次只选择一个运行)
-- require("airui_label") --动态更新标签演示
-- require("airui_button")  --按钮演示
-- require("airui_image")  --图片显示演示
-- require("airui_container")  --容器演示
-- require("airui_bar")  --动态进度条演示
-- require("airui_dropdown")  --下拉框演示
-- require("airui_switch")  --开关组件演示
-- require("airui_msgbox")  --消息框组件演示
-- require("airui_input")  --输入框和键盘演示
-- require("airui_tabview")  --选项卡演示
-- require("airui_table") --表格演示
-- require("airui_win")  --标签窗口演示
require("airui_all_component") --所有组件综合演示
-- require("airui_switch_page")  --页面切换演示
-- require("airui_hzfont")  --内置软件矢量字体演示

-- 用户代码已结束
-- 结尾总是这一句
sys.run()
-- sys.run()之后不要加任何语句!!!!!因为添加的任何语句都不会被执行

6.2 airui_all_component.lua

本文件演示所有AirUI组件的综合用法,展示完整UI界面。

local function ui_main()
    -- 初始化硬件


    -- 创建主容器(竖屏尺寸)
    local main_container = airui.container({
        x = 0,
        y = 0,
        w = 320,    -- 改为320
        h = 480,    -- 保持480
        color = 0xF5F5F5,
    })

    -- 1. 标题区域
    local title_bar = airui.container({
        parent = main_container,
        x = 0,
        y = 0,
        w = 320,
        h = 50,
        color = 0x007AFF,
    })

    local title_label = airui.label({
        parent = title_bar,
        text = "AirUI组件演示",
        x = 10,
        y = 10,
        w = 300,
        h = 30,
    })

    -- 2. 内容区域(可滚动区域)
    local scroll_container = airui.container({
        parent = main_container,
        x = 0,
        y = 50,     -- 从标题栏下面开始
        w = 320,
        h = 380,    -- 为底部键盘留出空间
        color = 0xFFFFFF,
    })

    -- 2.1 文本输入框组件
    airui.label({
        parent = scroll_container,
        text = "文本输入",
        x = 10,
        y = 10,
        w = 300,
        h = 20,
    })

    local text_input = airui.textarea({
        parent = scroll_container,
        x = 10,
        y = 35,
        w = 300,
        h = 40,
        max_len = 50,
        text = "示例文本",
        placeholder = "请输入...",
        on_text_change = function(self, text)
            log.info("textarea", "输入: " .. text)
        end
    })

    -- 2.2 进度条组件
    airui.label({
        parent = scroll_container,
        text = "进度条",
        x = 10,
        y = 85,
        w = 100,
        h = 20,
    })

    local progress_bar = airui.bar({
        parent = scroll_container,
        x = 10,
        y = 110,
        w = 300,
        h = 15,
        value = 65,
        bg_color = 0xE0E0E0,
        indicator_color = 0x4CAF50,
        radius = 7,
    })

    -- 2.3 按钮组件 - 横向排列
    local btn_container = airui.container({
        parent = scroll_container,
        x = 10,
        y = 135,
        w = 300,
        h = 50,
        color = 0xFFFFFF,
    })

    local test_btn = airui.button({
        parent = btn_container,
        x = 0,
        y = 0,
        w = 145,
        h = 40,
        text = "更新进度",
        on_click = function()
            local current = progress_bar:get_value()
            local new_value = current + 10
            if new_value > 100 then
                new_value = 0
            end
            progress_bar:set_value(new_value, true)
            log.info("progress", "进度更新为: " .. new_value .. "%")
        end
    })

    local msgbox_btn = airui.button({
        parent = btn_container,
        x = 155,
        y = 0,
        w = 145,
        h = 40,
        text = "显示消息",
        on_click = function()
            local msgbox = airui.msgbox({
                title = "提示",
                text = "这是消息框演示\n点击确定关闭",
                buttons = { "确定", "取消" },
                timeout = 2000,
                on_action = function(self, label)
                    log.info("msgbox", "点击了: " .. label)
                end
            })
            msgbox:show()
        end
    })

    -- 2.4 开关组件
    local switch_container = airui.container({
        parent = scroll_container,
        x = 10,
        y = 195,
        w = 300,
        h = 40,
        color = 0xFFFFFF,
    })

    airui.label({
        parent = switch_container,
        text = "开关",
        x = 0,
        y = 10,
        w = 60,
        h = 20,
    })

    local is_on = true
    local toggle_switch = airui.switch({
        parent = switch_container,
        x = 70,
        y = 5,
        w = 60,
        h = 30,
        checked = true,
        on_change = function(self)
            is_on = not is_on
            if is_on then
                log.info("当前状态: 开")
            else
                log.info("当前状态: 关")
            end
        end
    })

    -- 2.5 下拉框组件
    airui.label({
        parent = scroll_container,
        text = "下拉选择",
        x = 10,
        y = 245,
        w = 100,
        h = 20,
    })

    local dropdown = airui.dropdown({
        parent = scroll_container,
        x = 10,
        y = 270,
        w = 300,
        h = 40,
        options = { "选项一", "选项二", "选项三", "选项四" },
        default_index = 0,
        on_change = function(self, index)
            local texts = { "选项一", "选项二", "选项三", "选项四" }
            log.info("dropdown", "选择了: " .. texts[index + 1])
        end
    })

    -- 2.6 表格组件
    airui.label({
        parent = scroll_container,
        text = "数据表格",
        x = 10,
        y = 320,
        w = 300,
        h = 20,
    })

    local data_table = airui.table({
        parent = scroll_container,
        x = 10,
        y = 345,
        w = 300,
        h = 120,
        rows = 3,
        cols = 3,
        col_width = { 100, 80, 100 },
        border_color = 0xCCCCCC
    })

    -- 设置表格内容
    data_table:set_cell_text(0, 0, "姓名")
    data_table:set_cell_text(0, 1, "年龄")
    data_table:set_cell_text(0, 2, "城市")
    data_table:set_cell_text(1, 0, "张三")
    data_table:set_cell_text(1, 1, "25")
    data_table:set_cell_text(1, 2, "北京")
    data_table:set_cell_text(2, 0, "李四")
    data_table:set_cell_text(2, 1, "30")
    data_table:set_cell_text(2, 2, "上海")

    -- 3. 创建虚拟键盘(放在底部)
    local keyboard = airui.keyboard({
        x = 0,
        y = -20,  -- 距离底边10像素
        w = 320,
        h = 200,
        mode = "text",
        target = text_input,
        auto_hide = true,
        on_commit = function()
            log.info("input", "输入内容: ", text_input:get_text())
        end,
    })

    -- 4. 底部状态栏
    local status_bar = airui.container({
        parent = main_container,
        x = 0,
        y = 460,  -- 从460位置开始
        w = 320,
        h = 20,
        color = 0x333333,
    })

    airui.label({
        parent = status_bar,
        text = "AirUI Demo v1.0",
        x = 10,
        y = 2,
        w = 300,
        h = 16,
    })

end

sys.taskInit(ui_main)

6.3 airui_bar.lua

本文件演示airui.bar组件的用法,展示动态变化的进度条。

local direction = 1 -- 变化方向
local current = 0   -- 当前值

local function ui_main()
    -- 初始化硬件


    -- 创建进度条
    local progress = airui.bar({
        x = 20,
        y = 200,
        w = 280,
        value = 30
    })

    -- 主循环
    while true do

        -- 更新进度条值
        current = current + direction
        if current >= 100 then
            direction = -1
        elseif current <= 0 then
            direction = 1
        end

        progress:set_value(current, true)
        sys.wait(50)
    end
end

sys.taskInit(ui_main)

6.4 airui_button.lua

本文件演示airui.button组件的用法,展示可点击按钮。

local function ui_main()
    -- 初始化硬件


    -- 创建按钮
    local btn = airui.button({ 
        x = 20, 
        y = 80, 
        on_click = function() 
            log.info("btn", "按钮被点击了") 
        end 
    })


end

sys.taskInit(ui_main)

6.5 airui_container.lua

本文件演示airui.container组件的用法,展示如何创建容器并添加子组件。

local function ui_main()
    -- 初始化硬件


    -- 创建红色容器
    local box = airui.container({
        x = 100,
        y = 100,
        w = 100,
        h = 100,
        color = 0xff0000
    })

    -- 在容器中添加标签
    local label = airui.label({
        parent = box, -- 指定父容器
        text = "容器中的标签",
        x = 10,
        y = 50,
        w = 100,
        h = 100,
    })


end

sys.taskInit(ui_main)

6.6 airui_dropdown.lua

本文件演示airui.dropdown组件的用法,展示下拉选择功能。

local function ui_main()
    -- 初始化硬件


    -- 创建标签显示选择结果
    local label = airui.label({
        text = "请选择选项",
        x = 50,
        y = 80,
        w = 200,
        h = 40,
    })

    -- 创建下拉框
    local dd = airui.dropdown({
        x = 50,
        y = 120,
        w = 120,
        h = 40,
        options = { "选项A", "选项B", "选项C" },
        default_index = 1,
        on_change = function(self, index)
            -- 更新标签显示选择结果
            local texts = { "选项A", "选项B", "选项C" }
            label:set_text("选择了: " .. texts[index + 1])
        end
    })


end

sys.taskInit(ui_main)

6.7 airui_hzfont.lua

本文件演示HzFont矢量字体的各项特性,包括全字号无级缩放、抗锯齿优化和字体使用自由。

local function ui_main()
    -- 初始化硬件


    -- 创建主容器(竖屏尺寸)
    local main_container = airui.container({
        x = 0,
        y = 0,
        w = 320,
        h = 480,
        color = 0xFFFFFF,  -- 白色背景
    })

    -- 标题区域
    local title_bar = airui.container({
        parent = main_container,
        x = 0,
        y = 0,
        w = 320, 
        h = 60, 
        color = 0x2196F3,  -- 蓝色背景
    })

    local title_label = airui.label({
        parent = title_bar,
        text = "HzFont矢量字体演示",
        x = 10,
        y = 15,
        w = 300,
        h = 30,
    })

    -- 创建可滚动内容区域
    local scroll_area = airui.container({
        parent = main_container,
        x = 0,
        y = 60,     -- 从标题栏下方开始
        w = 320,
        h = 400,    -- 留出底部空间
        color = 0xF8F9FA,  -- 浅灰色背景
    })

    -- 第1个特性卡片:全字号无级缩放
    local card1 = airui.container({
        parent = scroll_area,
        x = 10,
        y = 20,
        w = 300,
        h = 120,
        color = 0xFFFFFF,
        radius = 8,        -- 圆角
    })

    local card1_title = airui.label({
        parent = card1,
        text = "特性一:全字号无级缩放",
        x = 10,
        y = 10,
        w = 280,
        h = 25,
    })

    local card1_content = airui.label({
        parent = card1,
        text = "完整支持12-255字号,可随意指定任意大小,满足精细化界面排版需求。提供多种字号展示效果。",
        x = 10,
        y = 40,
        w = 280,
        h = 70,
    })

    -- 第2个特性卡片:智能抗锯齿优化
    local card2 = airui.container({
        parent = scroll_area,
        x = 10,
        y = 150,    -- 与上一个卡片保持间距
        w = 300,
        h = 120,
        color = 0xFFFFFF,
        radius = 8,
    })

    local card2_title = airui.label({
        parent = card2,
        text = "特性二:智能抗锯齿优化",
        x = 10,
        y = 10,
        w = 280,
        h = 25,
    })

    local card2_content = airui.label({
        parent = card2,
        text = "支持可调节的抗锯齿等级,有效平滑字体边缘,提升显示细腻度与视觉效果。适合不同尺寸文字渲染。",
        x = 10,
        y = 40,
        w = 280,
        h = 70,
    })

    -- 第3个特性卡片:字体使用高度自由
    local card3 = airui.container({
        parent = scroll_area,
        x = 10,
        y = 280,    -- 与上一个卡片保持间距
        w = 300,
        h = 120,
        color = 0xFFFFFF,
        radius = 8,
    })

    local card3_title = airui.label({
        parent = card3,
        text = "特性三:字体使用高度自由",
        x = 10,
        y = 10,
        w = 280,
        h = 25,
    })

    local card3_content = airui.label({
        parent = card3,
        text = "既可使用固件内置字库快速上手,也能轻松加载外部.ttf字体文件,便于对定制字体与多国语言的支持。",
        x = 10,
        y = 40,
        w = 280,
        h = 70,
    })

    -- 底部说明区域
    local bottom_info = airui.container({
        parent = main_container,
        x = 0,
        y = 460,    -- 放在底部
        w = 320,
        h = 20,
        color = 0x333333,
    })

    airui.label({
        parent = bottom_info,
        text = "HzFont矢量字体 v1.0",
        x = 10,
        y = 2,
        w = 300,
        h = 16,
    })


end

sys.taskInit(ui_main)

6.8 airui_image.lua

本文件演示airui.image组件的用法,展示图片显示功能。

local function ui_main()
    -- 初始化硬件


    -- 创建可点击图片
    local img = airui.image({
        src = "/luadb/dingwei_50x50.png",
        x = 100,
        y = 176,
        w = 128,
        h = 128,
        opacity = 100, -- 透明度
        on_click = function(self)
            log.info("image", "图片被点击了")
        end
    })

    -- 创建半透明图片
    local img1 = airui.image({
        src = "/luadb/logo.jpg",
        x = 20,
        y = 20,
        w = 80,
        h = 80,
    })


end

sys.taskInit(ui_main)

6.9 airui_input.lua

本文件演示airui.textarea和airui.keyboard组件的用法,展示文本输入功能。

local function ui_main()
    -- 初始化硬件

    -- 创建虚拟键盘
    local keyboard = airui.keyboard({
        x = 0,
        y = -10,
        w = 320,
        h = 200,
        mode = "text",
    })

    -- 创建文本输入框
    local textarea = airui.textarea({
        x = 10,
        y = 50,
        w = 300,
        h = 100,
        max_len = 512,
        text = "在这里输入文字",
        placeholder = "点击输入...",
        keyboard = keyboard
    })

end

sys.taskInit(ui_main)

6.10 airui_label.lua

本文件演示airui.label组件的用法,展示文本标签功能。

local function ui_main()
    -- 初始化硬件


    -- 创建文本标签
    local label1 = airui.label({
        text = "Hello, World!",
        x = 20,
        y = 80,
        w = 100,
        h = 40,
    })

    -- 创建图标标签
    local label2 = airui.label({
        symbol = airui.SYMBOL_SETTINGS,
        x = 120,
        y = 80,
        w = 20,
        h = 20,
        on_click = function(self)
            log.info("label2", "设置图标被点击")
        end
    })

end

sys.taskInit(ui_main)

6.11 airui_msgbox.lua

本文件演示airui.msgbox组件的用法,展示消息提示框功能。

local function ui_main()
    -- 初始化硬件


    -- 创建消息框
    local box = airui.msgbox({
        title = "通知",
        text = "2026年你会发财!",
        buttons = { "确定" },
        on_action = function(self, label)
            if label == "确定" then
                self:hide()
            end
        end
    })

end

sys.taskInit(ui_main)

6.12 airui_switch.lua

本文件演示airui.switch组件的用法,展示开关切换功能。

local function ui_main()
    -- 初始化硬件


    -- 创建标签显示状态
    local label = airui.label({
        text = "当前状态: 开",
        x = 20,
        y = 80,
        w = 150,
        h = 40,
    })

    -- 创建开关
-- 使用一个变量来跟踪当前状态
    local is_on = true -- 初始为ON,与switch的checked=true对应
    local sw = airui.switch({
        x = 20,
        y = 120,
        checked = true,
        on_change = function()
            -- 切换状态
            is_on = not is_on
            -- 根据状态更新文本
            if is_on then
                label:set_text("当前状态: 开")
            else
                label:set_text("当前状态: 关")
            end
        end
    })


end

sys.taskInit(ui_main)

6.13 airui_switch_page.lua

本文件演示如何使用容器组件实现多页面切换功能。

local current_page = 1
local total_pages = 3
local pages = {}

local function ui_main()
    -- 初始化硬件


    -- 创建主容器(竖屏尺寸)
    local main_container = airui.container({
        x = 0,
        y = 0,
        w = 320, -- 改为320
        h = 480, -- 保持480
        color = 0xF8F9FA,
    })

    -- 创建标题栏
    local title_bar = airui.container({
        parent = main_container,
        x = 0,
        y = 0,
        w = 320, -- 改为320
        h = 60,  -- 缩小高度
        color = 0x007AFF,
    })

    local title_label = airui.label({
        parent = title_bar,
        text = "页面切换演示",
        x = 10,
        y = 15,
        w = 200,
        h = 30,
    })

    local page_indicator = airui.label({
        parent = title_bar,
        text = "第1页/共3页",
        x = 220,
        y = 15,
        w = 90,
        h = 30,
    })

    -- 创建内容区域
    local content_area = airui.container({
        parent = main_container,
        x = 10,     -- 左边距
        y = 70,     -- 标题栏下方
        w = 300,    -- 改为300
        h = 300,    -- 减小高度,为导航栏留空间
        color = 0xFFFFFF,
        radius = 8, -- 圆角
    })

    -- 创建三个页面
    for i = 1, total_pages do
        pages[i] = airui.container({
            parent = content_area,
            x = 0,
            y = 0,
            w = 300, -- 改为300
            h = 300,
            color = 0xFFFFFF,
        })

        -- 设置页面初始状态(只显示第一个页面)
        if i ~= 1 then
            pages[i]:set_hidden(true)
        end

        -- 为每个页面添加不同的内容
        if i == 1 then
            -- 第一页:欢迎页面
            local welcome_label = airui.label({
                parent = pages[i],
                text = "欢迎使用页面切换演示",
                x = 0,
                y = 40,
                w = 300,
                h = 40,
            })

            local desc_label = airui.label({
                parent = pages[i],
                text = "这是一个演示多页面切换功能的示例\n使用容器组件实现页面切换\n点击下方按钮切换页面",
                x = 0,
                y = 100,
                w = 300,
                h = 80,
            })
        elseif i == 2 then
            -- 第二页:设置页面
            airui.label({
                parent = pages[i],
                text = "设置页面",
                x = 0,
                y = 20,
                w = 300,
                h = 30,
            })

            -- 设置项目1 - 开关
            local setting1_container = airui.container({
                parent = pages[i],
                x = 20,
                y = 60,
                w = 260,
                h = 40,
                color = 0xFFFFFF,
            })

            airui.label({
                parent = setting1_container,
                text = "开关设置",
                x = 0,
                y = 10,
                w = 120,
                h = 30,
            })

            local switch1 = airui.switch({
                parent = setting1_container,
                x = 130,
                y = 5,
                w = 60,
                h = 30,
                checked = true,
                on_change = function()
                    log.info("page2", "开关1状态改变")
                end
            })

            -- 设置项目2 - 进度条
            local setting2_container = airui.container({
                parent = pages[i],
                x = 20,
                y = 110,
                w = 260,
                h = 50,
                color = 0xFFFFFF,
            })

            airui.label({
                parent = setting2_container,
                text = "亮度调节",
                x = 0,
                y = 15,
                w = 120,
                h = 30,
            })

            local brightness_bar = airui.bar({
                parent = setting2_container,
                x = 130,
                y = 15,
                w = 120,
                h = 20,
                value = 75,
                indicator_color = 0xFF9800,
            })

            -- 设置项目3 - 下拉框
            local setting3_container = airui.container({
                parent = pages[i],
                x = 20,
                y = 170,
                w = 260,
                h = 60,
                color = 0xFFFFFF,
            })

            airui.label({
                parent = setting3_container,
                text = "模式选择",
                x = 0,
                y = 20,
                w = 120,
                h = 30,
            })

            local mode_dropdown = airui.dropdown({
                parent = setting3_container,
                x = 130,
                y = 15,
                w = 120,
                h = 40,
                options = { "自动模式", "手动模式", "节能模式" },
                default_index = 0,
            })
        elseif i == 3 then
            -- 第三页:数据页面
            airui.label({
                parent = pages[i],
                text = "数据展示",
                x = 0,
                y = 20,
                w = 300,
                h = 30,
            })

            -- 创建数据表格(适配竖屏)
            local data_table = airui.table({
                parent = pages[i],
                x = 10,
                y = 60,
                w = 280, -- 减小宽度
                h = 220,
                rows = 5,
                cols = 4,
                col_width = { 70, 70, 70, 70 },
                border_color = 0xCCCCCC
            })

            -- 设置表头
            data_table:set_cell_text(0, 0, "设备")
            data_table:set_cell_text(0, 1, "温度")
            data_table:set_cell_text(0, 2, "湿度")
            data_table:set_cell_text(0, 3, "状态")

            -- 设置数据
            data_table:set_cell_text(1, 0, "传感器1")
            data_table:set_cell_text(1, 1, "25°C")
            data_table:set_cell_text(1, 2, "65%")
            data_table:set_cell_text(1, 3, "正常")

            data_table:set_cell_text(2, 0, "传感器2")
            data_table:set_cell_text(2, 1, "28°C")
            data_table:set_cell_text(2, 2, "70%")
            data_table:set_cell_text(2, 3, "正常")

            data_table:set_cell_text(3, 0, "传感器3")
            data_table:set_cell_text(3, 1, "22°C")
            data_table:set_cell_text(3, 2, "60%")
            data_table:set_cell_text(3, 3, "正常")

            data_table:set_cell_text(4, 0, "传感器4")
            data_table:set_cell_text(4, 1, "30°C")
            data_table:set_cell_text(4, 2, "75%")
            data_table:set_cell_text(4, 3, "警告")
        end
    end

    -- 创建底部导航栏
    local nav_bar = airui.container({
        parent = main_container,
        x = 10,
        y = 380, -- 调整位置
        w = 300,
        h = 90,  -- 增加高度以适应竖屏按钮排列
        color = 0xFFFFFF,
    })

    -- 创建导航按钮容器
    local btn_container = airui.container({
        parent = nav_bar,
        x = 0,
        y = 0,
        w = 300,
        h = 90,
        color = 0xFFFFFF,
    })

    -- 创建上一页和下一页按钮(横向排列)
    local prev_next_container = airui.container({
        parent = btn_container,
        x = 0,
        y = 0,
        w = 300,
        h = 40,
        color = 0xFFFFFF,
    })

    local prev_btn = airui.button({
        parent = prev_next_container,
        x = 0,
        y = 0,
        w = 140,
        h = 40,
        text = "上一页",
        on_click = function()
            if current_page > 1 then
                -- 隐藏当前页面
                pages[current_page]:set_hidden(true)
                current_page = current_page - 1
                -- 显示新页面
                pages[current_page]:set_hidden(false)
                page_indicator:set_text("第" .. current_page .. "页/共3页")
                log.info("page_switch", "切换到第 " .. current_page .. " 页")
            end
        end
    })

    local next_btn = airui.button({
        parent = prev_next_container,
        x = 160,
        y = 0,
        w = 140,
        h = 40,
        text = "下一页",
        on_click = function()
            if current_page < total_pages then
                -- 隐藏当前页面
                pages[current_page]:set_hidden(true)
                current_page = current_page + 1
                -- 显示新页面
                pages[current_page]:set_hidden(false)
                page_indicator:set_text("第" .. current_page .. "页/共3页")
                log.info("page_switch", "切换到第 " .. current_page .. " 页")
            end
        end
    })

    -- 创建页面快速跳转按钮(横向排列)
    local page_btn_container = airui.container({
        parent = btn_container,
        x = 0,
        y = 50,
        w = 300,
        h = 40,
        color = 0xFFFFFF,
    })

    local page_btn_x = 0
    for i = 1, total_pages do
        local btn_text = "第" .. i .. "页"
        local btn_width = 90 -- 每个按钮宽度

        local page_btn = airui.button({
            parent = page_btn_container,
            x = page_btn_x,
            y = 0,
            w = btn_width,
            h = 40,
            text = btn_text,
            on_click = function()
                -- 隐藏所有页面
                for j = 1, total_pages do
                    pages[j]:set_hidden(true)
                end
                -- 显示选中的页面
                current_page = i
                pages[current_page]:set_hidden(false)
                page_indicator:set_text("第" .. current_page .. "页/共3页")
                log.info("page_switch", "跳转到第 " .. current_page .. " 页")
            end
        })
        page_btn_x = page_btn_x + btn_width + 10 -- 按钮间距
    end


end

sys.taskInit(ui_main)

6.14 airui_table.lua

本文件演示airui.table组件的用法,展示表格功能。

local function ui_main()
    -- 初始化硬件


    -- 创建3行3列的表格
    local tbl = airui.table({ 
        x = 10, 
        y = 10, 
        h = 200,
        w = 310,
        rows = 3, 
        cols = 3
    })

    -- 设置表格标题
    tbl:set_cell_text(0, 0, "姓名")
    tbl:set_cell_text(0, 1, "年龄")
    tbl:set_cell_text(0, 2, "城市")

    -- 设置表格内容
    tbl:set_cell_text(1, 0, "张三")
    tbl:set_cell_text(1, 1, "25")
    tbl:set_cell_text(1, 2, "北京")

    tbl:set_cell_text(2, 0, "李四")
    tbl:set_cell_text(2, 1, "30")
    tbl:set_cell_text(2, 2, "上海")


end

sys.taskInit(ui_main)

6.15 airui_tabview.lua

本文件演示airui.tabview组件的用法,展示多页面切换功能。

local function ui_main()
    -- 初始化硬件


    -- 创建选项卡视图
    local tv = airui.tabview({
        x = 0,
        y = 0,
        w = 320,
        h = 480,
        tabs = { "页面A", "页面B", "页面C", "页面D", "页面E" }
    })

    -- 获取各个页面容器
    local page1 = tv:get_content(0)
    local page2 = tv:get_content(1)
    local page3 = tv:get_content(2)
    local page4 = tv:get_content(3)
    local page5 = tv:get_content(4)

    -- 在每个页面中添加标签
    airui.label({ parent = page1, text = "这是页面A", x = 100, y = 80 })
    airui.label({ parent = page2, text = "这是页面B", x = 100, y = 80 })
    airui.label({ parent = page3, text = "这是页面C", x = 100, y = 80 })
    airui.label({ parent = page4, text = "这是页面D", x = 100, y = 80 })
    airui.label({ parent = page5, text = "这是页面E", x = 100, y = 80 })


end

sys.taskInit(ui_main)

6.16 airui_win.lua

本文件演示airui.win组件的用法,展示窗口功能。

local function ui_main()
    -- 初始化硬件


    -- 创建窗口
    local win1 = airui.win({
        title = "示例窗口",
        x = 0,
        y = 0,
        w = 320,
        h = 400,
        close_btn = true,
        auto_center = false,
        style = "radius",
        on_close = function(self)
            log.info("win", "窗口已关闭")
        end
    })

    -- 在窗口中添加标签
    local label1 = airui.label({
        parent = win1,
        text = "窗口中的内容",
        x = 20,
        y = 20,
    })

    -- 当前版本子组件还需再添加进win组件,后续版本可能添加为父级即可
    win1:add_content(label1)


end

sys.taskInit(ui_main)

6.17 lcd_drv.lua

LCD显示驱动模块,基于lcd核心库。

local function lcd_drv_init()
    local result = lcd.init("st7796",
        {
            pin_pwr = 1,       -- 背光控制引脚GPIO端口号
            port = lcd.HWID_0, -- 驱动端口
            pin_rst = 36,      -- lcd复位引脚
            direction = 0,     -- lcd屏幕方向 0:0° 1:90° 2:180° 3:270°,屏幕方向和分辨率保存一致
            w = 320,           -- lcd 水平分辨率
            h = 480,           -- lcd 竖直分辨率
            xoffset = 0,       -- x偏移(不同屏幕ic 不同屏幕方向会有差异)
            yoffset = 0,       -- y偏移(不同屏幕ic 不同屏幕方向会有差异)
        })

    log.info("lcd.init", result)

    if result then
        -- 开启缓冲区, 刷屏速度会加快, 但也消耗2倍屏幕分辨率的内存
        lcd.setupBuff(nil, true)
        lcd.autoFlush(false)

        -- 初始化AirUI
        local width, height = lcd.getSize()
        local result = airui.init(width, height)
        if not result then
            log.error("airui", "init failed")
            return result
        end

        -- 加载中文字体
        if rtos.bsp() ~= "Air8101" then
            -- PC端/Air8000/780EHM 从14号固件/114号固件中加载hzfont字库,从而支持12-255~号中文显示
            airui.font_load({
                type = "hzfont",   -- 字体类型,可选 "hzfont" 或 "bin"
                path = nil,        -- 字体路径,对于 "hzfont",传 nil 则使用内置字库
                size = 20,         -- 字体大小,默认 16
                cache_size = 1048, -- 缓存字数大小,默认 2048
                antialias = 1,     -- 抗锯齿等级1-3,默认 1
            })
        else
            -- Air8101使用104号固件将字体文件烧录到文件系统,从文件系统中加载hzfont字库,从而支持12-255号中文显示
            airui.font_load({
                type = "hzfont",             -- 字体类型,可选 "hzfont" 或 "bin"
                path = "/MiSans_gb2312.ttf", -- 字体路径,对于 "hzfont",传 nil 则使用内置字库
                size = 20,                   -- 字体大小,默认 16
                cache_size = 1048,           -- 缓存字数大小,默认 2048
                antialias = 1,               -- 抗锯齿等级1-3,默认 1
                -- load_to_psram= true,
                global = true
            })
        end

        -- 开启背光引脚供电
        gpio.setup(1, 1)

        -- 查询当前固件内AirUI核心库版本,V1.0.3新增接口
        log.info("airui", "version -> " .. airui.version())

        return result
    end

end

lcd_drv_init()

6.18 tp_drv.lua

触摸面板驱动模块,基于tp核心库。

local function tp_drv_init()

    -- 初始化硬件I2C
    i2c.setup(1, i2c.SLOW) -- 初始化I2C 1,设置为低速模式

    -- 此处触摸IC数据读取使用的是硬件I2C接口
    -- 参数说明:
    -- "gt911": 触摸控制器型号
    -- port: I2C接口
    -- pin_rst: 复位引脚编号
    -- pin_int: 中断引脚编号
    -- w: 触摸面板宽度
    -- h: 触摸面板高度
    local result = tp.init("gt911", { port = 1, pin_rst = 0xff, pin_int = gpio.WAKEUP0, w = 320, h = 480 })

    log.info("tp.init", result)

    if rtos.bsp() ~= "PC" then

        -- 绑定触摸设备到AirUI输入设备
        airui.device_bind_touch(result)

        -- 在PC模拟器上启用系统键盘输入
        airui.keyboard_enable_system(true)
    else
        if not result then
            log.error("ui_main", "触摸初始化失败")
            return result
        else
            -- 绑定触摸设备到AirUI输入设备
            return airui.device_bind_touch(result)
        end
    end
end

tp_drv_init()

七、显示效果展示

7.1 硬件准备

  1. 按照硬件接线表连接所有设备
  2. 通过 TYPE-C USB 口供电
  3. 检查所有接线无误

7.2 软件配置

main.lua 中选择要运行的演示模块:

-- 加载显示驱动
require("lcd_drv")
-- 加载触摸驱动
require("tp_drv")

-- 引入演示模块(每次只选择一个运行)
-- require("airui_label") --动态更新标签演示
-- require("airui_button")  --按钮演示
-- require("airui_image")  --图片显示演示
-- require("airui_container")  --容器演示
-- require("airui_bar")  --动态进度条演示
-- require("airui_dropdown")  --下拉框演示
-- require("airui_switch")  --开关组件演示
-- require("airui_msgbox")  --消息框组件演示
-- require("airui_input")  --输入框和键盘演示
-- require("airui_tabview")  --选项卡演示
-- require("airui_table") --表格演示
-- require("airui_win")  --标签窗口演示
require("airui_all_component") --所有组件综合演示
-- require("airui_switch_page")  --页面切换演示
-- require("airui_hzfont")  --内置软件矢量字体演示

7.3 软件烧录

  1. 使用 Luatools 烧录对应型号的最新内核固件
  2. 下载本项目所有脚本文件和图片文件
  3. 将演示图片文件(如 logo.jpg 等)同.lua脚本文件一起烧录到脚本分区
  4. 设备自动重启后开始运行选定的演示模块

7.4 功能测试

组件
输入法



八、使用合宙 LuatOS-PC 模拟器仿真 airui

8.1 PC 模拟器说明

  • 合宙 LuatOS-PC 模拟器是一个能在 win10/win11 上模拟运行 lua 脚本的仿真软件,内置 LuatOS 内核固件,运行.lua 脚本效果与实际设备类似;
  • 目前 PC 模拟器可以通过 LuaTools 工具的资源管理器进行下载,所以我们需要先下载安装 LuaTools 工具,然后再通过 LuaTools 工具来下载 LuatOS-PC 模拟器,最后通过 LuatOS-PC 模拟器运行 airui演示 demo;

8.2 LuatOS-PC 模拟器安装步骤

1、点击下载:Luatools v3 下载调试工具

2、通过 LuaTools 工具下载 LuatOS-PC 模拟器

  • LuaTools 工具安装完毕后,点击首页面左上角的--账户--打开资源下载
  • 选择-公共资源--LuatOS 的 PC 模拟器--选择最新版本 LuatOS-PC 模拟器--点击开始下载(非刷机)

4.3 下载底层固件和上层运行脚本

  1. 下载运行所需固件,点击资源管理--选择 Air780EGHV的 LuatOS 固件--下载V2024版本及以上的 14/114 号固件
  2. 下载本演示 demo 内所有.lua 脚本文件、images 文件夹内的图片(以下图片仅是示范,请根据实际情况下载对应固件)

4.4 使用 LuatOS-PC 模拟器仿真 运行 airui 演示 demo

  1. 返回 Luatloos 工具首页,点击--项目管理测试

  1. 创建一个项目并命名

  1. 选择固件刚才下载的固件--点击打开,路径在 Luatools 目录下 resource\LuatOS_Air780EGH\LuatOS-SoC_VXXXX_Air780EGH(以下图片仅是示范,请根据实际情况选择对应固件)

  1. 将下载的 demo 图片资源和.lua文件拖入到项目管理内的脚本和资源列表区域--勾选添加默认 lib--点击模拟器运行--出来的界面就是 demo 在实际设备上运行界面的仿真,可以用鼠标进行交互(以下图片仅是示范,请根据实际情况选择对应固件和脚本)

  1. 如需切换 demo 内的演示内容,可打开下载脚本文件中的 mian.lua 文件,将需要演示 demo 的 require 前面的注释符"--"去掉,将不需要演示 demo 的 require 前面加上注释符“--”。修改后保存代码文件,再点击模拟器运行,就会出现所 require 的 demo 对应的界面仿真。
  2. 比如:需要演示下拉框组件,将 main.lua 文件中的-- require("airui_dropdown") 改为 require("airui_dropdown") ,并把其他加载的组件改为注释状态。

九、故障排除

9.1 常见问题及解决方案

1、显示异常

  • 检查 LCD 接线是否存在异常
  • 确认 lcd_drv.lua 内屏幕型号及其参数配置是否正确

2、触摸无响应

  • 检查 I2C 接线是否存在异常
  • 确认确认 tp_drv.lua 内触摸芯片型号配置正确

3、字体显示异常

  • 确认选择的字体驱动与硬件匹配
  • 检查固件版本是否支持所选字体

4、图片无法显示

  • 确认图片文件已正确烧录
  • 检查文件路径和名称是否正确

5、系统运行缓慢

  • 检查是否有过多的组件同时渲染
  • 适当调整刷新间隔时间

9.2 调试技巧

  • 使用 log.info() 输出调试信息
  • 检查系统内存使用情况
  • 逐步启用组件排查问题