Yoga入门

一、布局 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 节点树的布局会一次性完成计算。在计算时,可通过传入availableWidthavailableHeight来限制布局的可用尺寸;若希望在某一轴向上允许尺寸无限扩展,可传入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 配置,并使其在整个应用生命周期内生效。当然也可以采用其他的配置归属方案,比如让节点树中不同部分使用不同的布局合规性规则来执行布局。

全局配置节点独立配置上下文相关配置
GlobalPer-nodeContextual

不同语言下创建并绑定配置

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 roundingAfter 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);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值