Reputation: 1319
I have a page with a player that has a height of 1/3 of the screen height. Under the channels, there are multiple channels inside a scroll view. I am trying to set the height of the scroll view section exactly from bottom of the player to bottom of the page. I tried to set it to (screen height - (playerheight) - (navigation bar height) - (tabbed bar height)). But the problem is that the tabbed bar height changes from device to device. I tried the following code:
.frame(height: (UIScreen.main.bounds.height) - ((UIScreen.main.bounds.height) * 2/6) - (geometry.safeAreaInsets.top + geometry.safeAreaInsets.bottom ) )
But it looks like geometry.safeAreaInsets.bottom does not contain the tabbed bar height. So is there any way to calculate it in SwiftUI or is there any other way to achieve a similar appearance?
I just want to place scrollview that contains the channels exactly between player and tab bar for all screen sizes.
Upvotes: 4
Views: 9219
Reputation: 77452
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:
Upvotes: 3