SwiftUI navigationTitle appear on a wired position and has a layout warning - ios

This is a subView of my project
and it appears at a very low position
xcode also give me the layout warning
import SwiftUI
struct DetailedView: View {
var referFood:ReferFood
#StateObject var recentFood=RecentSearched()
var body: some View {
NavigationView{
Form{
Section("名称")
{
Text("\(referFood.name)")
}
Section("保质期")
{
Text("\(referFood.qualityTime)")
}
Section("储藏方法")
{
Text("\(referFood.method)")
}
}.navigationTitle("详细信息")
.navigationBarTitleDisplayMode(.inline)
}
}
}
It build successfully however when I drag the slider

NavigationView should be in RootView only.
Example in documentation
https://developer.apple.com/documentation/swiftui/navigationlink
is shown below:
Destination View:
struct ColorDetail: View {
var color: Color
var body: some View {
color.navigationTitle(color.description)
}
}
RootView:
NavigationStack {
List {
NavigationLink("Mint") { ColorDetail(color: .mint) }
NavigationLink("Pink") { ColorDetail(color: .pink) }
NavigationLink("Teal") { ColorDetail(color: .teal) }
}
.navigationTitle("Colors")
}
ps:
NavigationStack is the new version of NavigationView which is now deprecated in iOS 16.

Related

Transitions not working inside NavigationView

I am trying to navigate between two views without a NavigationLink.
Here is the code:
import SwiftUI
struct NextView: View {
#State var text = ""
#Binding var displayView: Bool
var body: some View {
// 3
//NavigationView {
VStack {
Spacer()
TextField("Type something!", text: $text)
Button("Remove View") {
withAnimation {
displayView = false
}
}
Spacer()
}.background(Color.cyan)
//}
}
}
struct InitialView: View {
#State var displayView = false
var body: some View {
// 1
//NavigationView {
if displayView {
//2
//NavigationView {
NextView(displayView: $displayView)
.transition(.slide)
//}
} else {
Button("Tap to continue") {
withAnimation {
displayView = true
}
}
}
//}
}
}
I tried to place the NavigationView in 3 different places, one at a time. I managed to get the animation I wanted only by placing the structure in position 3 or not using it. Could anyone tell me why this happens and other possible solutions to use the NavigationView in position 1?
I tested only in the iPhone 12 simulator and am using XCode Version 13.4.1.
I think you just wanted this - animatable transition
struct InitialView: View {
#State var displayView = false
var body: some View {
NavigationView { // << just root view, not important
ZStack { // << owner container !!
if displayView {
NextView(displayView: $displayView)
.transition(.slide)
} else {
Button("Tap to continue") {
displayView = true
}
}
}
.animation(.default, value: displayView) // << animation !!
}
}
}
Tested with Xcode 13.4 / iOS 15.5
This is a tricky question. If you look closely at your code, you see that in postion 3 .transition is applied to the NavigationView. However, in positions 1 & 2 it’s not.
Transitions must be applied to the View that is transitioning, in your case, it’s the NavigationView that is wrapping the content. Implying that the NavigationView needs the modifier.
Add the transition to the NavigationView in any position & it should work as expected.

Can I navigate ParentView to another View by button in ChildView?, swiftUI

I'm new to SwiftUI and struggling to move MainView to LoginView by clicking Text() in ChildView.
I tried make NavigationView and NavigationLink like this code but it's not working. It's much more complex in real code but I show only simple structure of my code to explain.
struct ContentView: View {
#State private var currViewIdx: Int = 0
var body: some View {
NavigationView {
CurrentView(currViewIdx: $currViewIdx)
}
}
}
struct CurrentView: View {
#Binding var currViewIdx: Int
var body: some View {
if self.currViewIdx == 0 {
HomeView()
.onTapGesture {
self.currViewIdx = 0
}
} else {
//SomeView.onTapGesture(self.currViewIdx = 1)
}
}
}
struct HomeView: View {
var body: some View {
NavigationLink(destination: TestView()) {
Text("Go TestView")
.contentShape(Rectangle())
}
}
}
struct TestView: View {
var body: some View {
Text("Here is Test View")
}
}
I think, the top hierarchy view, ContentView, has NavigationView and it should be changed when I click Text("Go TestView") in HomeView because it's in NavagationLink.
But the ContentView is not changed to TestView although I touch Text("Go TestView"). How to solve this problem? I considered way to add one more State value to change top level view, but it seems not good if I'll make lots of more values
Thank you

remove status bar in SwiftUI

Trying to hide the status bar in iOS SwiftUI on the first view.
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationView {
VStack {
NavigationLink(destination: ContentViewC()) {
Text("New View")
}
}.offset(y: 100)
}.navigationViewStyle(StackNavigationViewStyle())
.accentColor(.white)
.statusBar(hidden: true)
}
}
The status bar is still showing on the initial view. Any suggestions?
This looks like a SwiftUI bug. The possible valid workaround is to use UIKit view controller, as representable, to manage status bar hidden.
Here is a demo of possible solution. Tested with Xcode 12.4 / iOS 14.4
class StatusBarHideHelper: UIViewController {
override var prefersStatusBarHidden: Bool { true } // << important !!
}
struct StatusBarHideHelperView: UIViewControllerRepresentable {
func makeUIViewController(context: Context) -> UIViewController {
StatusBarHideHelper()
}
func updateUIViewController(_ uiViewController: UIViewController, context: Context) {
}
}
and now we can use it in our SwiftUI view hierarchy, like
var body: some View {
NavigationView {
VStack {
NavigationLink(destination: ContentViewC()) {
Text("New View")
}
}.offset(y: 100)
}.navigationViewStyle(StackNavigationViewStyle())
.background(StatusBarHideHelperView()) // << this !!
.accentColor(.white)
Try that one
struct ContentView: View {
#State var hideStatusBar = false
var body: some View {
Button("Toggle Status Bar") {
withAnimation {
self.hideStatusBar.toggle()
}
}
.statusBar(hidden: hideStatusBar)
}
}

How it is possible to dismiss a view from a subtracted subview in SwiftUI

Whenever my code gets too big, SwiftUI starts acting weird and generates an error:
"The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions"
So I started breaking up my code into Extracted Subviews, one of the problems I came across is how to dismiss a view from a subtracted subview.
Example: we have here LoginContentView this view contains a button when the button is clicked it will show the next view UsersOnlineView.
struct LoginContentView: View {
#State var showUsersOnlineView = false
var body: some View {
Button(action: {
self.showUsersOnlineView = true
}) {
Text("Show the next view")
}
.fullScreenCover(isPresented: $showUsersOnlineView, content: {
UsersOnlineView()
})
}
On the other hand, we have a button that is extracted to subview, to dismiss the modal and go back to the original view:
import SwiftUI
struct UsersOnlineView: View {
var body: some View {
ZStack {
VStack {
CloseViewButton()
}
}
}
}
struct CloseViewButton: View {
var body: some View {
Button(action: {
// Close the Modal
}) {
Text("Close the view")
}
}
}
Give the sbview the state property that defines if the view is shown.
struct CloseViewButton: View {
#Binding var showView: Bool
var body: some View {
Button(
ShowView = false
}) {
Text("Close the view")
}
}
}
When you use the sub view give it the property
CloseButtonView(showView: $showOnlineView)
To allow the sub view to change the isShown property it needs to get a binding.
On the presentation mode. I think this only works with Swiftui presentations like sheet and alert.
The simplest solution for this scenario is to use presentationMode environment variable:
struct CloseViewButton: View {
#Environment(\.presentationMode) var presentationMode
var body: some View {
Button(action: {
presentationMode.wrappedValue.dismiss()
}) {
Text("Close the view")
}
}
}
Tested with Xcode 12.1 / iOS 14.1

SwiftUI adding custom UIViewControllerTransitioningDelegate

I'm trying to create SwiftUI custom segue animation, like this
I try to chain the animation to Destination but no use, it just animates inside the contents of Destination after presentation animation finish.
struct ContentView : View {
var body: some View {
NavigationView {
VStack {
List {
NavigationButton(destination: withAnimation{
Destination()
}.frame(width: 300, height: 300)
.animation(.basic())) {
CellView()
}
}
}
}
}
}
struct CellView : View {
var body: some View {
VStack {
Text("Cell")
}
}
}
struct Destination : View {
var body: some View {
VStack {
Text("GFD")
}
}
}
you can try with removing the animation

Resources