十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Flipper Zero Date/Time Input 视图开发指南:从示例应用到源码级 API 解析

Flipper Zero Date/Time Input 视图开发指南:从示例应用到源码级 API 解析 Flipper Zero Date/Time Input 视图开发指南从示例应用到源码级 API 解析【免费下载链接】flipperzero-firmwareFlipper Zero firmware source code项目地址: https://gitcode.com/GitHub_Trending/fl/flipperzero-firmware导读本指南以 Flipper Zero 固件仓库中的官方示例应用example_date_time_input为主体系统讲解 GUI 模块date_time_input日期/时间输入视图的完整用法如何配置可编辑字段、注册值变更与编辑完成两类回调、如何与 Scene Manager 场景框架集成并结合模块源码剖析其底层实现原理。读完本文你将能够独立在自己的 Flipper Zero 应用中实现编辑日期/时间并回写结果的完整交互流程。一、示例应用概览example_date_time_input是一个位于 applications/examples/example_date_time_input 目录下的官方示例应用。它的核心作用正如其 ReadMe.md 所述Simple view that allows the user to adjust a date and/or time.即一个允许用户调整日期和/或时间的简单视图。该应用通过 application.fam 声明为外部应用FAPApp( appidexample_date_time_input, nameExample: Date/Time Input, apptypeFlipperAppType.EXTERNAL, entry_pointexample_date_time_input, requires[gui], stack_size1 * 1024, fap_categoryExamples, )关键配置含义apptypeFlipperAppType.EXTERNAL以外部应用.fap文件形式构建可放入 SD 卡运行requires[gui]声明对 GUI 服务的依赖视图模块依赖gui记录RECORD_GUIstack_size1 * 1024为应用线程分配 1 KB 栈空间fap_categoryExamples在应用菜单中归类到 Examples 分组。二、General Principle回调驱动 单一数据源原文档给出了该示例最核心的设计原则General principleCallbacks can be defined for every time a value is edited (useful for application-specific bounds checking or validation) and for when the user is done editing (back button is pressed). The provided DateTime object is used both as the initial value and as the place where the result is stored.可以拆解为三点值变更回调changed callback用户每次调整任意字段年/月/日/时/分/秒时触发适合做应用自定义的边界检查或合法性校验编辑完成回调done callback用户按下返回键back button、结束编辑时触发单一数据源DateTime 对象调用方传入的DateTime结构体指针既作为视图的初始值也作为结果的存储位置——视图直接在该对象上修改编辑完成后调用方读取同一对象即可获得最终结果无需额外的返回值通道。该原则在源码中同样成立date_time_input_set_result_callback()把传入的DateTime*直接存入视图模型model之后的输入处理全部作用于这份数据。三、示例应用的完整源码结构3.1 文件组织示例应用采用典型的 Flipper Zero 场景Scene架构组织applications/examples/example_date_time_input/ ├── ReadMe.md # 官方说明文档本文主体 ├── application.fam # 应用清单构建声明 ├── example_date_time_input.c # 应用入口分配/释放、ViewDispatcher 装配 ├── example_date_time_input.h # 应用结构体与视图 ID 定义 └── scenes/ ├── example_date_time_input_scene.c # 场景处理器注册表 ├── example_date_time_input_scene.h # 场景枚举与处理器声明 ├── example_date_time_input_scene_config.h # 场景列表X-Macro 源 ├── example_date_time_input_scene_input_date_time.c # 日期/时间编辑场景 └── example_date_time_input_scene_show_date_time.c # 结果显示与入口场景3.2 应用入口与视图装配在 example_date_time_input.c 中应用按标准流程完成初始化static ExampleDateTimeInput* example_date_time_input_alloc() { ExampleDateTimeInput* app malloc(sizeof(ExampleDateTimeInput)); app-gui furi_record_open(RECORD_GUI); app-view_dispatcher view_dispatcher_alloc(); app-scene_manager scene_manager_alloc(example_date_time_input_scene_handlers, app); // 自定义事件与返回事件都转交给场景管理器 view_dispatcher_set_custom_event_callback( app-view_dispatcher, example_date_time_input_custom_event_callback); view_dispatcher_set_navigation_event_callback( app-view_dispatcher, example_date_time_input_back_event_callback); // 注册两个视图Date/Time Input 与 DialogEx app-date_time_input date_time_input_alloc(); view_dispatcher_add_view( app-view_dispatcher, ExampleDateTimeInputViewIdDateTimeInput, date_time_input_get_view(app-date_time_input)); app-dialog_ex dialog_ex_alloc(); view_dispatcher_add_view( app-view_dispatcher, ExampleDateTimeInputViewIdShowDateTime, dialog_ex_get_view(app-dialog_ex)); // 用当前真实时间填充初始值 furi_hal_rtc_get_datetime(app-date_time); app-edit_date false; app-edit_time false; return app; }值得注意的细节furi_hal_rtc_get_datetime(app-date_time)直接读取 RTC 实时时钟把当前日期时间作为初始值填入DateTime对象这正是initial value的典型来源app-edit_date/app-edit_time两个布尔标志控制后续进入编辑场景时可编辑的字段组合entry_point函数 example_date_time_input 以ViewDispatcherTypeFullscreen全屏模式挂载到 GUI并首先进入ExampleDateTimeInputSceneShowDateTime场景。3.3 场景流转显示 → 选择 → 编辑 → 回写场景列表定义在 example_date_time_input_scene_config.hADD_SCENE(example_date_time_input, input_date_time, InputDateTime) ADD_SCENE(example_date_time_input, show_date_time, ShowDateTime)该文件与场景实现配合构成完整的交互闭环ShowDateTime 场景example_date_time_input_scene_show_date_time.c使用DialogEx展示当前日期时间并显示三个按钮左键Date→edit_date true; edit_time false;右键Time→edit_date false; edit_time true;中键Both→edit_date true; edit_time true;InputDateTime 场景example_date_time_input_scene_input_date_time.c在on_enter中完成两件关键事情调用date_time_input_set_result_callback()注册完成回调此例未注册变更回调传入NULL仅做演示根据edit_date/edit_time调用date_time_input_set_editable_fields()决定哪些字段可编辑之后view_dispatcher_switch_to_view()切换到日期/时间输入视图。编辑场景的on_event中当收到SceneManagerEventTypeCustom事件由完成回调view_dispatcher_send_custom_event(app-view_dispatcher, 0)触发即Back button pressed时调用scene_manager_previous_scene()返回显示场景——此时app-date_time已被视图就地更新重新进入显示场景即可看到最新结果。编辑后返回显示场景展示的日期时间即为用户修改后的值这直观验证了DateTime 对象同时承担初始值与结果存储的设计。四、date_time_input 模块 API 详解日期/时间输入视图是 GUI 服务的内置模块头文件与实现位于 applications/services/gui/modules/date_time_input.h 与 date_time_input.c。以下 API 均来自模块公开接口。4.1 生命周期alloc / free / get_viewDateTimeInput* date_time_input_alloc(void); void date_time_input_free(DateTimeInput* date_time_input); View* date_time_input_get_view(DateTimeInput* date_time_input);date_time_input_alloc()内部通过view_alloc()创建视图并以ViewModelTypeLocking类型分配模型model内存同时挂载绘制回调与输入回调见 date_time_input.cget_view()返回内部View实例供view_dispatcher_add_view()注册到 ViewDispatcher 使用模块默认将所有字段year/month/day/hour/minute/second的editable标志置为true见 date_time_input.c。4.2 结果回调date_time_input_set_result_callbackvoid date_time_input_set_result_callback( DateTimeInput* date_time_input, DateTimeChangedCallback changed_callback, // 值变更回调可传 NULL DateTimeDoneCallback done_callback, // 编辑完成回调返回键触发 void* callback_context, DateTime* current_datetime); // 初始值 结果存储位置该函数将两类回调、回调上下文以及DateTime指针一并存入视图模型见 date_time_input.c。调用时机从实现源码可以确认changed_callback在用户修改字段值时被调用date_time_input.c 中未使用但模块内部在每次值变更处触发见 date_time_input.c适合执行边界检查/合法性校验并可配合DateTimeChangedCallback返回的DateTime做实时校正done_callback在用户按下返回键结束编辑时被调用见 date_time_input.c。4.3 可编辑字段date_time_input_set_editable_fields这是原文档重点讲解的配置接口void date_time_input_set_editable_fields( DateTimeInput* date_time_input, bool year, bool month, bool day, bool hour, bool minute, bool second);参数依次对应六个时间字段的是否允许编辑。原文档对禁用字段的 UI 行为有明确规定Disabled fields are shown but arent able to be selected and dont have an outer box. If all fields are disabled, the view is read-only and no cursor will be shown.即禁用字段仍然显示但不可被选中且不绘制外框无选中光标框若全部字段均被禁用视图进入只读状态不显示任何光标。源码层面date_time_input_set_editable_fields()在更新六个editable标志后会把行列选择器重置到第一个可编辑字段见 date_time_input.c确保进入视图时光标一定落在合法字段上——如果没有任何可编辑字段则保持无光标只读状态。示例应用通过该 API 实现了三种编辑模式完整展示了参数组合的用法// 仅编辑日期年/月/日可编辑时/分/秒不可编辑 date_time_input_set_editable_fields( date_time_input, true, /* year */ true, /* month */ true, /* day */ false, /* hour */ false, /* minute*/ false); /* second*/ // 仅编辑时间时/分/秒可编辑 date_time_input_set_editable_fields( date_time_input, false, false, false, true, true, true); // 日期时间均可编辑 date_time_input_set_editable_fields( date_time_input, true, true, true, true, true, true);五、结合源码的底层行为解析5.1 单一数据源在模型中的落地date_time_input_set_result_callback()把model-datetime current_datetime直接指向调用方传入的DateTime对象。这意味着用户在视图上的每一次调整都会就地修改该对象回调触发时调用方读取到的就是最新值编辑完成后甚至无需显式获取结果——原对象即结果。这是理解整个模块数据流的关键。5.2 时区与 12/24 小时制的联动示例的显示场景还演示了一个实用细节通过furi_hal_rtc_get_locale_timeformat()判断系统是否处于 12 小时制FuriHalRtcLocaleTimeFormat12h并据此在展示字符串中附加AM/PM后缀、将小时数转换为 12 小时制表示见 example_date_time_input_scene_show_date_time.c。这说明DateTime结构体的hour字段始终以 24 小时制存储展示层需要结合 locale 自行格式化。5.3 与 Flipper Zero 标准视图框架的集成方式从本示例可以总结出date_time_input与标准框架集成的固定套路date_time_input_alloc()创建模块实例date_time_input_get_view()view_dispatcher_add_view()注册到 ViewDispatcher场景on_enter中调用set_result_callback()与set_editable_fields()完成配置view_dispatcher_switch_to_view()切入视图完成回调中通过view_dispatcher_send_custom_event()抛出事件场景on_event接收后scene_manager_previous_scene()返回上一场景on_exit/free时用view_dispatcher_remove_view()date_time_input_free()释放资源。六、将本示例移植到自己应用的要点初始化数据使用furi_hal_rtc_get_datetime()读取 RTC 作为默认值或按业务需要自行构造DateTime校验时机若需限制取值范围例如日期不得早于今天注册changed_callback在每次值变更时校验并纠正字段裁剪利用set_editable_fields()实现只改日期、只改时间或全部可改等业务形态全禁用时得到只读展示视图结果读取编辑完成后直接读取传入的DateTime*即可无需额外查询接口构建运行该示例为 EXTERNAL 应用可参照 AppManifests.md 通过 fbt 构建为.fap后放入 SD 卡运行或借助 ufbt 独立编译调试。七、总结date_time_input是 Flipper Zero GUI 框架中实现日期/时间选择这一高频需求的官方视图模块。通过example_date_time_input示例开发者可以掌握其完整用法以DateTime对象为单一数据源、以 changed/done 双回调承接业务逻辑、以set_editable_fields()灵活裁剪可编辑字段。本文结合 date_time_input.c 与 date_time_input.h 的源码印证了文档所述禁用字段无外框、全禁用时只读无光标等行为的具体实现为在自有应用中安全、正确地使用该模块提供了可复用的实现参考。【免费下载链接】flipperzero-firmwareFlipper Zero firmware source code项目地址: https://gitcode.com/GitHub_Trending/fl/flipperzero-firmware创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表