I'm just starting to look at SwiftUI, but... I'm under the impression GeometryReader
should handle this for you.
Give this a try:
struct Tab1View: View {
var body: some View {
GeometryReader { geometry in
VStack {
Text("Top == 1/3 height")
.frame(width: geometry.size.width, height: geometry.size.height / 3.0, alignment: .center)
.background(Color.init(red: 0.1, green: 0.1, blue: 0.5))
.foregroundColor(Color.white)
.border(Color.yellow)
Text("Bottom == 2/3 height")
.frame(width: geometry.size.width, height: geometry.size.height * 2.0 / 3.0, alignment: .center)
.background(Color.init(red: 0.5, green: 0.1, blue: 0.1))
.foregroundColor(Color.white)
.border(Color.yellow)
}
.frame(width: geometry.size.width,
height: geometry.size.height,
alignment: .topLeading)
}
}
}
struct Tab2View: View {
var body: some View {
Color.blue
}
}
struct MyTabView: View {
var body: some View {
TabView {
//Text("The content of the first view")
Tab1View()
.tabItem {
Image(systemName: "phone.fill")
Text("First Tab")
}
//Text("The content of the second view")
Tab2View()
.tabItem {
Image(systemName: "tv.fill")
Text("Second Tab")
}
}
}
}
struct MyTabView_Previews: PreviewProvider {
static var previews: some View {
MyTabView()
}
}
Result:

and, auto-adjusted to TabBar height when rotated:

Edit
After some more investigation, it looks like ScrollView
can size itself to fill available space, so we only need to set the height on the top view.
Here's a modified example:
struct MyItemView: View {
var itemDesc = "Testing"
var geoWidth: CGFloat = 100
var body: some View {
Text("\(self.itemDesc)")
.foregroundColor(Color.white)
.padding(16.0)
.frame(width: self.geoWidth, height: nil, alignment: .leading)
}
}
struct Tab1View: View {
var body: some View {
GeometryReader { geometry in
VStack(spacing: 0.0) {
Text("Top == 1/3 height")
.frame(width: geometry.size.width, height: geometry.size.height * 1.0 / 3.0, alignment: .center)
.background(Color.init(red: 0.1, green: 0.1, blue: 0.5))
.foregroundColor(Color.white)
.border(Color.yellow)
ScrollView(.vertical) {
VStack(alignment: .leading, spacing: 0) {
ForEach((1...20), id: \.self) {
MyItemView(itemDesc: "This is item \($0)", geoWidth: geometry.size.width)
.background(Color.init(red: 0.5, green: 0.1, blue: 0.1))
.border(Color.yellow)
}
}
}
.frame(width: geometry.size.width, height: nil, alignment: .leading)
}
}
}
}
struct Tab2View: View {
var body: some View {
GeometryReader { geometry in
VStack {
Text("Top == 1/3 height")
.frame(width: geometry.size.width, height: geometry.size.height * 1.0 / 3.0, alignment: .center)
.background(Color.init(red: 0.1, green: 0.1, blue: 0.7))
.foregroundColor(Color.white)
.border(Color.yellow)
Text("Bottom == 2/3 height")
.frame(width: geometry.size.width, height: geometry.size.height * 2.0 / 3.0, alignment: .center)
.background(Color.init(red: 0.2, green: 0.6, blue: 0.1))
.foregroundColor(Color.white)
.border(Color.yellow)
}
}
}
}
struct MyTabView: View {
var body: some View {
TabView {
Tab1View()
.tabItem {
Image(systemName: "phone.fill")
Text("First Tab")
}
Tab2View()
.tabItem {
Image(systemName: "tv.fill")
Text("Second Tab")
}
}
}
}
struct MyTabView_Previews: PreviewProvider {
static var previews: some View {
MyTabView()
}
}
and, new result:

