【问题标题】:Optimal flexible box layout algorithm最优柔性盒子布局算法
【发布时间】:2011-08-02 16:06:18
【问题描述】:

我正在实现 W3C 定义的CSS3 flexible box layout module,它类似于Mozilla's box model for xul。虽然这些标准指定了模型的行为方式,但并未提供有关如何实施的任何细节。

我感兴趣的模型部分是:

  1. 框有宽度和高度。
  2. 框可以包含其他框。
  3. 容器框(父框)负责确定它们所包含的框(子框)的大小和位置。
  4. 框的方向可以是水平的或垂直的。方向决定子框的位置和大小。
  5. 子框可能是灵活的或不灵活的。如果子框不灵活,则以宽度和高度参数中指定的大小绘制。如果它是灵活的,则会调整其大小以适应父容器中的可用空间。
  6. 灵活性与同一容器中的其他子框相关,灵活性较高的框比灵活性较低的框调整大小更多。
  7. 可以将子框限制为最小或最大尺寸。如果子框是灵活的,则父框永远不会将其调整为低于最小尺寸或高于最大尺寸。

功能 1-5 可以非常有效地实现。特征 6 是有问题的,因为我能想出的最有效的算法非常幼稚。该算法的工作原理如下:

  1. 将所有框放在一个列表中。
  2. 遍历每个子框并使用灵活性来调整其大小,以确定调整大小的数量。
  3. 如果大小超过限制之一,则将框大小设置为限制并将其从列表中删除,并从列表的开头开始。

第 3 步是效率下降的地方。例如,如果列表中有十个项目,最后一个有约束,那么算法会计算前九个项目的大小,然后当它达到第十个时,它需要重做所有计算。我考虑过保持列表排序并首先调整所有受限框的大小,但这会带来增加复杂性和排序列表开销的成本。

考虑到这是浏览器和框架(XUL、.Net、Flex 等)中相当常见的功能,我希望有一个公认的最佳解决方案。

【问题讨论】:

    标签: algorithm optimization layout


    【解决方案1】:

    大多数盒子/容器布局算法使用 2 pass 算法。在 .NET (WPF) 的情况下,它们被称为“测量”和“排列”。每个控件都可以测量其内容并在递归测量过程中报告“所需大小”。

    在第二次传递(排列)期间,如果子代所需的尺寸不适合父代,则父代使用其布局算法为每个子代提供实际尺寸,例如通过分配按所需尺寸加权的实际尺寸。最小/最大尺寸、盒子的灵活性等都可以在这里发挥作用。

    有关 WPF 布局系统的更多信息 http://msdn.microsoft.com/en-us/library/ms745058.aspx

    Xul 布局 http://www-archive.mozilla.org/projects/xul/layout.html

    【讨论】:

    • +1 获取有趣的链接和信息。我目前正在做两遍,问题在于安排阶段,而在这个阶段发生的正是我想要优化的。
    • 排列阶段应该是使用一些映射函数(布局算法)从所需尺寸到实际尺寸的简单映射。例如,如果您想将两个宽度为 60 的子元素放入宽度为 100 的内容中,则在公平分配中可能会以 {50, 50} 结束,在另一个分配函数中可能会以 {60, 40} 结束。您是否将布局视为“调整大小”操作而不是“分配新大小”的操作?在布局过程中,孩子的任何旧尺寸都应该无关紧要,对吗?
    • 正确,每个布局通道都是独一无二的。我不能使用您所描述的直接映射的原因是由于最小/最大尺寸限制。例如,给定两个宽度为 40 的孩子,一个可能会被限制为最大宽度 60。当两个孩子都被拟合到一个 200 宽的区域时,受约束的孩子必须是 60,而另一个可以扩展到 140。一个正常的传递,它将尝试为两个框分配 100 的宽度。当遇到约束框时,需要重新计算非约束框。有没有办法只做一次所有的计算?
    • 如果您想将两个都过满的子元素分配到 200 宽的区域中,并且第一个子元素的最大宽度为 60,则它们所需的大小将为 {60,200}。您可以通过多种方式分配这些所需的尺寸:“首先提供”:{60,140}。 “所需的重量”:{46, 154}。 “先送达”的问题在于,如果顺序颠倒,分配将是 {200,0},这是不可取的。一种折衷方案是进行 2 遍排列,从公平的 {100,100} 开始,然后钳制到最小/最大尺寸以达到 {60,100},最后将松弛分配给不受约束的子级 {60,140}。
    • 我认为您应该查看 WPF 网格列宽分配算法以供参考。 wpftutorial.net/GridLayout.html 先看看列定义是如何产生的,然后或许可以尝试看看测量/排列代码的实现(我是通过反射器比如Jetbrains DotPeek 或RedGate's Reflector 来查看的)。首先,您应该问自己尺寸的定义是什么。它们是“所需尺寸”吗?或测量尺寸(如果它们本身包含儿童)。 wpf 列有 3 个不同的设置:fixed/auto/star,我认为这很有意义。
    猜你喜欢
    • 1970-01-01
    • 2011-12-02
    • 2020-08-12
    • 1970-01-01
    • 1970-01-01
    • 2017-10-29
    • 1970-01-01
    • 2011-05-26
    • 2021-12-05
    相关资源
    最近更新 更多