一、布局 Yoga 节点树
在 Yoga 中,每个盒子都由Yoga 节点(Yoga Node)来表示。这些节点会构成一个树形结构,该结构既用于存储输入的样式信息,也用于存储输出的布局计算结果。
构建 Yoga 节点树
可以对 Yoga 节点执行创建、样式设置和关联操作。若需了解如何为 Yoga 节点设置样式的完整参考,可查阅 “样式设置” 相关文档。
C/C++ 语言
#include <yoga/Yoga.h>
YGNodeRef root = YGNodeNew();
YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
YGNodeStyleSetWidth(root, 100.0f);
YGNodeStyleSetHeight(root, 100.0f);
YGNodeRef child0 = YGNodeNew();
YGNodeStyleSetFlexGrow(child0, 1.0f);
YGNodeStyleSetMargin(child0, YGEdgeRight, 10.0f);
YGNodeInsertChild(root, child0, 0.0f);
YGNodeRef child1 = YGNodeNew();
YGNodeStyleSetFlexGrow(child1, 1.0f);
YGNodeInsertChild(root, child1, 1.0f);
⚠️ 注意Yoga 节点不会被自动释放,在不再需要时需手动销毁。可调用YGNodeFree(node)释放单个节点,或调用YGNodeFreeRecursive(node)递归释放整个 Yoga 节点树。
Java 语言
import com.facebook.yoga.YogaEdge;
import com.facebook.yoga.YogaFlexDirection;
import com.facebook.yoga.YogaNode;
import com.facebook.yoga.YogaNodeFactory;
import com.facebook.yoga.YogaPositionType;
YogaNode root = YogaNodeFactory.create();
root.setFlexDirection(YogaFlexDirection.ROW);
root.setWidth(100.0f);
root.setHeight(100.0f);
YogaNode child0 = YogaNodeFactory.create();
child0.setFlexGrow(1.0f);
child0.setMargin(YogaEdge.Right, 10.0f);
root.addChildAt(child0, 0.0f);
YogaNode child1 = YogaNodeFactory.create();
child1.setFlexGrow(1.0f);
root.addChildAt(child1, 1.0f);
ℹ️ 说明基于 Java 实现的 Yoga 节点支持垃圾回收机制,无需手动释放。
JavaScript 语言
import Yoga, {Edge, FlexDirection, PositionType} from 'yoga-layout';
const root = Yoga.Node.create();
root.setFlexDirection(FlexDirection.Row);
root.setWidth(100);
root.setHeight(100);
const child0 = Yoga.Node.create();
child0.setFlexGrow(1);
child0.setMargin(Edge.Right, 10);
root.insertChild(child0, 0);
const child1 = Yoga.Node.create();
child1.setFlexGrow(1);
root.insertChild(child1, 1);
⚠️ 注意Yoga 节点不会被自动释放,在不再需要时需手动销毁。可调用node.free()释放单个节点,或调用node.freeRecursive()递归释放整个 Yoga 节点树。未来 Yoga 的 JavaScript 绑定版本可能会接入垃圾回收机制,从而移除手动释放的要求。
执行节点树布局计算
整个 Yoga 节点树的布局会一次性完成计算。在计算时,可通过传入availableWidth和availableHeight来限制布局的可用尺寸;若希望在某一轴向上允许尺寸无限扩展,可传入Undefined。
C/C++ 语言
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
Java 语言
root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED);
ℹ️ 说明Java 环境下的 Yoga 节点树若要实现从右到左(RTL)的布局,可通过设置根节点的direction属性来实现。
JavaScript 语言
root.calculateLayout(undefined, undefined, Direction.LTR);
读取布局计算结果
布局计算完成后,结果会写入每个 Yoga 节点中。这些结果包括节点相对于其父节点边框盒的偏移量、自身尺寸,以及各物理方向上外边距(margin)、边框(border)和内边距(padding)的最终解析值。
C/C++ 语言
float left = YGNodeLayoutGetLeft(child0);
float height = YGNodeLayoutGetHeight(child0);
Java 语言
float left = child0.getLayoutX();
float height = child0.getLayoutHeight();
JavaScript 语言
const left = child0.getComputedLeft();
const height = child0.getComputedHeight();
二、配置 Yoga
可以通过Yoga 配置(Yoga Config)来为 Yoga 设置不同的行为逻辑。一份配置会绑定到特定的 Yoga 节点上,这使得 Yoga 节点树中不同部分在布局计算时能采用不同的行为规则。
多数 UI 框架会应用一套统一的配置。在这类场景下,通常会创建一个全局的 Yoga 配置,并使其在整个应用生命周期内生效。当然也可以采用其他的配置归属方案,比如让节点树中不同部分使用不同的布局合规性规则来执行布局。
| 全局配置 | 节点独立配置 | 上下文相关配置 |
|---|---|---|
| Global | Per-node | Contextual |
![]() | ![]() | ![]() |
不同语言下创建并绑定配置
C/C++ 语言
#include <yoga/Yoga.h>
YGConfigRef config = YGConfigNew();
// 配置参数设置...
YGNodeRef root = YGNodeNewWithConfig(config);
⚠️ 注意Yoga 配置不会自动释放,在不再需要时需调用YGConfigFree(config)手动释放。
Java 语言
import com.facebook.yoga.YogaConfigFactory;
import com.facebook.yoga.YogaNodeFactory;
YogaConfig config = YogaConfigFactory.create();
// 配置参数设置...
YogaNode root = YogaNodeFactory.create(config);
JavaScript 语言
import Yoga from 'yoga-layout';
const config = Yoga.Config.create();
// 配置参数设置...
const root = Yoga.Node.create(config);
⚠️ 注意Yoga 配置不会自动释放,在不再需要时需调用config.free()手动释放。未来 Yoga 的 JavaScript 绑定版本可能会接入垃圾回收机制,从而移除手动释放的要求。
布局合规性与 Yoga 兼容补丁
在历史版本中,Yoga 存在一些不符合行业标准的行为,这会导致其布局效果与网页浏览器中的样式布局产生差异。若修复这些行为问题,又可能会改变基于 Yoga 旧版行为开发的现有应用的布局效果。为此,Yoga 支持通过配置兼容补丁(Errata),来选择优先遵循标准合规性还是保障向后兼容性。默认情况下,Yoga 会优先满足标准合规性。
兼容补丁可通过位标记的方式进行精细化配置,同时也提供了几种常用的预设选项:
None(默认):优先遵循标准合规性,Yoga 版本更新时会启用可能改变原有布局的修复项。Classic:尽可能贴近 Yoga 1.x 版本的行为逻辑。All:在Classic补丁集的基础上,额外启用StretchFlexBasis补丁,该补丁对应 Yoga 1.x 中默认未开启的UseLegacyStretchBehaviour行为。
不同语言下配置兼容补丁
C/C++ 语言
#include <yoga/Yoga.h>
YGConfigRef config = YGConfigNew();
YGConfigSetErrata(config, YGErrataClassic);
Java 语言
import com.facebook.yoga.YogaConfigFactory;
import com.facebook.yoga.YogaErrata;
YogaConfig config = YogaConfigFactory.create();
config.setErrata(YogaErrata.CLASSIC);
JavaScript 语言
import Yoga, {Errata} from 'yoga-layout';
const config = Yoga.Config.create();
config.setErrata(Errata.Classic);
点缩放系数
Yoga 会在 “点(point)” 构成的浮点网格上表示元素位置。这在底层 UI 框架进行渲染时,容易导致布局盒子的边缘落在子像素边界上,进而引发渲染不一致、元素模糊等问题。为缓解该问题,Yoga 默认会对位置进行取整,确保盒子边缘与物理 “像素网格” 对齐。
可以为节点配置PointScaleFactor(点缩放系数),用于告知 Yoga 点与物理像素之间的映射关系(通常对应显示器的像素密度)。若将PointScaleFactor设为0,则会关闭像素网格取整功能。
| 取整前 | 取整后 |
|---|---|
| Before rounding | After rounding |
![]() | ![]() |
不同语言下配置点缩放系数
C/C++ 语言
#include <yoga/Yoga.h>
YGConfigRef config = YGConfigNew();
YGConfigSetPointScaleFactor(config, 2.0f);
Java 语言
import com.facebook.yoga.YogaConfigFactory;
YogaConfig config = YogaConfigFactory.create();
config.setPointScaleFactor(2.0f);
JavaScript 语言
import Yoga from 'yoga-layout';
const config = Yoga.Config.create();
config.setPointScaleFactor(2);






406

被折叠的 条评论
为什么被折叠?



