gpt4 book ai didi

ios - 根据SwiftUI中的宽度计算每行的项目数

转载 作者:行者123 更新时间:2023-12-04 13:11:44 52 4
gpt4 key购买 nike

这是我之前的问题( Get width of a view using in SwiftUI )的扩展

我需要实现一个布局,其中每行的项目数是根据它们的组合宽度动态确定的(基本上,将项目排成一行,直到它们不再适合为止)。

two muppets

有人告诉我,使用 GeometryReader 是一种用声明性语言做某事的hacky 方式,这显然是正确的。

我也被定向到这个类似 CollectionView 的组件 https://github.com/Q-Mobile/QGrid但该解决方案是静态的,因为在呈现任何组件之前,行数和每行单元格的数量是一次性确定的。

我不知道如何解决这个问题,所以任何建议对我来说都非常有值(value)!

❤️❤️❤️

最佳答案

TL; 博士

GeometryReader 可能是一个“hacky”解决方案,但它是我们目前拥有的解决方案。可以创建一个动态回流少量项目或延迟大量项目的解决方案。 My demo code 在这里会很笨拙,但听起来描述我的方法可能有用。

使用我们所拥有的

在幕后,SwiftUI 正在执行各种优化的约束求解以有效地布局您的 View 。从理论上讲,像您描述的那样回流内容可能是解决约束的一部分;在今天的 SwiftUI 中,事实并非如此。因此,执行您所描述的操作的唯一方法是以下某些变体:

  • 让 SwiftUI 根据我们的数据模型布置所有内容。
  • 获取 SwiftUI 决定使用几何阅读器和首选项/回调的宽度。
  • 使用这些宽度来解决我们的回流限制。
  • 更新数据模型,会触发第一步。

  • 希望这个过程收敛到一个稳定的布局,而不是进入一个无限循环。

    我的结果

    在玩弄它之后,这就是我到目前为止所得到的。您可以看到,随着宽度的变化,少量项目(在我的示例中为 29)几乎立即回流。对于大量项目(在我的示例中为 262),会有明显的延迟。如果内容和 View 宽度不改变并且不需要经常更新,这应该不是什么大问题。时间几乎全部花在步骤 1 上,所以在我们在 SwiftUI 中获得适当的回流支持之前,我怀疑这已经足够了。 (如果您想知道,一旦回流完成,垂直 ScrollView 会以正常响应滚动。)

    View reflow example

    我的策略

    本质上,我的数据模型从一个 [String] 数组开始,并将其转换为一个 [[String]] 数组,其中每个内部数组对应于一条线,在我的 View 中可以水平放置。 (从技术上讲,它以 String 开头,在空白处拆分以形成 [String] ,但从广义上讲,我有一个要拆分为多行的集合。)然后我可以使用 VStackHStack 进行布局 ForEach

    我的第一种方法是尝试读取我正在显示的实际 View 的宽度。但是,我很快遇到了无限递归或奇怪的不稳定振荡​​,因为它可能会截断 TextView (例如 [四] [分数] [和] [se ...]),然后在回流改变后取消截断一次,返回来回(或以截断状态结束。

    所以我决定作弊。我在第二个不可见的水平 ScrollView 中布置了所有单词。这样,它们都可以根据需要占用尽可能多的空间,永远不会被截断,最重要的是,因为此布局仅取决于 [String] 数组而不是派生的 [[String]] 数组,因此它永远不会进入递归循环。您可能认为将每个 View 放置两次(一次用于测量宽度,一次用于显示)是低效的,但我发现它比尝试从显示的 View 中测量宽度要快几十倍,并产生 100% 的正确结果时间。
    +---------- FIRST TRY - CYCLIC ----------+  +-------- SECOND TRY - ACYCLIC --------+
    | | | |
    | +--------+ [String] +----------+ | | +-------+ [String] +--------+ |
    | | | | | | | |
    | | +--------------------------+ | | | v v |
    | | | | | | | Hidden +--> Widths +--> [[String]] |
    | v v + v | | layout | |
    | Display +--> Widths +--> [[String]] | | v |
    | layout | | Display |
    | | | layout |
    +----------------------------------------+ +--------------------------------------+

    为了读取和保存宽度,我调整了 GeometryReader/PreferenceKey 方法 detailed on swiftui-lab.com 。宽度保存在 View 模型中,并在隐藏 ScrollView 中的 View 数量或大小发生变化时更新。这样的更改(或更改 View 的宽度)然后根据模型中保存的宽度将 [String] 数组回流到 [[String]]

    概括

    现在,这些在运输应用程序中是否有用将取决于您想要回流的项目数量,以及它们是否会在布局后保持静态或经常更改。但我发现这是一个迷人的消遣!

    关于ios - 根据SwiftUI中的宽度计算每行的项目数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57595009/

    52 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com