I find some tutorials online for NavigationView, one example is here.
However, most of examples are for macOS 11, but I want to run on macOS 10.15 or lower. Here is an example code:
var body: some View {
NavigationView {
List {
Label("Books", systemImage: "book.closed")
Label("Tutorials", systemImage: "list.bullet.rectangle")
Label("Video Tutorials", systemImage: "tv")
Label("Contacts", systemImage: "mail.stack")
Label("Search", systemImage: "magnifyingglass")
}
.listStyle(SidebarListStyle())
.navigationTitle("Code")
}
However, this code error at Label. How can I fix this for running on macOS 10.15
Thanks
Related
I want to use the new iOS 16 Buttom Sheet Feature to create a view like the find my:
Unfortunately the TabView gets hidden behind the Sheet:
My Code:
TabView {
Text("View 1")
.sheet(isPresented: .constant(true)) {
Text("Sheet View Content")
.presentationDetents([.medium, .large])
}
.tabItem {
Label("Menu", systemImage: "list.dash")
}
Text("View 2")
.tabItem {
Label("Order", systemImage: "square.and.pencil")
}
}
How can I achieve this?
No Solution for the moment
Unfortunately, it is not currently possible to show a modal sheet with a tab bar visible using the current version of SwiftUI. This issue has been raised by other developers on the Apple developer forums and on other threads on StackOverflow, such as the following:
https://developer.apple.com/forums/thread/711702
Swift UI show modal sheet with tab bar visible
SwiftUI present sheet in a TabItem of TabView using presentationDetents
I am also searching for a solution to this problem.
I am currently working on a custom ViewModifier to address this issue, and if it is successful, I will make it publicly available on GitHub.
I'm a newbie, using XCode 13.0 to create a very basic app that needs to have a Settings view. I'd like to navigate to the Settings view on tapping a label. To do that, it seemed sensible to use a NavigationView with a NavigationLink.
Unfortunately, I'm encountering a formatting issue that creates a mess of the HStack in which the Setting label (gear icon) resides, as show below:
This is what I want, a result of the following code:
HStack(spacing: 25) {
... other labels
Label ("", systemImage: "gear")
.foregroundColor(.gray)
.font(.title)
.onTapGesture(perform: {
// Set a state variable that triggers an extension
// that brings up the SettingsView
})
}
This is what happens when NavigationView encapsulates the gear icon label. Note the vertical and horizontal white space around it.
HStack(spacing: 25) {
... other labels
NavigationView {
NavigationLink(destination: SettingsView()) {
Label ("", systemImage: "gear")
.foregroundColor(.gray)
.font(.title)
}.navigationBarTitle(Text(""))
}
}
I've, literally, spent weeks (sporadically) on this issue, looking up dozens of answers and trying various formatting options, without luck. I've also tried encapsulating parent and grandparent stacks into the NavigationView. To no avail. Surely, this is something trivial. Can somebody point me in the right direction?
p.s. there are other issues in that that Navigation link opens as a sub-window; I plan to tackle that later.
Edit: Right, so I tried using Yrb's code:
HStack(spacing: 25) {
... other labels
NavigationView {
NavigationLink(destination: Text("Linked View")) {
Image(systemName: "gear")
.foregroundColor(.gray)
.font(.title)
}
.fixedSize()
.background(Color.red)
}
]
Unfortunately, there's no substantive change...
In diagnosing these sort of issues, it helps to throw a .background() with a color on. You can then see the issue. In this case, it was twofold, one, you need to use a .fixedSize to shrink the view to its smallest dimensions necessary. That would leave you with the icon plus a little space. That was due to you using a label as it was leaving a spot for the Text("") that you used as a fill in. Since you only want the image, use Image(systemName:) The code then comes out like this:
struct NavLinkNoSpace: View {
var body: some View {
NavigationView {
NavigationLink(destination: Text("Linked View")) {
Image(systemName: "gear")
.foregroundColor(.gray)
.font(.title)
}
.fixedSize()
// Setting this shows you what space you are using. Remove it when you are done
.background(Color.red)
}
}
}
A couple more things. If you have not ever set the NavigationTitle, you don't need to set it to "". In your example, there was no title, so I simply removed it and there was no effect.
More importantly, and it was addressed by some of the comments, you should only have one NavigationView in the view hierarchy. As long as you are in the hierarchy, you do not need to wrap things like NavigationLink to have them work. You can always throw one around your view call in the preview provider if you are in a child view, to show what things look like, and to test NavigationLinks, etc., but do not just put them in to your main code. It will lead to undesirable outcomes.
To summarize what worked to fix the primary problem, that of formatting: The key was in figuring what to encapsulate within the NavigationView. My mistake was to assume that only the NavigationLink needed to be in the NavigationView.
What worked was to place all the contents of the body into the NavigationView, like below:
var body: some View {
NavigationView {
VStack(spacing: -10) {
Text(appName)
.font(.largeTitle)
.foregroundColor(.blue)
.padding(.bottom)
// ...
// includes a bunch of VStacks and HStacks
// ... and finally
NavigationLink(destination: SettingsView()) {
Image(systemName: "gear")
.foregroundColor(.gray)
.font(.title)
// ... more stuff
// ... and finally
}.padding(.top, -100) // NavigationView
} // body
When I go to my second page which has a ScrollView, and I scroll to the point it becomes inline and then return to the mainView - the navigationBarTitles is being overwritten with both navigationBarTitles.
I am using Xcode Version 12.5 (12E262) and this is iOS 14.
It is happening both in the simulator and on a device.
MainView
ScrollView
ScrollView scrolled so it becomes inline
And when I return to the MainView from the inline NavBar I get this.
It is fine - unless I have scrolled. And what makes it even more confusing it only does it about 25% of the time.
I am just using "self.presentationMode.wrappedValue.dismiss()" to return to the mainView
I am using a NavigationLink to go to the second page.
NavigationLink(destination: ScrollView(), isActive: $showScroll ) { EmptyView() }
Is there something I have missed when dismissing from Scrolling?
very plain code for the scrollView.
I am obviously missing something or this is a big issue with SwiftUI and Xcode.
Thank you.
var body: some View {
ScrollView(showsIndicators: false) {
}
.navigationBarBackButtonHidden(true)
.navigationBarTitle("scrollView Page")
.navigationBarItems(
leading:
Button(action:{
self.presentationMode.wrappedValue.dismiss()},
label: {
Image(systemName: "arrow.left")
})
}
I have tried to have a layout like the following screen shots. Basically a long vertical scrolling view, with a number of round corner panes.
My code as follows:
struct DetailView: View {
#EnvironmentObject var modelData: ModelData
var body: some View {
ZStack {
Image("Dummy")
.resizable()
.aspectRatio(contentMode: .fill)
.opacity(0.2)
.frame(width: .infinity, height: .infinity)
.edgesIgnoringSafeArea(.all)
ScrollView(.vertical, showsIndicators: false) {
VStack(alignment: .leading, spacing: 0) {
TabView {
VStack(alignment: .leading, spacing:0) {
HStack {
Text("A long Text title").font(.title)
Spacer()
}.frame(width:UIScreen.main.bounds.size.width*0.9)
HStack {
Text("A long Text title").font(.title)
Spacer()
}.frame(width:UIScreen.main.bounds.size.width*0.9)
HStack {
Text("A long Text title").font(.title)
Spacer()
}.frame(width:UIScreen.main.bounds.size.width*0.9)
HStack {
Text("A long Text title").font(.title)
Spacer()
}.frame(width:UIScreen.main.bounds.size.width*0.9)
}
}.tabViewStyle(PageTabViewStyle())
.background(Color.green)
TabView {
ImageView()
.frame(width:UIScreen.main.bounds.size.width*0.9)
.cornerRadius(UIConstants.cardCornerRadius)
ImageView()
.frame(width:UIScreen.main.bounds.size.width*0.9)
.cornerRadius(UIConstants.cardCornerRadius)
ImageView()
.frame(width:UIScreen.main.bounds.size.width*0.9)
.cornerRadius(UIConstants.cardCornerRadius)
}
.tabViewStyle(PageTabViewStyle())
.indexViewStyle(PageIndexViewStyle(backgroundDisplayMode: .always))
.background(Color.red)
TabView {
TextInfoView()
.frame(width:UIScreen.main.bounds.size.width*0.9)
.cornerRadius(UIConstants.cardCornerRadius)
.padding([.horizontal])
}.tabViewStyle(PageTabViewStyle())
.background(Color.green)
TabView {
TextInfoView()
.frame(width:UIScreen.main.bounds.size.width*0.9)
.cornerRadius(UIConstants.cardCornerRadius)
.padding([.horizontal])
}.tabViewStyle(PageTabViewStyle())
.background(Color.purple)
}
}
}
}
}
struct TextInfoView: View {
var body: some View {
VStack {
Text("Learn how to use SwiftUI to compose rich views out of simple ones, set up data flow, and build the navigation while watching it unfold in Xcode’s preview. Learn how to use SwiftUI to compose rich views out of simple ones, set up data flow, and build the navigation while watching it unfold in Xcode’s preview.Learn how to use SwiftUI to compose rich views out of simple ones, set up data flow, and build the navigation while watching it unfold in Xcode’s preview.Learn how to use SwiftUI to compose rich views out of simple ones, set up data flow, and build the navigation while watching it unfold in Xcode’s preview.Learn how to use SwiftUI to compose rich views out of simple ones, set up data flow, and build the navigation while watching it unfold in Xcode’s preview.Learn how to use SwiftUI to compose rich views out of simple ones, set up data flow, and build the navigation while watching it unfold in Xcode’s preview.").padding()
}
.background(Color.yellow)
}
}
struct ImageView: View {
var body: some View {
Image("Dummy")
.resizable()
.aspectRatio(contentMode: /*#START_MENU_TOKEN#*/.fill/*#END_MENU_TOKEN#*/)
.frame(height:UIScreen.main.bounds.size.height*0.7)
}
}
The results as follows:
A few issues here:
You can see that I tried to wrap the TextInfoView with a TabView as well. It is because if I do not enclose it in a TabView, it cannot align with the TabView with ImageView above. Any method to solve this issue?
At the top, the green area. Why there is such large padding around the text? How can I remove those extra green area? I want it to be tight at top and bottom.
If I do not add .frame() for the green area text, I found that the text gone, and cannot align to the left. Any method to solve this?
struct DetailViews: View {
var body: some View {
ZStack {
Color.green.edgesIgnoringSafeArea(.all)
ScrollView(.vertical, showsIndicators: false) {
VStack(spacing: 0) {
VStack{
Text("A long Text Title")
Text("A long Text Title")
Text("A long Text Title")
Text("A long Text Title")
}
.frame(maxWidth: .infinity)
.background(Color.yellow)
TabView {
ImageView()
.frame(width:UIScreen.main.bounds.size.width*0.9)
.cornerRadius(15)
ImageView()
.frame(width:UIScreen.main.bounds.size.width*0.9)
.cornerRadius(15)
ImageView()
.frame(width:UIScreen.main.bounds.size.width*0.9)
.cornerRadius(15)
}
.tabViewStyle(PageTabViewStyle())
.indexViewStyle(PageIndexViewStyle(backgroundDisplayMode: .always))
.background(Color.red)
TextInfoView()
.cornerRadius(15)
.padding()
.background(Color.blue)
TextInfoView()
.cornerRadius(15)
.padding()
.background(Color.purple)
}
}
}
}
}
struct TextInfoView: View {
var body: some View {
VStack {
Text("Learn how to use SwiftUI to compose rich views out of simple ones, set up data flow, and build the navigation while watching it unfold in Xcode’s preview. Learn how to use SwiftUI to compose rich views out of simple ones, set up data flow, and build the navigation while watching it unfold in Xcode’s preview.Learn how to use SwiftUI to compose rich views out of simple ones, set up data flow, and build the navigation while watching it unfold in Xcode’s preview.Learn how to use SwiftUI to compose rich views out of simple ones, set up data flow, and build the navigation while watching it unfold in Xcode’s preview.Learn how to use SwiftUI to compose rich views out of simple ones, set up data flow, and build the navigation while watching it unfold in Xcode’s preview.Learn how to use SwiftUI to compose rich views out of simple ones, set up data flow, and build the navigation while watching it unfold in Xcode’s preview.")
.fixedSize(horizontal: false, vertical: true).padding()//added
}
.background(Color.yellow)
}
}
I have a button and I'd like to put a semi-transparent gradient overlay on top of it.
Button(action: {
print("Pressed")
}) {
Text("Press me")
}
.overlay(
LinearGradient(
gradient: Gradient(colors: [.clear, Color.black.opacity(0.3)]),
startPoint: .top,
endPoint: .bottom
).disabled(true)
)
Even though the gradient has disabled(true) it still eats the touches and doesn't forward them to the actual button. .allowsHitTesting(false) provides the same result.
Any idea what can be wrong?
Note: I know I can put the overlay just to Text("Press me") but I don't want it. (This is just example code showcasing the problem)
Edit: This issue is solved in Xcode 11.2 ✅
The following code works on Xcode 11.2 / iOS 13.2
struct TestButtonWithOverlay: View {
var body: some View {
Button(action: {
print("Pressed")
}) {
Text("Press me")
.padding()
}
.overlay(
LinearGradient(
gradient: Gradient(colors: [.clear, Color.black.opacity(0.3)]),
startPoint: .top,
endPoint: .bottom
)
.allowsHitTesting(false) // !!! must be exactly here
)
}
}
When working with a ScrollView the correct fix is to use the .background content modifier on the ScrollView:
https://developer.apple.com/documentation/swiftui/form/background(alignment:content:)
It will as expected with your "background" appearing above the content of the ScrollView.
Example of using to create a shadow effect:
Interesting note: On the simulator .overlay works with a ScrollView, but on a physical device only .background allows scrolling.
The physical device is on iOS 14, and the simulator is iOS 15, so it's possible it might have been a regression. Although apparently this issue dates back further than either.