SwiftUI 中的比例高度(或宽度)

2024-02-26

我开始探索 SwiftUI,但找不到一种方法来获得简单的东西:我希望 View 具有成比例的高度(基本上是其父级高度的百分比)。假设我有 3 个垂直堆叠的视图。我想:

  • 第一个高度为(其父级高度)的 43%
  • 第二个高度为(其父级高度的)37%
  • 最后一个高度为(其父级高度的)20%

我观看了 WWDC19 上有关 SwiftUI 中自定义视图的有趣视频(https://developer.apple.com/videos/play/wwdc2019/237/ https://developer.apple.com/videos/play/wwdc2019/237/)并且我理解(如果我错了请纠正我)基本上视图本身从来没有大小,大小是其子级的大小。因此,父视图询问其子视图他们有多高。他们的回答是这样的:“你身高的一半!”然后什么?布局系统(与我们习惯的布局系统不同)如何处理这种情况?

如果您编写以下代码:

struct ContentView : View {
    var body: some View {
        VStack(spacing: 0) {
            Rectangle()
                .fill(Color.red)
            Rectangle()
                .fill(Color.green)
            Rectangle()
                .fill(Color.yellow)
        }
    }
}

SwiftUI 布局系统将每个视图的大小设置为 1/3 高,根据我上面发布的视频,这是正确的。 您可以这样将矩形包裹在框架中:

struct ContentView : View {
    var body: some View {
        VStack(spacing: 0) {
            Rectangle()
                .fill(Color.red)
                .frame(height: 200)
            Rectangle()
                .fill(Color.green)
                .frame(height: 400)
            Rectangle()
                .fill(Color.yellow)
        }
    }
}

这样,布局系统将第一个矩形的大小调整为 200 高,第二个矩形的高度调整为 400,第三个矩形的大小调整为适合所有剩余空间。再说一次,这很好。 你不能(通过这种方式)指定比例高度。


UPDATE

如果您的部署目标至少为 iOS 16、macOS 13、tvOS 16 或 watchOS 9,您可以编写自定义Layout。例如:

import SwiftUI

struct MyLayout: Layout {
    func sizeThatFits(proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) -> CGSize {
        return proposal.replacingUnspecifiedDimensions()
    }

    func placeSubviews(in bounds: CGRect, proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) {
        precondition(subviews.count == 3)

        var p = bounds.origin
        let h0 = bounds.size.height * 0.43
        subviews[0].place(
            at: p,
            proposal: .init(width: bounds.size.width, height: h0)
        )
        p.y += h0

        let h1 = bounds.size.height * 0.37
        subviews[1].place(
            at: p,
            proposal: .init(width: bounds.size.width, height: h1)
        )
        p.y += h1

        subviews[2].place(
            at: p,
            proposal: .init(
                width: bounds.size.width,
                height: bounds.size.height - h0 - h1
            )
        )
    }
}

import PlaygroundSupport
PlaygroundPage.current.setLiveView(MyLayout {
    Color.pink
    Color.indigo
    Color.mint
}.frame(width: 50, height: 100).padding())

Result:

虽然这比下面的代码更多GeometryReader解决方案(如下),它可以更容易调试并扩展到更复杂的布局。

ORIGINAL

您可以利用GeometryReader。让读者围绕所有其他视图并使用其闭包值metrics计算高度:

let propHeight = metrics.size.height * 0.43

使用方法如下:

import SwiftUI

struct ContentView: View {
    var body: some View {
        GeometryReader { metrics in
            VStack(spacing: 0) {
                Color.red.frame(height: metrics.size.height * 0.43)
                Color.green.frame(height: metrics.size.height * 0.37)
                Color.yellow
            }
        }
    }
}

import PlaygroundSupport

PlaygroundPage.current.liveView = UIHostingController(rootView: ContentView())
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SwiftUI 中的比例高度(或宽度) 的相关文章

随机推荐