Ios 自动布局如何从视图中获取计算值

Ios 自动布局如何从视图中获取计算值,ios,macos,cocoa,autolayout,Ios,Macos,Cocoa,Autolayout,有一件事真的让我对自动布局发狂,我在做测试,发现如果你将UIView子类化,并将一些视图与它们的约束放在一起,就不可能知道计算值 假设我们有一个继承自UIView的TestViewClass,我们在里面有一些子视图。我们想在iPhone和iPad上使用它,所以我们使用了两种尺寸,假设100x100和200x200,我们做了一些限制,使一切都能正常工作。我们通过将这些子视图放置在某些位置来构建此视图 现在我们需要构建另一个子视图,其中包含许多按钮作为子视图(contentView),这些子视图的数

有一件事真的让我对自动布局发狂,我在做测试,发现如果你将UIView子类化,并将一些视图与它们的约束放在一起,就不可能知道计算值
假设我们有一个继承自
UIView
的TestViewClass,我们在里面有一些子视图。我们想在iPhone和iPad上使用它,所以我们使用了两种尺寸,假设100x100和200x200,我们做了一些限制,使一切都能正常工作。我们通过将这些子视图放置在某些位置来构建此视图
现在我们需要构建另一个子视图,其中包含许多按钮作为子视图(contentView),这些子视图的数量在运行时给定。
该算法将选择此内容视图的大小,并放置正确数量的按钮,计算它们之间的空间,使它们之间的距离相同,但覆盖整个内容视图宽度。例如,contentView的宽度为200点,按钮为3,边长为60。它们总共覆盖了180个点,所以我们还有20个点,应该放在按钮->10个点之间
这很简单,在自动布局之前做了几千次。为此,我需要contentView的宽度,它对其superview有一些限制,使其根据superview大小调整宽度,问题是我在UIView实现中找不到任何可以获得contentView大小最终值的地方。
我尝试查看
-layoutSubviews
-updateconstraint
-didmovetoserview
,值显示始终是原始视图。何时计算新帧?
很明显,我对自动布局没有什么了解…




我在设置表视图单元格高度时发现了这个问题,试图使它们根据表视图的大小独立地显示在屏幕上。以下是相关问题

您可以使用视图控制器的
viewdilayoutsubviews
,它将在布局视图时通知您。如果所有这些都是在自定义的
UIView
中添加约束,那么您只需为视图编写一个名为
viewdilayoutsubviews
的方法,并在视图控制器接收到它时让视图控制器调用它。此时,容器的尺寸应正确配置

但是,有两种方法甚至可以在不需要知道容器视图大小的情况下间隔一组按钮:

  • 我在容器中使用的一种方法是创建我称之为“间隔”的视图(存在的视图,但只有
    clearColor
    背景,因此您无法直观地看到它们)。然后,可以有效地使用以下内容创建一系列约束:

    H:|[spacer1][button1(60)][spacer2(==spacer1)][button2(60)][spacer3(==spacer1)][button3(60)][spacer4(==spacer1)]|
    
    如果按钮的数量是固定的,则可以使用VisualFormat在单个约束中执行此操作,如上所述。如果是数量可变的按钮,您可以对它们进行迭代,为每对按钮和间隔符构建一个VFL字符串(例如,第一个按钮将使用

    H:|[spacer][button(60)]
    
    所有后续操作将创建另一个按钮和另一个垫片,并使用以下VFL:

    H:[previousButton][spacer(==originalSpacer)][button(60)]
    
    然后我在末端添加一个最后的垫片:

    H:[lastButton][spacer(==originalSpacer)]|
    
    这有点麻烦,但正如您所看到的,您的控件布局完美,间距均匀,您不需要知道容器的尺寸

  • 另一种方法是使用
    NSLayoutFormatAlignAllCenterX
    属性。这样就不需要创建所有这些间隔符,但如果使用下面的简单算法,这些中心将均匀分布在它们之间。因此,除了标准的垂直约束和水平宽度约束之外对于按钮,您可以通过以下方式控制按钮的水平放置:

    [containerView addConstraint:[NSLayoutConstraint constraintWithItem:button[i]
                                                              attribute:NSLayoutAttributeCenterX
                                                              relatedBy:NSLayoutRelationEqual
                                                                 toItem:containerView
                                                              attribute:NSLayoutAttributeCenterX
                                                             multiplier:2.0 * (double) (i + 0.5) / (double) n
                                                               constant:0.0]];
    
    其中,
    i
    是为哪个按钮设置此水平约束的从零开始的索引,
    n
    是按钮数


  • 最后,我得到了我所缺少的关于自动布局的东西,这是一个基本概念

    自动布局的工作方式与自动调整遮罩的工作方式不同,新帧的工作方式不同 即时更新,但应请求。

    这将产生巨大的差异,它似乎与CATTransaction渲染周期同步,这是有意义的,因为布局计算可能是一项昂贵的任务,并且在渲染过程中的大多数时间,在您真正需要之前是没有用的。
    当然也有一些例外,比如这个,我们如何强制自动布局来进行计算?我们可以设置
    -setNeedsLayout
    方法和
    -layoutIfNeeded
    。第一种方法将视图标记为“脏”第二种方法强制立即进行布局。如果在获得正确的更新帧后立即在
    -didmovetoserview
    中设置调用这两种方法。
    希望这有帮助,
    Andrea

    您是否尝试过签出视图控制器的
    viewDidLayoutSubviews
    中的
    值?嗨,Rob,我没有尝试,因为它们是私有属性,所以不可见。但是即使它们是正确的,我也需要在子类中捕获它们。您还可以将间隔视图设置为hidden.hidden views participa布局中的te。@robmayoff同意。或者将
    alpha
    设置为零。有很多选项。谢谢!嗨@Rob谢谢你的回答。这是一个很有价值的答案,我投了赞成票,但不是重点。我想我已经明白了。感谢你的精彩解释。两年后,这帮助我在不同的实现中解决了相同的问题。