|
|
本帖最后由 hongda 于 2025-5-12 08:40 编辑
以下是代码的流程解释,按照模块和交互顺序组织:
一、应用注册与初始化流程
注册入口 (Register.cpp)
通过REGIST_NATIVE宏将应用信息注册到系统,包含:
应用ID(NativeRegisterType::GUI_DEMO2)
图标资源
应用名称("gui_demo2")
系统启动时会调用InitSlice()初始化应用界面
界面初始化
建SliceProxy代理对象,关联gui_demo2View和gui_demo2Presenter
将Slice添加到NativeAbility管理系统中,用于页面切换
二、界面构建流程
View层初始化 ( View.cpp)
OnStart()方法:
设置根容器可拖动、可触摸
绑定Presenter为拖拽监听器
调用ui.setupUi()创建按钮和列表控件
将控件添加到根容器
UI布局构建 ( ui_gui_demo2View.h)
setupUi()方法:
创建按钮(button1_)和列表(list1_)
设置控件位置、尺寸、ID和样式
列表绑定数据适配器(IconAdapter)
按钮注册点击监听器到Presenter
三、事件处理流程
用户交互触发
用户操作(点击/拖动等)被控件捕获
例如按钮点击触发OnClick,拖动触发OnDragStart等
Presenter处理事件 (文档3 Presenter.cpp)
通用返回逻辑:在所有拖拽事件中检测从左到右滑动:
cpp
if ((event.GetDragDirection() == LEFT_TO_RIGHT) &&
(event.GetDeltaX() > X_DRAG_OFFSET)) {
NativeAbility::GetInstance().ChangeSlice(preSlice); // 返回上一页面
}
具体控件处理(需开发者扩展):
cpp
if (strcmp(view.GetViewId(), "button_test1") == 0) {
// 处理按钮点击
}
数据交互 (Model)
当前Model为空实现,预留了单例接口GetInstance()
开发者可在此添加数据存取逻辑,供Presenter调用
四、动画系统
动画实现 (文档6 Presenter.h)
IcosahedronViewgui_demo2AnimatorCallback类:
使用线性插值计算多面体边长变化
实现270度旋转动画
通过Animator驱动动画更新
五、模块关系图
NativeAbility<----->View(gui_demo2View)
SliceProxy(注册管理)
Presenter(事件处理中心)
Model(数据存储层)
六、关键设计特点
MVP架构:
View只负责UI构建
Presenter处理所有业务逻辑
Model提供数据接口(待实现)
标准化事件处理:
统一通过View ID识别控件
预留了13种事件处理模板(点击、长按、拖拽等)
模块化注册机制:
通过NativeRegister实现应用解耦
方便系统统一管理多个应用
动画扩展机制:
提供AnimatorCallback模板
支持自定义插值算法实现复杂动效
建议开发时:
在Presenter中补充具体控件的业务逻辑
在Model层添加数据管理逻辑
使用提供的动画模板实现定制化动效
通过修改注册信息配置应用图标和名称
示例:
根据代码结构,需要分三步修改实现将按钮添加到列表:
一、修改UI列表数据模型 (在ui_gui_demo2View.h)
cpp
复制
// 原始代码
List<IconItemNode*>* list1data_ = nullptr;
IconAdapter* list1adapter_ = nullptr;
// 修改为(新增按钮数据结构):struct ButtonItemNode {
const char* btnText;
const char* btnId;
};
List<ButtonItemNode*>* list1data_ = nullptr;
// 创建新的按钮适配器class ButtonAdapter : public BaseAdapter {public:
explicit ButtonAdapter(gui_demo2Presenter* presenter) : presenter_(presenter) {}
UIView* GetView(UIView* inView, int16_t index) override {
UIButton* button = new UIButton();
button->SetPosition(0, 0); // 列表项内部位置
button->Resize(180, 40); // 按钮尺寸
button->SetText(listData_[index]->btnText);
button->SetViewId(listData_[index]->btnId);
button->SetOnClickListener(presenter_); // 绑定点击事件
return button;
}
//... 其他必要方法private:
gui_demo2Presenter* presenter_;
List<ButtonItemNode*>* listData_;
};
ButtonAdapter* list1adapter_ = nullptr;
二、调整setupUi初始化逻辑
cpp
复制
void setupUi() {
// 创建适配器时传入presenter
list1adapter_ = new ButtonAdapter(gui_demo2presenter_);
// 添加测试按钮数据
ButtonItemNode* item1 = new ButtonItemNode{"按钮1", "list_btn_1"};
ButtonItemNode* item2 = new ButtonItemNode{"按钮2", "list_btn_2"};
list1data_->PushBack(item1);
list1data_->PushBack(item2);
list1adapter_->SetData(list1data_);
list1_->SetAdapter(list1adapter_);
// 调整列表尺寸适应内容
list1_->SetRowHeight(45); // 每行高度
list1_->SetYScrollBarVisible(true); // 启用滚动条
}
三、在Presenter处理按钮点击
cpp
复制
bool gui_demo2Presenter::OnClick(UIView &view, const ClickEvent &event) {
if (view.GetViewId() != nullptr) {
// 处理列表按钮点击
if (strcmp(view.GetViewId(), "list_btn_1") == 0) {
WEARABLE_LOGD("列表按钮1被点击");
// 添加业务逻辑...
} else if (strcmp(view.GetViewId(), "list_btn_2") == 0) {
WEARABLE_LOGD("列表按钮2被点击");
// 添加业务逻辑...
}
}
return true;
}
关键修改点说明:
1.数据层改造:
用ButtonItemNode替代IconItemNode,存储按钮文本和ID
每个列表项对应一个独立的按钮数据
1.视图层适配:
ButtonAdapter继承自BaseAdapter
在GetView中动态创建按钮控件
绑定presenter作为事件监听器
1.事件处理扩展:
通过GetViewId()识别具体按钮
支持在同一个列表中混合多种按钮类型
可根据btnId实现差异化逻辑
效果示意图:
markdown
复制
+---------------------+
| [ 按钮1 ] | ← 列表项1
+---------------------+
| [ 按钮2 ] | ← 列表项2
+---------------------+
| ... |
+---------------------+
|
|