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.
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:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With