gpt4 book ai didi

ios - 当另一个维度被夹住时,SwiftUI View 如何在一个维度上调整其理想大小?

转载 作者:行者123 更新时间:2023-12-01 19:32:23 26 4
gpt4 key购买 nike

View当另一个维度被夹紧时,在一个维度上调整它的理想尺寸?

例如,Text表现出这种行为。如果受 .fixedSize 约束并且在一个维度上给定的空间太小,如果可能的话,另一个维度的理想尺寸会相应地增长。

使用 .fixedSize(horizontal: false, vertical: false)


使用 .fixedSize(horizontal: false, vertical: true)


使用 .fixedSize(horizontal: true, vertical: false)


看起来像 Text以某种方式将其理想大小定义为 .frame(idealWidth: 400, idealHeight: 20)在前两种情况下。然而,令我困惑的部分是,它似乎正在将第三种情况下的内容修改为类似于 .frame(idealWidth: 80, idealHeight: 100) 的内容。 .

我们怎么能像 Text , 允许我们的 View更新其理想尺寸以响应被夹紧的尺寸?

这是 Text 中显示此行为的一些代码。我在上面描述过:

VStack(spacing: 100) {
Group {
Text("ooooooooooooooooooooooooooooooooooo")
.fixedSize(horizontal: false, vertical: false)
Text("ooooooooooooooooooooooooooooooooooo")
.fixedSize(horizontal: true, vertical: false)
Text("ooooooooooooooooooooooooooooooooooo")
.fixedSize(horizontal: false, vertical: true)
}
.background(Color.green)
.frame(width: 75, height: 75)
.background(Color.blue)
}

使用这种字体并重复“o”内容, Text希望基本上有大约等于 7,000 个点的正方形空间(案例 #2 的理想尺寸为 338x20,案例 #3 的理想尺寸为 68x108)。

这怎么能在自定义 View 中复制? ? minHeightminWidth不是静态的;它们取决于是否已夹紧尺寸的父级。作为 child ,我们如何知道我们被困在了哪些维度(如果有的话)?在每个示例中,来自父级的建议尺寸仍然是 75x75,那么 subview 可以访问什么来作为其理想尺寸的基础? Text怎么样这样做?

为了使答案更具体,请考虑如何替换 Text("oooooo")具有与 .fixedSize 行为相似的自定义类的实例的实例. IE。尝试保持 7,000 点正方形区域,最小高度为 20 点,更喜欢先水平生长。

最佳答案

由于 fixedSize 的性质,这是有问题的。作品:

  • 我们可以提供min , idealmax width 的值& height在哪里 min <= ideal <= max .
  • 我们必须预先提供它们,这是不可能的,因为 ideal水平/垂直固定的值会有所不同。

  • GeometryReader 包装器

    enter image description here

    注释代码是不言自明的。

    import SwiftUI

    extension View {
    func frame(size: CGSize) -> some View {
    self.frame(width: size.width, height: size.height)
    }
    }

    struct TextLike: View {
    // It's like text, how much space we'd like to occupy
    var squareArea: CGFloat

    // Text() draws at least one line of text, we'll do the same
    private let preferredHeight: CGFloat = 20

    // Preferred/Max width in case of one line of text
    private let preferredWidth: CGFloat

    init(squareArea: CGFloat) {
    self.squareArea = squareArea
    self.preferredWidth = squareArea / preferredHeight
    }

    var body: some View {
    GeometryReader { proxy in
    // Let's say that this is the text
    Color.green.opacity(0.5)
    .frame(size: self.size(withProxy: proxy))
    }
    .frame(
    // Ideally we'd like to draw it as one line of text
    idealWidth: preferredWidth,
    // Maximum width equals to ideal width (one line of text)
    maxWidth: preferredWidth,
    // At least one line of text
    minHeight: preferredHeight,
    // Ideally we'd like to draw it as one line of text
    idealHeight: preferredHeight
    )
    }

    private func size(withProxy proxy: GeometryProxy) -> CGSize {
    //
    // Good enough for the demonstration, but you should get PhD & read:
    //
    // https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
    // https://stackoverflow.com/a/10335601/581190
    // https://stackoverflow.com/a/10334868/581190
    //
    // Also it must be generic enough to cover different devices, ...
    //
    // proxy.size.width on iPhone SE (2nd) = 350.0
    // proxy.size.width on iPhone 11 Pro Max = 350.3333...
    //
    // Just be aware of this and provide proper logic.
    //
    let horizontalFix = abs(proxy.size.width.distance(to: preferredWidth)).isLessThanOrEqualTo(1.0)
    let verticalFix = abs(proxy.size.height.distance(to: preferredHeight)).isLessThanOrEqualTo(1.0)

    switch (horizontalFix, verticalFix) {
    case (true, _):
    // Horizontal fix -> use preferred (= max) width -> one line of text
    // Vertical is irrelevant, because we do prefer horizontal grow
    return CGSize(width: preferredWidth, height: preferredHeight)
    case (false, false):
    // Use the offered size -> fits container, possible truncation
    return proxy.size
    case (false, true):
    // Vertical fix -> use offered width & calculate height
    return CGSize(width: proxy.size.width, height: squareArea / proxy.size.width)
    }
    }
    }

    struct ContentView: View {
    var body: some View {
    VStack(spacing: 50) {
    Group {
    TextLike(squareArea: 7000)
    .fixedSize(horizontal: false, vertical: false)
    TextLike(squareArea: 7000)
    .fixedSize(horizontal: true, vertical: false)
    TextLike(squareArea: 7000)
    .fixedSize(horizontal: false, vertical: true)
    TextLike(squareArea: 7000)
    .fixedSize(horizontal: true, vertical: true)
    }
    .frame(width: 75, height: 75)
    .background(Color.blue)
    }
    }
    }

    问题
  • TextLike充当包装器,实际 View 在其中(一个附加层)。
  • 我们不能使用 background例如,它的修饰符。

  • 让我们修改代码并使用 background TextLike 上的修饰符和你一样的水平。

    struct ContentView: View {
    var body: some View {
    VStack(spacing: 50) {
    Group {
    TextLike(squareArea: 7000)
    .fixedSize(horizontal: false, vertical: false)
    TextLike(squareArea: 7000)
    .fixedSize(horizontal: true, vertical: false)
    TextLike(squareArea: 7000)
    .fixedSize(horizontal: false, vertical: true)
    TextLike(squareArea: 7000)
    .fixedSize(horizontal: true, vertical: true)
    }
    .background(Color.red.opacity(0.2))
    .frame(width: 75, height: 75)
    .background(Color.blue)
    }
    }
    }

    这就是发生的事情:

    enter image description here

    坦率地说,不是很理想,也不是很好,但我现在能得到最接近的。

    关于ios - 当另一个维度被夹住时,SwiftUI View 如何在一个维度上调整其理想大小?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61855646/

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