Skip to content

Conversation

@Acdset
Copy link

@Acdset Acdset commented Jan 30, 2026

Problem

When a layout view (e.g. TGLinearLayout) is used as a subview of another layout with wrap width or height (tg_width.equal(.wrap) / tg_height.equal(.wrap)), the sublayout gets a frame of (0, 0, width, 0) or (0, 0, 0, height) instead of its content size.

Cause: tgCalcSizeFromSizeWrapSubview in TGBaseLayout.swift only handles non-layout views. For subviews that are TGBaseLayout with wrap size, it never calls tg_sizeThatFits to compute their size, so sbvtgFrame stays at the initial (0,0,0,0). The parent then uses this zero size when assigning the sublayout’s frame.

Solution

In tgCalcSizeFromSizeWrapSubview, before the existing non-layout branch:

  • If the subview is a TGBaseLayout and has wrap width or height (sbvsc.isSomeSizeWrap):
    • Call tg_sizeThatFits(sbvtgFrame.frame.size) to get the sublayout’s size.
    • Update sbvtgFrame.width and/or sbvtgFrame.height with the returned size when the corresponding dimension is wrap.

This way the parent layout gets the correct size for the layout subview and no longer assigns zero height or width.

Code change

File: TangramKit/TGBaseLayout.swift
Function: tgCalcSizeFromSizeWrapSubview(_:sbvsc:sbvtgFrame:)

Add the following block right after the tg_visibility == .gone early return and before the existing “只有非布局视图才这样处理” block:

// Layout subviews with wrap size: call tg_sizeThatFits to compute size and update sbvtgFrame;
// otherwise parent layout keeps (0,0,0,0) and assigns zero height/width to the sublayout.
if let sbvl = sbv as? TGBaseLayout, sbvsc.isSomeSizeWrap
{
    let fitSize = sbvl.tg_sizeThatFits(sbvtgFrame.frame.size)
    if sbvsc.width.isWrap
    {
        sbvtgFrame.width = sbvsc.width.measure(fitSize.width)
    }
    if sbvsc.height.isWrap
    {
        sbvtgFrame.height = sbvsc.height.measure(fitSize.height)
    }
    return
}

How to verify

  1. In a vertical root TGLinearLayout, add a child TGLinearLayout(.vert) with tg_size(width:.fill, height: .wrap) and add several subviews with fixed heights to the child.
  2. Before the fix: the child layout’s frame has height 0.
  3. After the fix: the child layout’s height is the wrapped content height (e.g. sum of subview heights + spacing).

Checklist

  • Change is limited to tgCalcSizeFromSizeWrapSubview; no API changes.
  • Layout subviews with wrap size now get correct size from tg_sizeThatFits.
  • Non-layout views and layout subviews without wrap size are unchanged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant