Retrieving the content size that caused overflow #1807

Closed
opened 2025-04-30 20:11:23 -07:00 by ehopperdietzel · 3 comments
ehopperdietzel commented 2025-04-30 20:11:23 -07:00 (Migrated from github.com)

Hi, since Yoga lets us know when overflow occurs, I assume it might also know the content size. If that's the case, could an API be added to access this information? This would save users from having to iterate and recalculate it manually.

Hi, since Yoga lets us know when overflow occurs, I assume it might also know the content size. If that's the case, could an API be added to access this information? This would save users from having to iterate and recalculate it manually.
elgunhuseynli commented 2025-05-09 18:20:36 -07:00 (Migrated from github.com)

Hi. I also hit the same issue as you described while implementing scroll view. Unfortunately there are issues from 2017 asking the same API and Yoga team didn't implemented the requested feature. For now we can solve this by two approach. One is add intermediate node between scroll view and its content, then you can get width/height of intermediate node which will be the natural size of content. Second solution is iterating children and manually calculating bounding box and caching it, and invalidating the cache on YGNodeSetDirtiedFunc().

Here is the basic implementation for second solution.

class UINode {
public:

    UINode() {
        YGNodeSetContext(mYogaNode, this);
        YGNodeSetDirtiedFunc(mYogaNode, [](YGNodeConstRef node) {
            auto uiNode = static_cast<UINode*>(YGNodeGetContext(node));
            uiNode->mNaturalSize = {-1, -1}; // invalidate the cache
        });
    }
    ~UINode() {
        YGNodeFree(mYogaNode);
    }

    YGSize getNaturalSize() {
        if (mNaturalSize.width >= 0 && mNaturalSize.height >= 0) {
            return mNaturalSize; // return cached natural size
        }

        YGSize size{0, 0};

        for (int i = 0; i < YGNodeGetChildCount(mYogaNode); ++i) {
            YGNodeRef child = YGNodeGetChild(mYogaNode, i);
            size.height = std::max(YGNodeLayoutGetTop(child) + YGNodeLayoutGetHeight(child) + YGNodeLayoutGetMargin(child, YGEdgeBottom), size.height);
            size.width = std::max(YGNodeLayoutGetLeft(child) + YGNodeLayoutGetWidth(child) + YGNodeLayoutGetMargin(child, YGEdgeRight), size.width);
        }

        size.height += YGNodeLayoutGetPadding(mYogaNode, YGEdgeBottom);
        size.width += YGNodeLayoutGetPadding(mYogaNode, YGEdgeRight);

        mNaturalSize = size;

        return mNaturalSize;
    }

private:
    YGNodeRef mYogaNode = YGNodeNew();
    YGSize mNaturalSize {-1, -1};
}
Hi. I also hit the same issue as you described while implementing scroll view. Unfortunately there are issues from 2017 asking the same API and Yoga team didn't implemented the requested feature. For now we can solve this by two approach. One is add intermediate node between scroll view and its content, then you can get width/height of intermediate node which will be the natural size of content. Second solution is iterating children and manually calculating bounding box and caching it, and invalidating the cache on YGNodeSetDirtiedFunc(). Here is the basic implementation for second solution. ```cpp class UINode { public: UINode() { YGNodeSetContext(mYogaNode, this); YGNodeSetDirtiedFunc(mYogaNode, [](YGNodeConstRef node) { auto uiNode = static_cast<UINode*>(YGNodeGetContext(node)); uiNode->mNaturalSize = {-1, -1}; // invalidate the cache }); } ~UINode() { YGNodeFree(mYogaNode); } YGSize getNaturalSize() { if (mNaturalSize.width >= 0 && mNaturalSize.height >= 0) { return mNaturalSize; // return cached natural size } YGSize size{0, 0}; for (int i = 0; i < YGNodeGetChildCount(mYogaNode); ++i) { YGNodeRef child = YGNodeGetChild(mYogaNode, i); size.height = std::max(YGNodeLayoutGetTop(child) + YGNodeLayoutGetHeight(child) + YGNodeLayoutGetMargin(child, YGEdgeBottom), size.height); size.width = std::max(YGNodeLayoutGetLeft(child) + YGNodeLayoutGetWidth(child) + YGNodeLayoutGetMargin(child, YGEdgeRight), size.width); } size.height += YGNodeLayoutGetPadding(mYogaNode, YGEdgeBottom); size.width += YGNodeLayoutGetPadding(mYogaNode, YGEdgeRight); mNaturalSize = size; return mNaturalSize; } private: YGNodeRef mYogaNode = YGNodeNew(); YGSize mNaturalSize {-1, -1}; } ```
ehopperdietzel commented 2025-05-09 20:55:14 -07:00 (Migrated from github.com)

Hi @elgunhuseynli, thank you! I eventually ended up calculating it myself as you suggested, but ignoring nodes with absolute pos. In my case, it's for window resizing, where I want to avoid letting the user resize it to less than the minimum content size.

So, after layout, I manually calculate the content bounds (which luckily are never more than 2 or 3 nodes) and check at the same time if there is overflow with the parent. If there is, I update the parent size and calculate again. I always check if there is overflow myself because I noticed that the hasOverflow result applies only to one of the axes, I assume the layout direction, if the other axis has overflow it still returns false.

Hi @elgunhuseynli, thank you! I eventually ended up calculating it myself as you suggested, but ignoring nodes with absolute pos. In my case, it's for window resizing, where I want to avoid letting the user resize it to less than the minimum content size. So, after layout, I manually calculate the content bounds (which luckily are never more than 2 or 3 nodes) and check at the same time if there is overflow with the parent. If there is, I update the parent size and calculate again. I always check if there is overflow myself because I noticed that the `hasOverflow` result applies only to one of the axes, I assume the layout direction, if the other axis has overflow it still returns false.
ehopperdietzel commented 2025-05-10 00:56:39 -07:00 (Migrated from github.com)

Closing as this appears to be a duplicate of https://github.com/facebook/yoga/issues/623

Closing as this appears to be a duplicate of https://github.com/facebook/yoga/issues/623
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: DaddyFrosty/yoga#1807
No description provided.