SwiftUI TabView covers content view - swift

Is it possible to have TabView tabItem to be positioned below the screen content?
My layout is:
var body: some View {
TabView {
self.contentView
.tabItem {
Image(systemName: "chart.bar.fill")
Text("Chart")
}
Text("Screen 2")
.tabItem {
Image(systemName: "person.3.fill")
Text("Leaderboard")
}
Text("Screen 3")
.tabItem {
Image(systemName: "ellipsis")
Text("More")
}
}
}
The actual result looks like this:
Is it possible to position TabView below the content layout, not on top of it? Or the option would be to set bottom padding on content view (and in this case it would be required to check the TabView height).
The contentView layout looks like this:
VStack {
List() { ... }
HStack { Button() Spacer() Button() ... }
}

The contentView contains a List, and it fills all available space, moving buttons that are located below the List under the TabView. Adding Space after the contentView solves the issue.
var body: some View {
TabView {
VStack {
self.contentView
Spacer()
}
.tabItem {
Image(systemName: "chart.bar.fill")
Text("Chart")
}
Text("Screen 2")
.tabItem {
Image(systemName: "person.3.fill")
Text("Leaderboard")
}
Text("Screen 3")
.tabItem {
Image(systemName: "ellipsis")
Text("More")
}
}
}
Thank you #Asperi for pointing in right direction, and checking the children of the contentView.

Just add to your content view:
.padding(.bottom, tabBarHeight)

Related

SwiftUI: Tabview Repeating itself

I'm trying to create a tabview for a macOS 10.15 app.
TabView {
BookmarksView()
.tabItem {
Text("Bookmark Settings")
}
DisplaySettings()
.tabItem {
Text("Display Settings")
}
}
And in any of my views included in the tab that has one element in the body it renders properly in the tab view.
struct BookmarksView: View {
var body: some View {
Text("Bookmarks View")
.font(.title)
.font(Font.body.bold())
}
}
But if i add any other element in the view, the tab repeats and shows the added element in its own tab.
struct BookmarksView: View {
var body: some View {
Text("Bookmarks View")
.font(.title)
.font(Font.body.bold())
Text("Testing")
.font(.system(size: 15))
}
}
Try to wrap them in container (stack or something) explicitly, like
struct BookmarksView: View {
var body: some View {
VStack { // << this !!
Text("Bookmarks View")
.font(.title)
.font(Font.body.bold())
Text("Testing")
.font(.system(size: 15))
}
}
}

SwiftUI - ForEach Loop in code is not displaying on tab

In my .tabItem 3 my loop is not displaying in the preview. Am I missing something? Still learning swift...
.tabItem {
VStack {
Image(systemName: "gamecontroller")
Text("Tab 3")
VStack {
List{
ForEach(0..<100) { index in
Text("This is tab 3!")
}
}
}
}
}
Your ForEach is inside the .tabItem, which is the tab bar icon. There's no way that tiny button can display 100 items.
I assume you want the ForEach to be that tab's screen?
Just put the VStack before the .tabItem.
VStack {
List{
ForEach(0..<100) { index in
Text("This is tab 3!")
}
}
}
.tabItem {
VStack {
Image(systemName: "gamecontroller")
Text("Tab 3")
}
}

SwiftUI Set Image Boundary

i want to set my right image frame boundaries like the left one without moving image or text. How can I do that. I tried a couple way but I couldn't find the solution.
You should use the built-in TabView. It provides all the functionality for you, and already made with accessibility in mind.
Here is an example (you can change it for your text and images):
struct ContentView: View {
#State private var selection: Int = 1
var body: some View {
TabView(selection: $selection) {
Text("Tab Content 1")
.tabItem {
Label("1", systemImage: "1.square")
}
.tag(1)
Text("Tab Content 2")
.tabItem {
Label("2", systemImage: "2.square")
}
.tag(2)
Text("Tab Content 3")
.tabItem {
Label("3", systemImage: "3.square")
}
.tag(3)
}
}
}
Result:
Custom version (highly unrecommended):
struct ContentView: View {
var body: some View {
VStack {
Spacer()
Text("Main Content")
Spacer()
HStack {
VStack {
Button {
//
} label: {
Label("1", systemImage: "1.square")
}
}.frame(maxWidth: .infinity)
VStack {
Button {
//
} label: {
Label("2", systemImage: "2.square")
}
}.frame(maxWidth: .infinity)
VStack {
Button {
//
} label: {
Label("3", systemImage: "3.square")
}
}.frame(maxWidth: .infinity)
}.frame(height: 50)
}
}
}

Center and align SwiftUI elements in a ScrollView

I have the following SwiftUI view:
import SwiftUI
struct MySwiftUIView: View {
var body: some View {
VStack {
HStack {
Text("top leading text")
Spacer()
}
Spacer()
HStack {
Spacer()
Text("centered text")
Spacer()
}
Spacer()
HStack {
Spacer()
Text("bottom trailing text")
}
}
}
}
It looks like this when run:
If I embed the view in a ScrollView like this:
import SwiftUI
struct MySwiftUIView: View {
var body: some View {
ScrollView {
VStack {
HStack {
Text("top leading text")
Spacer()
}
Spacer()
HStack {
Spacer()
Text("centered text")
Spacer()
}
Spacer()
HStack {
Spacer()
Text("bottom trailing text")
}
}
}
}
}
Then it looks like this when run:
How do I make the centered text centered, and the bottom trailing text rest on the bottom, when they are embedded in a ScrollView?
In a way, I want to use SwiftUI to replicate this scrolling behaviour seen in Xcode's inspectors, where the text "Not Applicable" is centered and scrollable:
Wrap the ScrollView inside GeometryReader. Then apply a minimum height to the scroll view equal to the geometry.size.height. Now the spacers you applied should fill the VStack the way you intended them to. Try the code below:
GeometryReader { geometry in
ScrollView(.vertical) {
VStack {
HStack {
Text("top leading text")
Spacer()
}
Spacer()
HStack {
Text("centered text")
}
Spacer()
HStack(alignment: .bottom) {
Spacer()
Text("bottom trailing text")
}
}
.padding()
.frame(width: geometry.size.width)
.frame(minHeight: geometry.size.height)
}
}
Also check this post for more discussion on this issue: SwiftUI - Vertical Centering Content inside Scrollview

NavigationView doesn't display correctly when using TabView in SwiftUI

Hello everyone. I'm developing a simple SwiftUI application that displays some tweets. It has a tab view with two views: the main page that will display the tweets and a secondary view.
The problem is that the main page has a NavigationView. If I choose to display only the main page, everything seems correct, but when I display it from the TabView and I scroll down, the NavigationView feels a bit weird.
As I'm not good at explaining, here you have some images:
It should be like this
But it is like this
I thought of adding .edgesIgnoringSafeArea(.top), but the NavigationView is now hidden by the notch and it doesn't make the effect.
Is there any way I can make the NavigationView display like in the first image?
Any help is appreciated. Thanks in advance.
My code
HomePageView:
struct HomePageView: View {
var body: some View {
NavigationView {
List {
//tweet code
}
.navigationBarTitle("Your feed")
}
}
}
TabView:
struct TabController: View {
#State private var selection = 0
var body: some View {
TabView(selection: $selection){
HomePageView()
.tabItem {
VStack {
Image(systemName: "house.fill")
.font(.title)
}
}
.tag(0)
Text("Second View")
.font(.title)
.tabItem {
VStack {
Image(systemName: "bell.fill")
.font(.title)
}
}
.tag(1)
}
}
}
Try adding .edgesIgnoringSafeArea(.top) to your tabview.
struct ContentView: View {
#State private var selection = 0
var body: some View {
TabView(selection: $selection){
HomePageView()
.tabItem {
VStack {
Image(systemName: "house.fill")
.font(.title)
}
}
.tag(0)
Text("Second View")
.font(.title)
.tabItem {
VStack {
Image(systemName: "bell.fill")
.font(.title)
}
}
.tag(1)
}.edgesIgnoringSafeArea(.top)
}
}