Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
565 views
in Technique[技术] by (71.8m points)

ios - Proportional height (or width) in SwiftUI

I started exploring SwiftUI and I can't find a way to get a simple thing: I'd like a View to have proportional height (basically a percentage of its parent's height). Let's say I have 3 views vertically stacked. I want:

  • The first to be 43% (of its parent's height) high
  • The second to be 37% (of its parent's height) high
  • The last to be 20% (of its parent's height) high

I watched this interesting video from the WWDC19 about custom views in SwiftUI (https://developer.apple.com/videos/play/wwdc2019/237/) and I understood (correct me if I'm wrong) that basically a View never has a size per se, the size is the size of its children. So, the parent view asks its children how tall they are. They answer something like: "half your height!" and then... what? How does the layout system (that is different from the layout system we are used to) manage this situation?

If you write the below code:

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

The SwiftUI layout system sizes each view to be 1/3 high and this is right according to the video I posted here above. You can wrap the rectangles in a frame this way:

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)
        }
    }
}

This way the layout system sizes the first rectangle to be 200 high, the second one to be 400 high and the third one to fit all the left space. And again, this is fine. What you can't do (this way) is specifying a proportional height.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You can make use of GeometryReader. Wrap the reader around all other views and use its closure value metrics to calculate the heights:

let propHeight = metrics.size.height * 0.43

Use it as follows:

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())

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...