SwiftUI: unwanted split view on iPad - ios

Problem: a view on Pad shows up with unwanted split view.
My current setup is:
Catalina OSX beta 5 +
Xcode 11 Beta 5
Here is the code I used, with a Navigation View and a Navigation Title:
import SwiftUI
struct SwiftUIView: View {
var body: some View {
NavigationView {
Text("Search")
.navigationBarTitle(Text("Search"))
}
}
}
#if DEBUG
struct SwiftUIView_Previews: PreviewProvider {
static var previews: some View {
SwiftUIView()
}
}
#endif
When simulated on iPad (both physical device and preview) instead of a full screen view, I get this split screen view:
If I have just a view, with no NavigationView, I get a full screen view:
import SwiftUI
struct SwiftUIView: View {
var body: some View {
Text("Hello World!")
}
}
#if DEBUG
struct SwiftUIView_Previews: PreviewProvider {
static var previews: some View {
SwiftUIView()
}
}
#endif
How can I make a NavigationView full screen (not split screen) on iPad?

Update July 2022
Using NavigationStack instead of NavigationView should display as the main view as you would expect on iPad:
NavigationStack {
Text("Hello world!")
}
*In newer versions, the navigationViewStyle modifier has been deprecated.
Original answer:
You can apply the .navigationViewStyle(.stack) modifier to the NavigationView.
...
NavigationView {
Text("Hello world!")
}
.navigationViewStyle(.stack)
...
Edit: Below, I am answering Alexandre's questions from his comment:
Why full view is not the default for iPad? That's just a choice made by Apple...
Why this modifier goes outside of NavigationView closure, while the Navigation Title goes inside... Maybe this gives clarification: https://stackoverflow.com/a/57400873/11432719

To use this split style for iPad but remove for iPhone:
extension View{
func phoneOnlyStackNavigationView() ->some View {
if UIDevice.current.userInterfaceIdiom == .phone{
return AnyView(self.navigationViewStyle(StackNavigationViewStyle()))
} else {
return AnyView(self)
}
}
}

Related

View background stretches over the safe area when using GeomtryReader

When having a view inside a GeomtryReader and setting the background to a color. It ignores the vertical safe area and stretches beyond it. Only when the view is at the vertical edges.
It doesn't only happen on Preview, it happens on actual device as well.
I am not sure if this is a bug or a normal behaviour of SwiftUI if so what am I doing wrong?
I have a very simple view that you can test with as follows:
import SwiftUI
struct TestView: View {
var body: some View {
GeometryReader { reader in
Text("TEST")
.background(Color.red)
}
}
}
struct TestView_Previews: PreviewProvider {
static var previews: some View {
TestView()
}
}
You can add it in a VStack and add a Spacer and you will see the same behaviour when it is at the bottom.
import SwiftUI
struct TestView: View {
var body: some View {
GeometryReader { reader in
VStack {
Spacer()
Text("TEST")
.background(Color.red)
}
}
}
}
struct TestView_Previews: PreviewProvider {
static var previews: some View {
TestView()
}
}
I can clip it by adding .clipped() to the Text and it will be removed but this sounds like a work around to me.
I stepped away from SwiftUI for a while so I do not remember if this is a normal behaviour or not. I did some research but couldn't find anything related to this.
I am using XCode 14.2 (14C18) and Swift swift-driver version: 1.62.15 Apple Swift version 5.7.2 (swiftlang-5.7.2.135.5 clang-1400.0.29.51)

SwiftUI NavigationView list not dismissing itself when NavigationLink is clicked on iPads running iOS 15 in portrait orientation

Since iOS 15, clicking a NavigationLink in a NavigationView sometimes does not dismiss its nested list / sidebar on iPads in portrait orientation. The first click will dismiss the list, then it gets stuck. You can drag / scroll the list up and down to make the auto-hide behavior work again temporarily but it gets stuck again.
Here is some sample code to demonstrate:
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationView {
List {
ForEach(0...30, id: \.self) { n in
NavigationLink(
"\(n)",
destination: DetailView(n: n)
)
}
}
.navigationBarTitle("List")
}
}
}
struct DetailView: View {
var n: Int
var body: some View {
Text("\(n)")
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Considering how basic the code above is, my guess is that it's an iOS 15 bug but I would appreciate any pointers if it isn't. Thanks!

Change Status Bar Color SwiftUI no UIHosting

I'm trying to change my status bar color dynamically without success, anyone has any idea how to change it ?
I'm not using UIHosting controller so there is no AppDelegate or SceneDelegate fully using swiftUI:
#main
struct MyProjectApp: App{}
If i set ZStack {}.preferredColorScheme(.light) it only apply once, so if i go to another view and try to put ZStack {}.preferredColorScheme(.dark) it doesn't work.
I think i have try all the question here on stackoverflow, so if anyone have a definitive solution i appreciated.
#Updated code example
struct ContentA: View {
var body: some View {
NavigationView {
ZStack {
NavigationLink(destination: ContentB()) {
Text("Show Detail View")
}.navigationBarTitle("Navigation")
}.preferredColorScheme(.light)
}
}
}
struct ContentB: View {
var body: some View {
ZStack {
Text("Hello ContetB")
.padding()
.foregroundColor(.green)
}.preferredColorScheme(.dark)
}
}
If you try to change StatusBar color using this way it doesn't work.
The colors within the app should be dynamic automatically, unless you set them specifically. You can toggle the .preferredColorScheme within the Previews section.
struct ContentView: View {
var body: some View {
Text("Hello, world!")
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
.preferredColorScheme(.dark)
}
}

NavigationBar not showing when going to another tab in tabview

In my app when I navigate to another tab and scroll down the view and gets cut off and the navigation bar doesn't collapse as shown here:
I tried to put .edgesIgnoringSafeArea(.top) but then this happens:
When I press the home button the simulator and navigate back to the app the navigation bar will collapse when scrolling as intended. Is this a bug with Xcode? Currently I'm using XCode 11.4.1, testing on an iPhone 11 Pro Max simulator but the exact same result occurs on my physical iPhone 6s Plus.
EDIT: The code for the tab view is as follows:
import SwiftUI
struct MenuScreen: View {
#State private var selection = 0
var body: some View {
TabView(selection: $selection){
ItemsTab().tabItem{
Image(systemName: "phone.fill")
Text("Items")
}.tag(0)
TestTab().tabItem{
Image(systemName: "phone.fill")
Text("Test")
}.tag(1)
}
.navigationBarTitle("Menu")
// .edgesIgnoringSafeArea(.top)
.navigationBarItems(trailing: NavigationLink(destination:ProfileScreen()){Text("Profile")})
// .padding(.top,1)
.navigationViewStyle(DefaultNavigationViewStyle())
// .navigationBarHidden(true)
}
}
struct MenuScreen_Previews: PreviewProvider {
static var previews: some View {
MenuScreen()
}
}
The navigation view is wrapped inside a splash screen like so:
import SwiftUI
struct SplashScreen: View {
#State private var isActive = false
let content = ContentView()
var body: some View {
NavigationView{
VStack{
Text("Loading")
LoopingAnimation()
NavigationLink(destination: content,isActive: $isActive,label: {EmptyView()})
}.onAppear(perform: {
self.goToContentView(time:2.5)
}).navigationBarTitle("My app")
}
}
func goToContentView(time:Double){
DispatchQueue.main.asyncAfter(deadline: .now() + Double(time)){
self.isActive = true
}
}
}
struct SplashScreen_Previews: PreviewProvider {
static var previews: some View {
SplashScreen()
}
}
EDIT 2: I tried to put navigation views inside the tabview as shown here:
import SwiftUI
struct MenuScreen: View {
var body: some View {
TabView{
NavigationView{
ItemsTab().navigationBarTitle("Items")
}.tabItem{
Image(systemName: "house.fill")
Text("Items")
}
NavigationView{
TestTab().navigationBarTitle("Test")
}.tabItem{
Image(systemName: "phone.fill")
Text("Test")
}
}
.navigationBarHidden(true)
// .navigationBarBackButtonHidden(true)
.frame(alignment: .center)
// .edgesIgnoringSafeArea(.top)
.navigationBarItems(trailing: NavigationLink(destination:ProfileScreen()){Text("Profile")})
// .padding(.top)
.navigationViewStyle(DefaultNavigationViewStyle())
}
}
struct MenuScreen_Previews: PreviewProvider {
static var previews: some View {
MenuScreen()
}
}
But while it resulted in a collapsing navigation bar that worked even switching tabs the result looked like this:
Made the navigation bar stay collapsed in the tab screen similar to what happens when you navigate to other categories within a tab in the app store by setting .displayMode inside .navigationBarTitle to .inline
Screenshot:

Disable split view using Swift UI on iPad

Is there a way to disable the SplitView using SwiftUI on iPad inside a navigation view?
By setting the NavigationViewStyle
import SwiftUI
struct NavView: View {
var body: some View {
NavigationView{
List{
NavigationLink(destination: TestView(), label: {Text("TestView")})
}
}.navigationViewStyle(StackNavigationViewStyle())
}
}
struct NavView_Previews: PreviewProvider {
static var previews: some View {
NavView()
}
}

Resources