View background stretches over the safe area when using GeomtryReader - ios

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)

Related

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)
}
}

How can I declare the correct content to import another swiftui file into the contentview file?

I'm a bit new to swift and am a bit confused about what is being asked of me. Some background: I found a guy online who has created a swiftui file for a sliding bottom view bar and I wanted to implement it into my ContentView swiftui file. I have looked up and down the internet and tried to play around with things after clicking "fix" in xcode but I have had no luck.
Here are images of the error, me clicking "fix" prompt from xcode, and the BottomSheetView.swift file's code -> https://imgur.com/a/GqEjMzo
Can someone help me by explaining what exactly swift is asking me to do and let me know how I can solve this error?
Here is my code:
import SwiftUI
struct ContentView: View {
var body: some View {
ZStack{
VStack{
MapView()
.edgesIgnoringSafeArea(.all)
let heightDouble = CGFloat(150.00)
BottomSheetView(isOpen: .constant(true), maxHeight: heightDouble, content: <#() -> Content#>)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
}
Errors in SwiftUI are not always shown where they really are. The problem in your code snippet is at the line:
let heightDouble = CGFloat(150.00)
and it should be: Closure containing a declaration cannot be used with function builder 'ViewBuilder'
Try this and you'll see, that the problem is not in other views:
var body: some View {
ZStack{
VStack{
Text("hello") // replaced MapView()
.edgesIgnoringSafeArea(.all)
// you need to delete this row to avoid error
let heightDouble = CGFloat(150.00)
Text("world") // replaced BottomSheetView(...)
}
}
}
the code in body variable must return some View, but defining a constant inside it violates this rule
update
in BottomSheetView you have content which is other View. I don't see all the code, but I think it should be something like this:
struct ContentView: View {
#State var isOpen = true
var body: some View {
ZStack{
VStack{
MapView()
.edgesIgnoringSafeArea(.all)
BottomSheetView(isOpen: self.$isOpen, maxHeight: CGFLoat(150)) {
Text("bottom")
}
}
}
}

Why SwiftUI view transitions modifiers don't work?

I needed to add a view to my scene using a view transition. I was trying to use the modifier .transition(.opacity) but it just adds the view without any transition. I also tried the other transition types and they don't work. Since this is a really simple test project a don't see where's the issue. Here's a link to a video of my problem
import SwiftUI
struct Test: View {
#State var show = false
var body: some View {
VStack {
Button(action: {self.show.toggle()}) {
Text("Button")
}
if show {
Text("Test Text")
.transition(.move(edge: .top))
}
}
}
}
struct Test_Previews: PreviewProvider {
static var previews: some View {
Test()
}
}
You need to add animation for the transition
if show {
Text("Test Text").animation(.linear)
.transition(.move(edge: .top))
}

SwiftUI: unwanted split view on iPad

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)
}
}
}

Resources