OpenHarmony ArkUI 焦点系统知识库
本文档为 Claude Code (claude.ai/code) 提供指导,用于处理 OpenHarmony ArkUI 的焦点系统代码。
概述
ArkUI 焦点系统是 OpenHarmony UI 框架中负责管理用户界面焦点交互的核心子系统,处理键盘、遥控器、触摸等多种输入方式的焦点导航和事件分发。
核心职责:
- 焦点链管理和维护
- 焦点导航(方向键、Tab键、数字键盘等)
- 焦点事件处理和分发
- 焦点样式渲染
- 辅助功能支持
关键特性:
- 支持树形焦点链结构
- 支持焦点组和焦点作用域
- 可定制的焦点样式
- 焦点优先级控制
- 无障碍访问支持
代码位置
核心代码
arkui_ace_engine/frameworks/core/components_ng/
├── event/ # 焦点事件层
│ ├── focus_hub.h/cpp # 焦点枢纽(核心)
│ ├── focus_event_handler.h/cpp # 焦点事件处理器
│ ├── focus_box.h/cpp # 焦点框样式
│ ├── focus_state.h # 焦点状态定义
│ └── focus_type.h # 焦点类型定义
├── manager/focus/ # 焦点管理层
│ ├── focus_manager.h/cpp # 焦点管理器
│ └── focus_view.h/cpp # 焦点视图
└── render/adapter/ # 焦点渲染层
├── focus_modifier.h/cpp # 焦点渲染修饰器
├── focus_state_modifier.h/cpp
└── focus_animation_modifier.h/cpp
辅助功能支持
arkui_ace_engine/adapter/ohos/osal/accessibility/focus_move/
├── accessibility_focus_strategy.cpp/h # 焦点移动策略
├── accessibility_focus_move_osal.cpp/h # 焦点移动 OSAL
├── accessibility_focus_frame_node_utils.cpp/h # FrameNode 工具
└── accessibility_third_node_utils.cpp/h # 第三方节点工具
桥接层
arkui_ace_engine/frameworks/bridge/declarative_frontend/engine/functions/
└── js_focus_function.cpp/h # JS 焦点函数接口
架构设计
三层架构
应用层 (ArkTS/JS)
- focusOnTouch, defaultFocus, tabIndex
- onFocus, onBlur, onKey
↓
桥接层 (Bridge)
- JSFocusFunction
- ArkTS Native Interface
↓
焦点管理层 (Manager)
- FocusManager: 全局焦点管理
- FocusView: 视图容器管理
↓
焦点事件层 (Event/Hub)
- FocusHub: 核心枢纽
- FocusEventHandler: 事件处理
↓
焦点渲染层 (Render)
- FocusModifier: 绘制焦点框
- FocusAnimationModifier: 焦点动画
核心类关系
FocusManager
(全局管理器)
│
│ 管理
FocusView
(视图容器)
│
│ 包含
FocusHub
(焦点枢纽)
┌───────────────┼───────────────┐
│ │ │
FocusBox FocusPattern FocusEventHandler
(焦点框样式) (焦点模式) (事件处理)
核心类详解
1. FocusManager (焦点管理器)
文件: frameworks/core/components_ng/manager/focus/focus_manager.h
职责:
- 全局焦点状态管理
- FocusView 栈管理
- 焦点切换协调
关键方法:
class FocusManager {
// FocusView 栈管理
void FocusViewShow(const RefPtr<FocusView>& focusView, bool isTriggerByStep = false);
void FocusViewHide(const RefPtr<FocusView>& focusView);
void FocusViewClose(const RefPtr<FocusView>& focusView, bool isDetachFromTree = false);
// 焦点请求
bool RequestFocus(const RefPtr<FocusHub>& focusHub, FocusReason reason);
// 焦点变更回调
void AddFocusChangeCallback(const FocusChangeCallback& callback);
private:
FocusViewMap focusViewMap_; // FocusView 映射表
WeakPtr<FocusView> lastFocusView_; // 上一个聚焦的视图
};
关键枚举:
enum class FocusActiveReason : int32_t {
POINTER_EVENT = 0, // 指针事件
DEFAULT = 1, // 默认焦点
USE_API = 2, // API 调用
KEY_TAB = 3, // Tab 键
ACTIVE_MARK = 4, // 激活标记
JOYSTICK_DPAD = 5, // 摇杆/方向键
};
enum class FocusViewStackState : int32_t {
IDLE = 0, // 空闲
SHOW = 1, // 显示
CLOSE = 2, // 关闭
};
2. FocusView (焦点视图)
文件: frameworks/core/components_ng/manager/focus/focus_view.h
职责:
- 表示可聚焦的视图容器(Window、Dialog、Overlay)
- 管理视图内的焦点子树
- 处理视图级别的焦点显示/隐藏
关键方法:
class FocusView {
// 视图生命周期
void FocusViewShow(bool isTriggerByStep = false);
void FocusViewHide();
void FocusViewClose(bool isDetachFromTree = false);
// 默认焦点处理
bool RequestDefaultFocus();
bool TriggerFocusMove();
// 焦点状态查询
RefPtr<FocusHub> GetFocusHub();
RefPtr<FocusHub> GetViewRootScope();
bool IsRootScopeCurrentFocus();
private:
bool isViewRootScopeFocused_ = true; // 视图根作用域是否聚焦
bool isViewHasFocused_ = false; // 视图是否曾经聚焦
bool isViewHasShow_ = false; // 视图是否已显示
WeakPtr<FocusHub> rootScopeSpecified_; // 指定的根作用域
};
3. FocusHub (焦点枢纽)
文件: frameworks/core/components_ng/event/focus_hub.h
职责:
- 焦点系统的核心枢纽
- 管理单个节点的焦点状态
- 协调子节点的焦点管理
- 处理焦点事件和回调
核心数据结构:
class FocusHub : public FocusState, public FocusEventHandler {
public:
// 焦点属性设置
void SetFocusable(bool focusable);
void SetFocusType(FocusType focusType);
void SetFocusPattern(const FocusPattern& pattern);
// 焦点状态查询
bool IsFocusable() const;
bool IsFocused() const;
bool IsCurrentFocus() const;
// 焦点请求
bool RequestFocusImmediately(FocusReason reason);
bool RequestFocus(FocusReason reason);
// 子节点管理
void AddChild(const RefPtr<FocusHub>& child);
void RemoveChild(const RefPtr<FocusHub>& child);
// 焦点样式
void SetFocusBox(const FocusBox& focusBox);
std::optional<FocusBox> GetFocusBox() const;
private:
// 焦点链
std::list<WeakPtr<FocusHub>> children_;
WeakPtr<FocusHub> parent_;
// 焦点属性
FocusPattern focusPattern_;
std::optional<FocusBox> focusBox_;
// 焦点状态
bool isFocused_ = false;
bool isCurrentFocus_ = false;
};
关键枚举:
enum class RequestFocusResult : int32_t {
DEFAULT = 0,
NON_FOCUSABLE = 1, // 不可聚焦
NON_FOCUSABLE_ANCESTOR = 2, // 祖先节点不可聚焦
NON_EXIST = 3, // 节点不存在
NON_FOCUSABLE_BY_TAB = 4, // Tab 键不可聚焦
};
enum class SwitchingStartReason : int32_t {
DEFAULT = 0,
WINDOW_FOCUS = 1,
REQUEST_FOCUS = 2,
LOST_FOCUS_TO_VIEW_ROOT = 3,
REMOVE_SELF = 4,
REMOVE_CHILD = 5,
LOST_FOCUS_TO_TABSTOP = 6,
};
enum class FocusDependence : int32_t {
CHILD = 0, // 子节点聚焦
SELF = 1, // 自身聚焦
AUTO = 2, // 自动选择
};
enum class FocusPriority : int32_t {
AUTO = 0,
PRIOR = 2000,
PREVIOUS = 3000,
};
4. FocusPattern (焦点模式)
文件: frameworks/core/components_ng/event/focus_hub.h
职责:
- 定义节点的焦点行为模式
- 控制焦点样式类型
- 配置焦点绘制参数
class FocusPattern {
public:
FocusPattern(FocusType focusType, bool focusable);
FocusPattern(FocusType focusType, bool focusable, FocusStyleType styleType);
FocusType GetFocusType() const;
bool GetFocusable() const;
FocusStyleType GetStyleType() const;
FocusPaintParam* GetFocusPaintParams() const;
private:
FocusType focusType_; // 焦点类型
bool focusable_; // 是否可聚焦
FocusStyleType styleType_; // 样式类型
std::unique_ptr<FocusPaintParam> paintParams_; // 绘制参数
};
5. FocusBox (焦点框)
文件: frameworks/core/components_ng/event/focus_box.h
职责:
- 定义焦点框的视觉样式
- 支持资源动态更新
struct FocusBoxStyle {
std::optional<Color> strokeColor; // 边框颜色
std::optional<CalcDimension> strokeWidth; // 边框宽度
std::optional<CalcDimension> margin; // 外边距
};
class FocusBox {
public:
void SetStyle(const FocusBoxStyle& style);
std::optional<FocusBoxStyle> GetStyle() const;
bool HasCustomStyle() const;
};
6. FocusEventHandler (焦点事件处理器)
文件: frameworks/core/components_ng/event/focus_event_handler.h
职责:
- 处理键盘和方向键事件
- 处理焦点导航逻辑
- 分发焦点相关回调
class FocusEventHandler : public FocusState {
public:
// 焦点事件回调设置
void SetOnFocusCallback(OnFocusFunc callback);
void SetOnBlurCallback(OnBlurFunc callback);
void SetOnKeyCallback(OnKeyConsumeFunc callback);
protected:
virtual bool HandleFocusTravel(const FocusEvent& event) = 0;
bool OnFocusEvent(const FocusEvent& event);
};
struct FocusCallbackEvents {
OnFocusFunc onFocusCallback_;
OnBlurFunc onBlurCallback_;
OnKeyConsumeFunc onKeyEventCallback_;
OnKeyConsumeFunc onKeyPreImeCallback_;
int32_t tabIndex_ = 0;
bool isDefaultFocus_ = false;
bool isDefaultGroupFocus_ = false;
std::optional<bool> isFocusOnTouch_;
};
焦点类型系统
FocusType (焦点类型)
文件: frameworks/core/components_ng/event/focus_type.h
enum class FocusType : int32_t {
DISABLE = 0, // 禁用焦点
NODE = 1, // 聚焦节点(叶子节点)
SCOPE = 2, // 聚焦作用域(容器节点)
};
类型说明:
- DISABLE: 节点不参与焦点系统
- NODE: 可聚焦的终端节点(Button、TextInput 等)
- SCOPE: 焦点容器节点(Row、Column、Grid 等)
FocusStyleType (焦点样式类型)
enum class FocusStyleType : int32_t {
NONE = -1, // 无样式
INNER_BORDER = 0, // 内边框
OUTER_BORDER = 1, // 外边框
CUSTOM_BORDER = 2, // 自定义边框
CUSTOM_REGION = 3, // 自定义区域
FORCE_BORDER = 4, // 强制边框
FORCE_NONE = 5, // 强制无边框
};
FocusStep (焦点移动方向)
enum class FocusStep : int32_t {
NONE = 0x0,
LEFT = 0x1, // 向左
UP = 0x2, // 向上
RIGHT = 0x11, // 向右
DOWN = 0x12, // 向下
LEFT_END = 0x3, // 向左到边界
UP_END = 0x4, // 向上到边界
RIGHT_END = 0x13, // 向右到边界
DOWN_END = 0x14, // 向下到边界
SHIFT_TAB = 0x5, // Shift+Tab(前一个)
TAB = 0x15, // Tab(下一个)
};
FocusIntension (焦点意图)
enum class FocusIntension : int32_t {
NONE = 0,
LEFT, UP, RIGHT, DOWN, // 方向键
TAB, SHIFT_TAB, // Tab 键
HOME, END, // Home/End 键
SELECT, SPACE, ESC, // 其他按键
};
焦点导航流程
方向键导航
用户按下方向键
↓
KeyEvent 分发到 FocusHub
↓
FocusEventHandler.OnKeyEvent()
↓
解析 FocusIntension (LEFT/UP/RIGHT/DOWN)
↓
HandleFocusTravel()
↓
根据 FocusStep 查找下一个可聚焦节点
↓
FocusManager.RequestFocus(newFocusHub)
↓
焦点切换成功
算法关键点:
- 当前节点判断: 检查当前焦点节点类型(NODE/SCOPE)
- 子节点遍历: SCOPE 类型遍历子节点查找候选
- 父节点委托: 无法处理时向上委托给父级 SCOPE
- 候选评估: 基于几何位置、Tab 顺序评估候选
Tab 键导航
用户按下 Tab/Shift+Tab
↓
KeyEvent 分发到 FocusHub
↓
解析为 FocusStep::TAB 或 SHIFT_TAB
↓
按 tabIndex 顺序查找下一个节点
↓
请求焦点到目标节点
↓
更新焦点状态
Tab 顺序规则:
- 优先按
tabIndex升序排列 - 相同
tabIndex按文档顺序 tabIndex < 0不参与 Tab 导航
默认焦点
FocusView 显示
↓
RequestDefaultFocus()
↓
查找 defaultFocus=true 的节点
↓
查找 tabIndex 最小的节点
↓
请求焦点到默认节点
↓
焦点成功设置
默认焦点优先级:
defaultFocus=true且isGroupDefault=true的节点defaultFocus=true的节点tabIndex最小的可聚焦节点
焦点样式渲染
FocusModifier (焦点修饰器)
文件: frameworks/core/components_ng/render/adapter/focus_modifier.h
class FocusModifier {
public:
void SetRoundRect(const RoundRect& rect, float borderWidth);
void SetPaintColor(const Color& paintColor);
void SetFrameNode(const RefPtr<FrameNode>& frameNode);
private:
RSRoundRect roundRect_; // Rosen 圆角矩形
Color paintColor_; // 绘制颜色
float paintWidthPx_; // 边框宽度
std::shared_ptr<RectF> overlayRect_; // 覆盖区域
};
焦点样式配置
应用层 (ArkTS):
Button('Click me')
.focusOnTouch(true)
.defaultFocus(false)
.tabIndex(1)
.onFocus(() => {
console.log('focused')
})
C++ 层:
// 设置焦点模式
FocusPattern pattern(FocusType::NODE, true, FocusStyleType::INNER_BORDER);
focusHub->SetFocusPattern(pattern);
// 设置焦点框样式
FocusBoxStyle boxStyle;
boxStyle.strokeColor = Color::BLUE;
boxStyle.strokeWidth = 2.0_vp;
FocusBox focusBox;
focusBox.SetStyle(boxStyle);
focusHub->SetFocusBox(focusBox);
API 映射
ArkTS 层到 C++ 层映射
| ArkTS 属性 | C++ 属性 | 设置方法 |
|---|---|---|
focusOnTouch |
FocusPattern::focusOnTouch | SetFocusOnTouch() |
defaultFocus |
FocusPattern::defaultFocus | SetDefaultFocus() |
tabIndex |
FocusPattern::tabIndex | SetTabIndex() |
groupDefaultFocus |
FocusPattern::isGroupDefault | SetIsGroupDefault() |
onFocus |
FocusCallbackEvents::onFocusCallback_ | SetOnFocusCallback() |
onBlur |
FocusCallbackEvents::onBlurCallback_ | SetOnBlurCallback() |
onKey |
FocusCallbackEvents::onKeyEventCallback_ | SetOnKeyCallback() |
桥接代码示例
文件: frameworks/bridge/declarative_frontend/engine/jsi/nativeModule/arkts_native_common_bridge.cpp
// 设置 focusOnTouch
ArkUINativeModuleValue SetFocusOnTouch(ArkUIRuntimeCallInfo* runtimeCallInfo)
{
EcmaVM* vm = runtimeCallInfo->GetVM();
Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(0); // Node
Local<JSValueRef> secondArg = runtimeCallInfo->GetCallArgRef(1); // Value
auto node = nodePtr(firstArg->ToNativePointer(vm)->Value());
bool focusOnTouch = secondArg->ToBoolean(vm)->Value();
auto frameNode = GetFrameNodeByNode(node);
auto focusHub = frameNode->GetFocusHub();
focusHub->SetFocusOnTouch(focusOnTouch);
return panda::JSValueRef::Undefined(vm);
}
常见问题排查
1. 焦点无法移动
检查清单:
- 节点
focusable属性是否为 true - 父节点是否为 SCOPE 类型
- 几何位置是否正确
- 是否有遮罩层阻挡
2. 焦点框不显示
检查清单:
-
FocusStyleType配置是否正确 -
FocusBox样式是否设置 -
FocusModifier是否正确应用 - 节点是否真正获得焦点
3. 默认焦点不生效
检查清单:
-
defaultFocus和tabIndex配置 - FocusView 是否已显示
- 节点是否可聚焦
- 焦点优先级是否冲突
最佳实践
1. 焦点设计原则
- 可预测性: 焦点移动应符合用户直觉(左→右,上→下)
- 可见性: 焦点框应清晰可见
- 一致性: 相同类型组件焦点行为一致
- 效率: 最小化焦点移动次数
2. 性能优化
- 避免过深焦点树嵌套(建议不超过 5 层)
- 合理使用 SCOPE 类型减少遍历范围
- 延迟加载复杂界面的焦点树
- 复用 FocusHub 实例
3. 无障碍支持
- 为所有可交互元素设置合适的
tabIndex - 提供有意义的
onFocus/onBlur回调 - 支持 keyboard navigation
- 为自定义组件实现焦点移动逻辑
搜索模式
# 查找焦点相关文件
find ace_engine -name "*focus*"
# 查找 FocusHub 使用
grep -r "GetFocusHub()" frameworks/core/components_ng
# 查找焦点事件处理
grep -r "OnKeyEvent\|OnFocus\|OnBlur" frameworks/core/components_ng
# 查找焦点样式
grep -r "FocusBox\|FocusPattern" frameworks/core/components_ng
参考资源
相关文件
| 文件 | 说明 |
|---|---|
focus_hub.h:45 |
FocusHub 类定义 |
focus_manager.h:171 |
FocusManager 类定义 |
focus_view.h:30 |
FocusView 类定义 |
focus_type.h:23 |
FocusType 枚举 |
focus_event_handler.h:125 |
HandleFocusTravel 方法 |
最后更新: 2025-02-04 适用版本: OpenHarmony API 12+