LVGL 拼音输入法(lv_ime_pinyin)使用说明¶
lv_ime_pinyin 是 LVGL 的拼音输入法组件,用于在 lv_textarea + lv_keyboard 的基础上提供中文拼音输入、候选字选择、英文/中文模式切换,以及可选的 9 键输入模式。
本文以当前工程使用的 LVGL v8 接口为主,源码路径:
sdk/external/lvgl_v8/src/extra/others/ime/lv_ime_pinyin.c
sdk/external/lvgl_v8/src/extra/others/ime/lv_ime_pinyin.h
1. 功能概览¶
lv_ime_pinyin 不是独立键盘,而是对 lv_keyboard 的输入事件进行接管和扩展:
绑定一个
lv_keyboard。从键盘获取输入字符。
根据输入的拼音查字典,生成候选字。
在键盘上方显示候选字面板。
点击候选字后,把中文字符写入当前
lv_textarea。支持英文模式、26 键拼音模式、9 键拼音模式、9 键数字模式。
典型 UI 结构如下:
父容器/页面
├── lv_textarea 文本输入框
├── lv_keyboard 软键盘
└── lv_ime_pinyin 拼音输入法对象(内部会创建候选字面板 cand_panel)
1.1 显示效果¶
集成后的典型显示效果如下图所示:

实际交互表现:
输入框位于页面上半部分,用于显示和编辑文本内容。
键盘固定在页面底部,按键样式由
lv_keyboard决定。输入拼音后,候选字面板会显示在键盘上方;未输入拼音或候选为空时,候选面板隐藏。
候选面板中间为候选汉字,点击候选字后会写入当前
lv_textarea。候选面板两侧的
<、>用于候选字翻页。中用于在英文和中文拼音 26 键之间切换;ABC、abc用于大小写/英文键盘切换。在
pcalendar编辑页面中,候选面板设置为白色不透明背景、深色文字、高度 36 px,以避免和上方输入内容重叠。
2. 配置开关¶
使用前需要先启用 LVGL v8,并打开拼音输入法。menuconfig 的完整路径为:menuconfig (Top) → SiFli SDK configuration → Third party packages → LittlevGL2RTT: The LittlevGl gui lib adapter RT-Thread (PKG_USING_LITTLEVGL2RTT) → LVGL configuration → select LVGL Version. → LVGL V8 → LVGL V8 configuration → Others → Enable Pinyin input method (LV_USE_IME_PINYIN)。PKG_USING_LITTLEVGL2RTT 默认关闭,启用后 select LVGL Version. 默认选择 LVGL V8;该 SDK 路径在 HCPU、LCPU 和 PC Simulator 工程均可见。
LV_USE_IME_PINYIN 无直接 depends on,默认关闭,启用后会自动选择 LV_USE_KEYBOARD,无需手动设置键盘宏。若项目直接维护 lv_conf.h,则可通过以下定义打开该功能;menuconfig 配置与 lv_conf.h 只选一种方式维护,避免相互覆盖。
2.1 必选配置¶
#define LV_USE_IME_PINYIN 1
2.2 可选配置¶
以下选项都位于同一路径的 Others 子菜单中;打开 LV_USE_IME_PINYIN 后才会显示。LV_IME_PINYIN_USE_DEFAULT_DICT 默认开启,LV_IME_PINYIN_CAND_TEXT_NUM 默认值为 6;LV_IME_PINYIN_USE_K9_MODE 默认开启,LV_IME_PINYIN_K9_CAND_TEXT_NUM 默认值为 3,且依赖 LV_IME_PINYIN_USE_K9_MODE。这些配置没有 HCPU/LCPU 或 SoC 专用限制。
#define LV_IME_PINYIN_USE_DEFAULT_DICT 1
#define LV_IME_PINYIN_CAND_TEXT_NUM 6
#define LV_IME_PINYIN_USE_K9_MODE 1
#define LV_IME_PINYIN_K9_CAND_TEXT_NUM 3
说明:
配置项 |
说明 |
|---|---|
|
是否使用内置拼音词库。若设为 0,必须调用 |
|
26 键拼音模式下候选字面板一次显示的候选按钮数量,默认 6。小屏可适当减小。 |
|
是否启用 9 键输入模式。 |
|
9 键模式候选拼音数量,默认 3。 |
3. 主要接口¶
头文件:
#include "lv_ime_pinyin.h"
3.1 创建输入法对象¶
lv_obj_t * lv_ime_pinyin_create(lv_obj_t * parent);
创建拼音输入法对象。创建后对象本身默认隐藏,但会在内部创建候选字面板 cand_panel。
参数:
parent:输入法对象的父对象。通常传键盘和输入框所在的页面/弹窗容器。
返回值:
lv_obj_t *:拼音输入法对象句柄。
3.2 绑定键盘¶
void lv_ime_pinyin_set_keyboard(lv_obj_t * obj, lv_obj_t * kb);
把输入法对象绑定到一个 lv_keyboard。
调用后输入法会:
保存键盘对象。
把输入法对象和候选面板移动到键盘的父容器下。
移除键盘默认事件
lv_keyboard_def_event_cb。给键盘注册拼音输入法事件处理函数。
将候选面板对齐到键盘上方。
注意:绑定前应先创建 lv_keyboard,并建议先调用 lv_keyboard_set_textarea(kb, ta) 指定输入框。
3.3 设置词库¶
void lv_ime_pinyin_set_dict(lv_obj_t * obj, lv_pinyin_dict_t * dict);
设置拼音词库。
词库结构:
typedef struct {
const char * const py; /* 拼音,例如 "ni" */
const char * const py_mb; /* 候选汉字字符串,例如 "你尼呢" */
} lv_pinyin_dict_t;
自定义词库示例:
static lv_pinyin_dict_t user_dict[] = {
{ "ni", "你尼呢" },
{ "hao", "好号浩" },
{ "shi", "是时事市" },
{ NULL, NULL } /* 必须使用 NULL 作为结束项 */
};
lv_ime_pinyin_set_dict(ime, user_dict);
如果 LV_IME_PINYIN_USE_DEFAULT_DICT 为 1,创建输入法时会自动加载内置词库;客户只需要扩展或替换词库时才需要调用该接口。
3.4 设置输入模式¶
void lv_ime_pinyin_set_mode(lv_obj_t * obj, lv_ime_pinyin_mode_t mode);
输入模式枚举:
typedef enum {
LV_IME_PINYIN_MODE_ENGLISH, /* 英文模式 */
LV_IME_PINYIN_MODE_K26, /* 26 键拼音模式 */
LV_IME_PINYIN_MODE_K9, /* 9 键拼音模式 */
LV_IME_PINYIN_MODE_K9_NUMBER, /* 9 键数字模式 */
} lv_ime_pinyin_mode_t;
常用设置:
lv_ime_pinyin_set_mode(ime, LV_IME_PINYIN_MODE_ENGLISH); /* 默认英文 */
lv_ime_pinyin_set_mode(ime, LV_IME_PINYIN_MODE_K26); /* 默认中文 26 键 */
注意:LV_IME_PINYIN_MODE_K9 和 LV_IME_PINYIN_MODE_K9_NUMBER 需要打开 LV_IME_PINYIN_USE_K9_MODE。
3.5 获取绑定键盘¶
lv_obj_t * lv_ime_pinyin_get_kb(lv_obj_t * obj);
返回当前绑定的 lv_keyboard。
3.6 获取候选字面板¶
lv_obj_t * lv_ime_pinyin_get_cand_panel(lv_obj_t * obj);
返回候选字面板对象。可用于设置候选字面板的高度、字体、背景色、文字颜色等 UI 样式。
示例:
lv_obj_t *cand_panel = lv_ime_pinyin_get_cand_panel(ime);
lv_obj_set_height(cand_panel, 36);
lv_obj_set_style_bg_color(cand_panel, lv_color_hex(0xffffff), LV_PART_MAIN);
lv_obj_set_style_bg_opa(cand_panel, LV_OPA_COVER, LV_PART_MAIN);
lv_obj_set_style_text_color(cand_panel, lv_color_hex(0x111111), LV_PART_MAIN);
lv_obj_set_style_text_color(cand_panel, lv_color_hex(0x111111), LV_PART_ITEMS);
3.7 获取词库¶
const lv_pinyin_dict_t * lv_ime_pinyin_get_dict(lv_obj_t * obj);
返回当前输入法使用的词库指针。
4. 最小使用流程¶
下面是一个最小可用示例:
#if LV_USE_IME_PINYIN
static lv_obj_t *ta;
static lv_obj_t *kb;
static lv_obj_t *ime;
void demo_create_pinyin_input(lv_obj_t *parent)
{
/* 1. 创建文本输入框 */
ta = lv_textarea_create(parent);
lv_obj_set_size(ta, LV_PCT(100), 100);
lv_obj_align(ta, LV_ALIGN_TOP_MID, 0, 0);
lv_textarea_set_one_line(ta, false);
/* 2. 创建键盘 */
kb = lv_keyboard_create(parent);
lv_obj_set_size(kb, LV_PCT(100), 160);
lv_obj_align(kb, LV_ALIGN_BOTTOM_MID, 0, 0);
lv_keyboard_set_textarea(kb, ta);
/* 3. 创建拼音输入法并绑定键盘 */
ime = lv_ime_pinyin_create(parent);
lv_ime_pinyin_set_keyboard(ime, kb);
/* 4. 设置初始模式:英文或中文 26 键 */
lv_ime_pinyin_set_mode(ime, LV_IME_PINYIN_MODE_K26);
/* 5. 设置候选字面板样式 */
lv_obj_t *cand_panel = lv_ime_pinyin_get_cand_panel(ime);
lv_obj_set_height(cand_panel, 36);
lv_obj_set_style_bg_opa(cand_panel, LV_OPA_COVER, LV_PART_MAIN);
lv_obj_set_style_bg_color(cand_panel, lv_color_hex(0xffffff), LV_PART_MAIN);
lv_obj_set_style_text_color(cand_panel, lv_color_hex(0x111111), LV_PART_MAIN);
lv_obj_set_style_text_color(cand_panel, lv_color_hex(0x111111), LV_PART_ITEMS);
}
#endif
5. UI 设置建议¶
5.1 键盘位置¶
建议键盘固定在页面底部:
lv_obj_set_size(kb, LV_PCT(100), keyboard_h);
lv_obj_align(kb, LV_ALIGN_BOTTOM_MID, 0, 0);
lv_ime_pinyin_set_keyboard() 会把候选面板自动对齐到键盘上方:
lv_obj_align_to(cand_panel, kb, LV_ALIGN_OUT_TOP_MID, 0, 0);
因此页面布局时,需要在键盘上方给候选面板预留一定高度。推荐候选面板高度为 32~40 像素,小屏可取 30~36 像素。
5.2 输入框高度¶
输入框建议不要被候选面板和键盘遮挡。可以按屏幕高度动态计算:
lv_coord_t screen_h = lv_disp_get_ver_res(NULL);
lv_coord_t header_h = 44;
lv_coord_t keyboard_h = screen_h <= 360 ? 132 : 164;
lv_coord_t cand_h = 36;
lv_coord_t textarea_h = screen_h - header_h - keyboard_h - cand_h - 10;
if (textarea_h < 62)
textarea_h = 62;
5.3 字体设置¶
候选字面板需要能显示中文。若系统默认字体不包含中文,需要给输入框、键盘、候选面板设置中文字体。
本工程示例中使用 lv_ext_set_local_font():
lv_ext_set_local_font(kb, FONT_NORMAL, lv_color_hex(0x222222));
lv_ext_set_local_font(ta, FONT_SMALL, lv_color_hex(0x111111));
lv_obj_t *cand_panel = lv_ime_pinyin_get_cand_panel(ime);
lv_ext_set_local_font(cand_panel, FONT_SMALL, lv_color_hex(0x111111));
如果直接使用 LVGL 字体接口,也可以设置 LV_PART_MAIN 和 LV_PART_ITEMS:
const lv_font_t *font = lv_obj_get_style_text_font(ta, LV_PART_MAIN);
lv_obj_set_style_text_font(cand_panel, font, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_text_font(cand_panel, font, LV_PART_ITEMS | LV_STATE_DEFAULT);
5.4 候选面板样式¶
推荐将候选面板设置为不透明背景,避免和后面的输入框或页面内容混在一起:
lv_obj_set_style_bg_color(cand_panel, lv_color_hex(0xffffff), LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_bg_opa(cand_panel, LV_OPA_COVER, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_text_color(cand_panel, lv_color_hex(0x111111), LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_text_color(cand_panel, lv_color_hex(0x111111), LV_PART_ITEMS | LV_STATE_DEFAULT);
6. 按键行为说明¶
拼音输入法接管键盘 LV_EVENT_VALUE_CHANGED 事件后,会处理以下按键文本:
按键 |
行为 |
|---|---|
|
英文模式下切换到中文拼音 26 键;中文模式下切回英文。 |
|
切换到英文大写,或从 9 键数字模式回到 9 键拼音。 |
|
从英文大写/符号等模式切换到小写或 26 键小写布局。 |
|
26 键拼音模式下切换到数字/符号布局。 |
|
在 26 键拼音和 9 键拼音之间切换。 |
|
9 键拼音模式下切换到 9 键数字模式。 |
|
删除拼音输入缓存;缓存为空时删除文本框中的字符。 |
|
输入空格,并清空拼音缓存。 |
|
插入换行;若文本框是单行模式则发送 |
|
清空拼音缓存,隐藏候选面板,并向键盘和文本框发送 |
|
普通模式下移动光标;9 键模式下翻页候选拼音。 |
候选字面板中:
第一个按钮
<:上一页候选字。最后一个翻页按钮
>:下一页候选字。中间按钮:候选汉字,点击后写入
lv_textarea。
7. 自定义词库¶
如果内置词库不满足客户输入需求,可以使用自定义词库。
7.1 定义词库¶
static lv_pinyin_dict_t custom_dict[] = {
{ "a", "啊阿" },
{ "ai", "爱矮挨" },
{ "an", "安按暗" },
{ "yuan", "元原远圆" },
{ "zhong", "中种重钟" },
{ NULL, NULL }
};
7.2 设置词库¶
ime = lv_ime_pinyin_create(parent);
lv_ime_pinyin_set_keyboard(ime, kb);
lv_ime_pinyin_set_dict(ime, custom_dict);
lv_ime_pinyin_set_mode(ime, LV_IME_PINYIN_MODE_K26);
注意事项:
拼音字符串建议使用小写字母。
词库数组必须以
{ NULL, NULL }结束,源码通过dict[i].py == NULL或dict[i].py_mb == NULL判断结束。词库需要按拼音首字母分组排列,例如
a...、b...、c...,不要把yuan放在zhong后面再接其它y开头词条,否则按首字母索引查找时可能漏查。候选汉字字符串需要使用 UTF-8 编码。当前实现按每个中文字符 3 字节计算候选数量,候选串中不要混入 ASCII 字符或 4 字节 Unicode 字符。
若
LV_IME_PINYIN_USE_DEFAULT_DICT为 0,必须先设置词库,否则无法正常出候选字。词库越大,占用 Flash/RAM 越多;小资源设备建议只保留业务所需词条。
8. 工程调用示例:pcalendar 编辑页面¶
当前工程 pcalendar 中已经有一套完整使用方式,可作为客户集成参考:
solution/examples/_dynamic_app/c/app/pcalendar/src/perpetual_calendar_gui.c
核心代码流程如下:
#if LV_USE_IME_PINYIN
g_editor.ime_mode = LV_IME_PINYIN_MODE_ENGLISH;
#endif
/* 创建键盘 */
g_editor.keyboard = lv_keyboard_create(box);
lv_obj_set_size(g_editor.keyboard, LV_PCT(100), keyboard_h);
lv_obj_align(g_editor.keyboard, LV_ALIGN_BOTTOM_MID, 0, 0);
lv_keyboard_set_mode(g_editor.keyboard, LV_KEYBOARD_MODE_TEXT_LOWER);
lv_ext_set_local_font(g_editor.keyboard, FONT_NORMAL, lv_color_hex(0x222222));
/* 创建输入框 */
g_editor.textarea = lv_textarea_create(box);
lv_obj_set_size(g_editor.textarea, LV_PCT(100), textarea_h);
lv_obj_align(g_editor.textarea, LV_ALIGN_TOP_MID, 0, header_h);
lv_textarea_set_one_line(g_editor.textarea, false);
lv_textarea_set_text(g_editor.textarea, text ? text : "");
lv_obj_set_style_bg_color(g_editor.textarea, lv_color_hex(0xffffff), LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_text_color(g_editor.textarea, lv_color_hex(0x111111), LV_PART_MAIN | LV_STATE_DEFAULT);
lv_ext_set_local_font(g_editor.textarea, FONT_SMALL, lv_color_hex(0x111111));
lv_obj_add_state(g_editor.textarea, LV_STATE_FOCUSED);
lv_keyboard_set_textarea(g_editor.keyboard, g_editor.textarea);
#if LV_USE_IME_PINYIN
/* 创建并绑定拼音输入法 */
g_editor.ime = lv_ime_pinyin_create(box);
lv_ime_pinyin_set_keyboard(g_editor.ime, g_editor.keyboard);
lv_obj_set_style_text_font(g_editor.ime, lv_obj_get_style_text_font(g_editor.textarea, LV_PART_MAIN), LV_PART_MAIN);
/* 候选面板 UI */
{
const lv_font_t *editor_font = lv_obj_get_style_text_font(g_editor.textarea, LV_PART_MAIN);
lv_obj_t *cand_panel = lv_ime_pinyin_get_cand_panel(g_editor.ime);
lv_obj_set_height(cand_panel, 36);
lv_ext_set_local_font(cand_panel, FONT_SMALL, lv_color_hex(0x111111));
lv_obj_set_style_text_font(cand_panel, editor_font, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_text_font(cand_panel, editor_font, LV_PART_ITEMS | LV_STATE_DEFAULT);
lv_obj_set_style_bg_color(cand_panel, lv_color_hex(0xffffff), LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_bg_opa(cand_panel, LV_OPA_COVER, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_text_color(cand_panel, lv_color_hex(0x111111), LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_text_color(cand_panel, lv_color_hex(0x111111), LV_PART_ITEMS | LV_STATE_DEFAULT);
}
/* 应用当前输入模式,pcalendar 中初始为 LV_IME_PINYIN_MODE_ENGLISH */
pcalendar_editor_apply_ime_mode();
#endif
上面的顺序与 pcalendar_open_editor() 当前实现保持一致:
创建编辑页父容器
box。创建底部键盘
g_editor.keyboard,设置大小、位置、键盘模式和字体。创建输入框
g_editor.textarea,设置大小、位置、初始文本、背景色、文字颜色和字体。调用
lv_keyboard_set_textarea(g_editor.keyboard, g_editor.textarea)将键盘输入目标绑定到输入框。在
#if LV_USE_IME_PINYIN下创建g_editor.ime,调用lv_ime_pinyin_set_keyboard()接管键盘事件。通过
lv_ime_pinyin_get_cand_panel()获取候选字面板,并设置 36 px 高度、中文字体、白色不透明背景和深色文字。调用
pcalendar_editor_apply_ime_mode(),内部实际执行lv_ime_pinyin_set_mode(g_editor.ime, (lv_ime_pinyin_mode_t)g_editor.ime_mode)。
9. 生命周期和资源释放¶
通常只需要删除父容器,LVGL 会递归删除输入框、键盘、输入法对象和候选面板。
如果需要单独关闭编辑页面,可以参考:
static void editor_close(void)
{
if (editor_box)
lv_obj_del(editor_box);
editor_box = NULL;
ime = NULL;
kb = NULL;
ta = NULL;
}
lv_ime_pinyin 析构时会尝试删除绑定的键盘和候选面板,因此建议把输入框、键盘、输入法放在同一个编辑页面容器下,由页面统一删除,避免悬空指针。
10. 常见问题¶
10.1 没有候选字¶
检查:
LV_USE_IME_PINYIN是否为 1。是否调用了
lv_ime_pinyin_set_keyboard(ime, kb)。是否调用了
lv_keyboard_set_textarea(kb, ta)。是否有词库:
LV_IME_PINYIN_USE_DEFAULT_DICT = 1,或已调用
lv_ime_pinyin_set_dict()设置自定义词库。
当前是否处于中文模式:
LV_IME_PINYIN_MODE_K26或LV_IME_PINYIN_MODE_K9。
10.2 候选字显示为方框或乱码¶
原因通常是字体不包含中文字形或编码不对。
处理:
确认词库字符串为 UTF-8。
给
textarea、keyboard、cand_panel设置包含中文的字体。尤其要设置候选面板
LV_PART_ITEMS的字体。
10.3 候选面板位置不对¶
lv_ime_pinyin_set_keyboard() 会将候选面板对齐到键盘上方。如果后续移动或改变键盘大小,建议重新调整候选面板:
lv_obj_t *cand_panel = lv_ime_pinyin_get_cand_panel(ime);
lv_obj_align_to(cand_panel, kb, LV_ALIGN_OUT_TOP_MID, 0, 0);
10.4 OK/Enter 后如何保存输入内容¶
OK 会向键盘和文本框发送 LV_EVENT_READY。可以给 textarea 或 keyboard 添加事件回调,在 LV_EVENT_READY 中读取文本:
static void textarea_ready_cb(lv_event_t *e)
{
lv_obj_t *ta = lv_event_get_target(e);
const char *txt = lv_textarea_get_text(ta);
/* 保存 txt */
}
lv_obj_add_event_cb(ta, textarea_ready_cb, LV_EVENT_READY, NULL);
11. 推荐集成步骤¶
按
menuconfig (Top) → SiFli SDK configuration → Third party packages → LittlevGL2RTT: The LittlevGl gui lib adapter RT-Thread (PKG_USING_LITTLEVGL2RTT) → LVGL configuration → select LVGL Version. → LVGL V8 → LVGL V8 configuration → Others → Enable Pinyin input method (LV_USE_IME_PINYIN)启用拼音输入法;LV_USE_IME_PINYIN默认关闭,启用后会自动选择LV_USE_KEYBOARD。按页面布局创建
lv_textarea。创建
lv_keyboard,并调用lv_keyboard_set_textarea(kb, ta)。创建
lv_ime_pinyin,调用lv_ime_pinyin_set_keyboard(ime, kb)。根据产品需求设置初始模式:英文或中文 26 键。
设置候选面板中文字体、背景色、高度。
如需业务词库,调用
lv_ime_pinyin_set_dict()。在
LV_EVENT_READY或保存按钮事件中读取lv_textarea_get_text(ta)。