跳转至

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 - 所有组件综合演示
  6. airui_chart.lua - 图表组件演示
  7. airui_qrcode.lua - 二维码组件演示

2.5 字体渲染演示

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

三、准备硬件环境

1、Air8101 核心板 × 1

2、AirLCD_1020 触摸配件板 × 1

3、双排40PIN的双头线 x 1

4、TYPE-C 数据线 × 1

5、Air8101 核心板和 AirLCD_1020配件板的硬件接线方式为

  • Air8101 核心板通过 TYPE-C USB 口供电(核心板背面的功耗测试开关拨到 OFF 一端,正面开关打到 3.3V 一端),此种供电方式下,vbat 引脚为 3.3V,可以直接给 AirLCD_1020配件板供电;
  • 为了演示方便,所以 Air8101 核心板上电后直接通过 vbat 引脚给 AirLCD_1020配件板提供了 3.3V 的供电;
  • 客户在设计实际项目时,一般来说,需要通过一个GPIO来控制LDO给LCD和TP供电,这样可以灵活地控制供电,可以使项目的整体功耗降到最低;
  • 核心板和配件板之间配备了双排40PIN的双头线,可以参考下表很方便地连接双方各自的40个管脚,插入或者拔出双头线时,要慢慢的操作,防止将排针折弯

    • 核心板和配件板之间配备了双排40PIN的双头线,可以参考下表很方便地连接双方各自的40个管脚,插入或者拔出双头线时,要慢慢的操作,防止将排针折弯;

5.2 接线配置

5.2.1 显示屏接线

Air8101核心板 AirLCD_1020配件板
gnd GND
vbat VCC
42/R0 RGB_R0
40/R1 RGB_R1
43/R2 RGB_R2
39/R3 RGB_R3
44/R4 RGB_R4
38/R5 RGB_R5
45/R6 RGB_R6
37/R7 RGB_R7
46/G0 RGB_G0
36/G1 RGB_G1
47/G2 RGB_G2
35/G3 RGB_G3
48/G4 RGB_G4
34/G5 RGB_G5
49/G6 RGB_G6
33/G7 RGB_G7
50/B0 RGB_B0
32/B1 RGB_B1
51/B2 RGB_B2
31/B3 RGB_B3
52/B4 RGB_B4
30/B5 RGB_B5
53/B6 RGB_B6
29/B7 RGB_B7
28/DCLK RGB_DCLK
54/DISP RGB_DISP
55/HSYN RGB_HSYNC
56/VSYN RGB_VSYNC
57/DE RGB_DE
14/GPIO8 LCD_BL
13/GPIO9 LCD_RST
8/GPIO5 LCD_SDI
9/GPIO6 LCD_SCL
68/GPIO12 LCD_CS
75/GPIO28 TP_RST
10/GPIO7 TP_INT
12/U1TX TP_SCL
11/U1RX TP_SDA

四、准备软件环境

4.1 软件环境

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

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

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

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

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

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

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_chart.lua
│── airui_container.lua
│── airui_dropdown.lua
│── airui_hzfont.lua
│── airui_image.lua
│── airui_input.lua
│── airui_label.lua
│── airui_msgbox.lua
│── airui_qrcode.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_chart.lua:图表组件演示

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

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

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

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

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

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

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

14、airui_qrcode.lua:二维码组件演示

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

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

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

18、airui_tabview.lua:选项卡组件演示

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

20、lcd_drv.lua:LCD 显示驱动

21、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")  --内置软件矢量字体演示
-- require("airui_chart")  --图表组件演示
-- require("airui_qrcode") --二维码组件演示

-- 用户代码已结束
-- 结尾总是这一句
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 = 800,
        h = 480,
        color = 0xF5F5F5,
    })

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

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

    -- 2. 左列组件
    local left_col = airui.container({
        parent = main_container,
        x = 20,
        y = 70,
        w = 380,
        h = 380,
        color = 0xFFFFFF,
        radius = 8,
    })

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

    -- 创建虚拟键盘
    local keyboard = airui.keyboard({
        x = 0,
        y = -20, -- 底部留20像素边距
        w = 800,
        h = 250,
        mode = "text",
        auto_hide = true,
    })

    -- 创建输入框并绑定键盘
    local text_input = airui.textarea({
        parent = left_col,
        x = 20,
        y = 50,
        w = 340,
        h = 60,
        max_len = 50,
        text = "示例文本",
        placeholder = "请输入...",
        keyboard = keyboard,
        on_text_change = function(text)
            log.info("textarea", text)
        end
    })

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

    local progress_bar = airui.bar({
        parent = left_col,
        x = 20,
        y = 160,
        w = 340,
        h = 20,
        value = 65,
        bg_color = 0xE0E0E0,
        indicator_color = 0x4CAF50,
        radius = 10,
    })

    -- 2.3 按钮组件
    local test_btn = airui.button({
        parent = left_col,
        x = 20,
        y = 200,
        w = 150,
        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
    })

    -- 2.4 消息框按钮
    local msgbox_btn = airui.button({
        parent = left_col,
        x = 200,
        y = 200,
        w = 150,
        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)
                    self:hide()
                end
            })
        end
    })

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

    local dropdown = airui.dropdown({
        parent = left_col,
        x = 20,
        y = 280,
        w = 200,
        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 = left_col,
        text = "开关",
        x = 240,
        y = 250,
        w = 60,
        h = 30,
    })

    -- 使用一个变量来跟踪当前状态
    local is_on = true -- 初始为ON,与switch的checked=true对应

    local toggle_switch = airui.switch({
        parent = left_col,
        x = 240,
        y = 280,
        checked = true,
        on_change = function(self)
            -- 切换状态
            is_on = not is_on
            -- 根据状态更新日志
            if is_on then
                log.info("当前状态: 开")
            else
                log.info("当前状态: 关")
            end
        end
    })

    -- 2.7 在左列底部添加图表组件(折线图)
    airui.label({
        parent = left_col,
        text = "图表(简化)",
        x = 20,
        y = 320,
        w = 100,
        h = 20,
    })

    local chart = airui.chart({
        parent = left_col,
        x = 20,
        y = 340,
        w = 340,
        h = 40,
        type = "line",
        y_min = 0,
        y_max = 100,
        point_count = 30,
        line_color = 0x00b4ff,
        line_width = 1,
        point_radius = 1,
        legend = false,
        x_axis = { enable = false },
        y_axis = { enable = false },
    })
    -- 设置一些示例数据
    chart:set_values(1, {30, 45, 60, 55, 70, 65, 80, 75, 90, 85, 95})

    -- 3. 右列组件
    local right_col = airui.container({
        parent = main_container,
        x = 420,
        y = 70,
        w = 360,
        h = 380,
        color = 0xFFFFFF,
        radius = 8,
    })

    -- 右列标题
    airui.label({
        parent = right_col,
        text = "数据表格",
        x = 20,
        y = 20,
        w = 320,
        h = 25,
    })

    -- 3.1 表格组件
    local data_table = airui.table({
        parent = right_col,
        x = 20,
        y = 60,
        w = 320,
        h = 220,
        rows = 3,
        cols = 3,
        col_width = { 100, 100, 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.2 二维码组件
    airui.label({
        parent = right_col,
        text = "二维码",
        x = 20,
        y = 290,
        w = 100,
        h = 20,
    })

    local qrcode = airui.qrcode({
        parent = right_col,
        x = 125,          -- 居中 (360-70)/2 = 145, 但考虑标签文字占用左边距,微调
        y = 310,
        size = 70,
        data = "https://docs.openluat.com/",
        dark_color = 0x000000,
        light_color = 0xFFFFFF,
        quiet_zone = true
    })

    -- 4. 底部状态栏
    local status_bar = airui.container({
        parent = main_container,
        x = 0,
        y = 460,
        w = 800,
        h = 20,
        color = 0xCFCFCF,
    })

    airui.label({
        parent = status_bar,
        text = "AirUI Demo v1.1",
        x = 20,
        y = 2,
        w = 760,
        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 = 100,
        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()
    -- 初始化硬件


    -- 创建按钮
    -- 示例1:创建一个基础按钮
    local btn1 = airui.button({ 
        text = "点我", 
        x = 20, 
        y = 80, 
        on_click = function() 
            log.info("btn", "tap") 
        end 
    })

    -- 示例2:创建一个支持切换显示内容的按钮,V1.0.3更新
    local is_play = false
    local btn2 = airui.button({
        text = "播放",
        x = 20,
        y = 180,
        on_click = function(self)
            if is_play then
                -- 当前是“停止”,点击后切换为“播放”
                self:set_text("播放") 
                is_play = false
            else
                -- 当前是“播放”,点击后切换为“停止”
                self:set_text("停止") 
                is_play = true
            end
        end
    })


end

sys.taskInit(ui_main)

6.5 airui_chart.lua

本文件演示airui.chart组件的用法,展示折线图动态数据更新。

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


    -- 创建图表(折线图)
    local chart = airui.chart({
        x = 20,
        y = 20,
        w = 760,
        h = 440,
        type = "line",                -- 折线图
        y_min = 0,
        y_max = 100,
        point_count = 120,            -- 数据点总数
        update_mode = "shift",         -- 滚动更新
        line_color = 0x00b4ff,         -- 主系列颜色
        line_width = 2,
        point_radius = 2,              -- 显示数据点
        hdiv = 6,
        vdiv = 6,
        legend = true,                 -- 显示图例
        x_axis = { enable = true, min = 0, max = 120, ticks = 6, unit = "s" },
        y_axis = { enable = true, min = 0, max = 100, ticks = 6, unit = "%" }
    })

    -- 添加第二个系列
    local sid2 = chart:add_series({ color = 0xff6b35, name = "avg" })
    -- 添加第三个系列
    local sid3 = chart:add_series({ color = 0x22c55e, name = "diff" })
    -- 设置第一个系列名称
    chart:set_series_name(1, "raw")

    -- 设置初始数据
    chart:set_values(1, {50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70})
    chart:set_values(sid2, {50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60})
    chart:set_values(sid3, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10})

    -- 模拟动态推送(可选)
    sys.timerLoopStart(function()
        -- 随机生成新数据并推入
        local v1 = 50 + math.random(-20, 20)
        local v2 = 50 + math.random(-15, 15)
        local v3 = v1 - v2
        chart:push(1, v1)
        chart:push(sid2, v2)
        chart:push(sid3, v3)
    end, 1000)
end

sys.taskInit(ui_main)

6.6 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.7 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.8 airui_hzfont.lua

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

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


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

    -- 标题栏(蓝色)
    local title_bar = airui.container({
        parent = main_container,
        x = 0,
        y = 0,
        w = 800,
        h = 80,
        color = 0x2196F3,
    })

    -- 标题:使用大字号 + 白色
    local title_label = airui.label({
        parent = title_bar,
        text = "HzFont 矢量字体演示 (Vector Font Demo)",
        x = 10,
        y = 20,
        w = 780,
        h = 40,
        font_size = 32, -- 大字号突出标题
        color = 0xFFFFFF, -- 白色文字
        align = airui.TEXT_ALIGN_CENTER
    })

    -- 内容区域(浅灰色圆角背景)
    local content_area = airui.container({
        parent = main_container,
        x = 40,
        y = 100,
        w = 720,
        h = 340,
        color = 0xF8F9FA,
        radius = 8,
    })

    -- 第1行:超大字号演示无级缩放(含英文、符号)
    local line1_label = airui.label({
        parent = content_area,
        text = "全字号无级缩放:字号 48 (Scale: 48px)",
        x = 20,
        y = 20,
        w = 680,
        h = 120,
        font_size = 48, -- 超大字号
        color = 0xE63946, -- 鲜艳红色
    })

    -- 第2行:中等字号 + 智能抗锯齿(多颜色)
    local line2_label = airui.label({
        parent = content_area,
        text = "智能抗锯齿优化:字号 28  Anti-aliasing  中文 English",
        x = 20,
        y = 150,
        w = 680,
        h = 70,
        font_size = 28, -- 中等字号
        color = 0x2A9D8F, -- 翠绿色
    })

    -- 第3行:小字号展示多语言和符号(长文本)
    local line3_label = airui.label({
        parent = content_area,
        text = "字体使用高度自由:内置字库 / 外部.ttf。支持中英符号",
        x = 20,
        y = 240,
        w = 680,
        h = 30,
        font_size = 24, -- 较小字号,适合多行文本
        color = 0x264653, -- 深蓝灰色
    })
end

sys.taskInit(ui_main)

6.9 airui_image.lua

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

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


    -- 创建可点击图片
    local img = airui.image({
        src = "/luadb/dingwei_50x50.png",
        x = 336,
        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,
        -- opacity = 100, -- jpg不支持调整透明度
    })


end

sys.taskInit(ui_main)

6.10 airui_input.lua

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

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


    -- 创建虚拟键盘
    local keyboard = airui.keyboard({
        x = 0,
        y = -20, -- 底部留20像素边距
        w = 800,
        h = 250,
        mode = "text",
        auto_hide = true,
    })

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

        -- 创建按钮
    local btn = airui.button({
        x = 20,
        y = 180,
        text = "提交",
        on_click = function()
            airui.msgbox({
                title = "提交内容为",
                text = textarea:get_text(),
                buttons = { "确定" },
                on_action = function(self, label)
                    if label == "确定" then
                        self:hide()
                    end
                end
            })
        end
    })


end

sys.taskInit(ui_main)

6.11 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.12 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.13 airui_qrcode.lua

本文件演示airui.qrcode组件的用法,展示二维码生成与切换。

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


    -- 创建二维码
    local qrcode = airui.qrcode({
        x = 40,
        y = 40,
        size = 220,                     -- 正方形尺寸
        data = "https://docs.openluat.com/",    -- 二维码内容
        dark_color = 0x000000,          -- 深色模块颜色
        light_color = 0xFFFFFF,         -- 浅色模块颜色
        quiet_zone = true                -- 四周留白
    })

    if not qrcode then
        log.error("qrcode", "创建二维码失败")
        return
    end

    -- 添加一个标签说明
    airui.label({
        x = 40,
        y = 280,
        w = 720,
        h = 40,
        text = "扫描上方二维码访问 LuatOS 官网",
        font_size = 20,
        color = 0x333333
    })
end

sys.taskInit(ui_main)

6.14 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
    local sw = airui.switch({
        x = 20,
        y = 120,
        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.15 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 = 800,
        h = 480,
        color = 0xF8F9FA,
    })

    -- 创建标题栏
    local title_bar = airui.container({
        parent = main_container,
        x = 0,
        y = 0,
        w = 800,
        h = 80,
        color = 0x007AFF,
    })

    local title_label = airui.label({
        parent = title_bar,
        text = "页面切换演示",
        x = 20,
        y = 20,
        w = 760,
        h = 40,
    })

    local page_indicator = airui.label({
        parent = title_bar,
        text = "第1页 / 共3页",
        x = 600,
        y = 20,
        w = 180,
        h = 40,
    })

    -- 创建内容区域
    local content_area = airui.container({
        parent = main_container,
        x = 20,
        y = 100,
        w = 760,
        h = 320,
        color = 0xFFFFFF,
        radius = 10,
    })

    -- 创建三个页面
    for i = 1, total_pages do
        pages[i] = airui.container({
            parent = content_area,
            x = 0,
            y = 0,
            w = 760,
            h = 320,
            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 = 50,
                w = 760,
                h = 50,
            })

            local desc_label = airui.label({
                parent = pages[i],
                text = "这是一个演示多页面切换功能的示例\n使用容器组件实现页面切换\n点击下方按钮切换页面",
                x = 0,
                y = 120,
                w = 760,
                h = 100,
            })

        elseif i == 2 then
            -- 第二页:设置页面
            airui.label({
                parent = pages[i],
                text = "设置页面",
                x = 0,
                y = 30,
                w = 760,
                h = 40,
            })

            -- 设置项目1
            airui.label({
                parent = pages[i],
                text = "开关设置",
                x = 50,
                y = 90,
                w = 200,
                h = 30,
            })

            local switch1 = airui.switch({
                parent = pages[i],
                x = 250,
                y = 95,
                checked = true,
                on_change = function()
                    log.info("page2", "开关1状态改变")
                end
            })

            -- 设置项目2
            airui.label({
                parent = pages[i],
                text = "亮度调节",
                x = 50,
                y = 140,
                w = 200,
                h = 30,
            })

            local brightness_bar = airui.bar({
                parent = pages[i],
                x = 250,
                y = 145,
                w = 200,
                h = 20,
                value = 75,
                indicator_color = 0xFF9800,
            })

            -- 设置项目3
            airui.label({
                parent = pages[i],
                text = "模式选择",
                x = 50,
                y = 190,
                w = 200,
                h = 30,
            })

            local mode_dropdown = airui.dropdown({
                parent = pages[i],
                x = 250,
                y = 190,
                w = 200,
                h = 40,
                options = { "自动模式", "手动模式", "节能模式" },
                default_index = 0,
            })

        elseif i == 3 then
            -- 第三页:数据页面
            airui.label({
                parent = pages[i],
                text = "数据展示",
                x = 0,
                y = 30,
                w = 760,
                h = 40,
            })

            -- 创建数据表格
            local data_table = airui.table({
                parent = pages[i],
                x = 50,
                y = 70,
                w = 660,
                h = 240,
                rows = 5,
                cols = 4,
                col_width = { 200, 150, 150, 150 },
                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 = 0,
        y = 430,
        w = 800,
        h = 50,
        color = 0xFFFFFF,
    })

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

    -- 创建上一页按钮
    local prev_btn = airui.button({
        parent = btn_container,
        x = 0,
        y = 0,
        w = 120,
        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 page_btn_x = 140
    for i = 1, total_pages do
        local btn_text = "第" .. i .. "页"
        local page_btn = airui.button({
            parent = btn_container,
            x = page_btn_x,
            y = 0,
            w = 80,
            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 + 90
    end

    -- 创建下一页按钮
    local next_btn = airui.button({
        parent = btn_container,
        x = 480,
        y = 0,
        w = 120,
        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
    })


end

sys.taskInit(ui_main)

6.16 airui_table.lua

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

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


    -- 创建3行3列的表格
    local tbl = airui.table({ 
        x = 10, 
        y = 10, 
        h = 200,
        w = 410,
        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.17 airui_tabview.lua

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

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


    -- 创建选项卡视图
    local tv = airui.tabview({
        x = 0,
        y = 0,
        w = 800,
        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 = 200, y = 80 })
    airui.label({ parent = page2, text = "这是页面B", x = 200, y = 80 })
    airui.label({ parent = page3, text = "这是页面C", x = 200, y = 80 })
    airui.label({ parent = page4, text = "这是页面D", x = 200, y = 80 })
    airui.label({ parent = page5, text = "这是页面E", x = 200, y = 80 })


end

sys.taskInit(ui_main)

6.18 airui_win.lua

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

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


    -- 创建窗口
    local win1 = airui.win({
        title = "示例窗口",
        x = 10,
        y = 10,
        w = 600,
        h = 400,
        close_btn = true,
        auto_center = false,
        style = "radius",
        -- V1.0.4版本实现点击关闭按钮关闭win组件
        on_close = function(self)
            log.info("win", "窗口已关闭")
        end
    })

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

end

sys.taskInit(ui_main)

6.19 lcd_drv.lua

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

local function lcd_drv_init()
    local result = lcd.init("h050iwv",
        {
            pin_pwr = 8,    -- 背光控制引脚GPIO端口号
            port = lcd.RGB, -- 驱动端口
            direction = 0,  -- lcd屏幕方向 0:0° 1:90° 2:180° 3:270°,屏幕方向和分辨率保存一致
            w = 800,        -- 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(8, 1)

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

        return result
    end

end

lcd_drv_init()

6.20 tp_drv.lua

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

local function tp_drv_init()
    -- 初始化软件I2C,接口i2c.createSoft(scl, sda, delay)
    -- 参数说明:
    -- 0: SCL引脚编号
    -- 1: SDA引脚编号
    local result = i2c.createSoft(0, 1)

    if type(result) ~= "userdata" then
        log.error("tp_drv.init i2c.createSoft error")
        return false
    end
    -- 此处触摸IC数据读取使用的是软件I2C接口
    -- 参数说明:
    -- "gt911": 触摸控制器型号
    -- port: I2C接口对象
    -- pin_rst: 复位引脚编号
    -- pin_int: 中断引脚编号
    -- w: 触摸面板宽度
    -- h: 触摸面板高度
    result = tp.init("gt911", { port = result, pin_rst = 28, pin_int = 7, w = 800, 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")  --内置软件矢量字体演示
-- require("airui_chart")  --图表组件演示
-- require("airui_qrcode") --二维码组件演示

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

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

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

  1. 创建一个项目并命名

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

  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() 输出调试信息
  • 检查系统内存使用情况
  • 逐步启用组件排查问题