SwiftUI - Dismiss sheet to another view - swift

I am trying to navigate to another View when sheet is dismissed, but not to the original
#State var showOnboarding: Bool = false
Button(action: {
self.showOnboarding.toggle()
}) {
Text("Click me")
}.sheet(isPresented: $showOnboarding) {
DiscoverView(showOnboarding: self.$showOnboarding)
}
My question: It is possible to put something like .onDissapear{ NewView() } ?

If I understood your question correctly you can use onDismiss to perform actions when a sheet is dismissed:
.sheet(isPresented: $showOnboarding, onDismiss: {
// on dismiss
// here you can set some variables for presenting another sheet or navigating to some other views
}) {
DiscoverView(showOnboarding: self.$showOnboarding)
}
You can present another View programmatically using a NavigationLink with an isActive parameter:
NavigationLink(destination: NewView(), isActive: $linkActive) {
EmptyView()
}
Summing up your code can look like this:
struct ContentView: View {
#State var showOnboarding: Bool = false
#State var linkActive: Bool = false
var body: some View {
NavigationView {
VStack {
Button(action: {
self.showOnboarding.toggle()
}) {
Text("Click me")
}
NavigationLink(destination: NewView(), isActive: $linkActive) {
EmptyView()
}
}
}.sheet(isPresented: $showOnboarding, onDismiss: {
self.linkActive = true
}) {
DiscoverView(showOnboarding: self.$showOnboarding)
}
}
}

Related

Button with NavigationLink and function call SwiftUI

I have an issue with NavigationLinks with conditions. It doesn't react what I'm expected. When a user click on the button the function "test" must be called and give a return value. If the return value is true the "SheetView" must be openend directly without clicking on the NavigationLink text. Please could someone give me a help on this one. Thanks in advance
I made a small (sample) program for showing the issue.
import SwiftUI
struct LoginView: View {
#State var check = false
#State var answer = false
var body: some View {
NavigationView {
VStack{
Text("it doesn't work")
Button(action: {
answer = test(value: 2)
if answer {
//if the return value is true then directly navigate to the sheetview
NavigationLink(
destination: SheetView(),
label: {
Text("Navigate")
})
}
}, label: {
Text("Calculate")
})
}
}
}
func test(value: Int) -> Bool {
if value == 1 {
check = false
} else {
print("Succes")
check = true
}
return check
}
}
struct SheetView: View {
var body: some View {
NavigationView {
VStack{
Text("Test")
.font(.title)
}
}
}
}
The answer from Yodagama works if you were trying to present a sheet (because you called your navigation destination SheetView), but if you were trying to navigate to SheetView instead of present a sheet, the following code would do that.
struct LoginView: View {
#State var check = false
#State var answer = false
var body: some View {
NavigationView {
VStack{
Text("it doesn't work")
NavigationLink(destination: SheetView(), isActive: $answer, label: {
Button(action: {
answer = test(value: 2)
}, label: {
Text("Calculate")
})
})
}
}
}
func test(value: Int) -> Bool {
if value == 1 {
check = false
} else {
print("Succes")
check = true
}
return check
}
}
struct SheetView: View {
var body: some View {
NavigationView {
VStack{
Text("Test")
.font(.title)
}
}
}
}
struct LoginView: View {
#State var check = false
#State var answer = false
var body: some View {
NavigationView {
VStack{
Text("it doesn't work")
Button(action: {
answer = test(value: 2)
//<= here
}, label: {
Text("Calculate")
})
}
.sheet(isPresented: $answer, content: { //<= here
SheetView()
})
}
}
...

SwiftUI: How can I change the Color of Alert Button and NavigationLink back button?

How can I change the Color from the Button in a Alert and the back Button from NavigationLink? To set .accentColor(.init("someColor")) after the Text from the Alert Button doesn't work. To set .accentColor(.init("someColor")) after navigationLink does not work too. What can I do?
The Alert Button:
The Back Button from NavigationLink:
struct ContentView: View {
#State var showSheet = false
#State var alertShouldBeShown = !UserDefaults.standard.bool(forKey: "£Start")
var body: some View {
Button(action: {
self.showSheet.toggle()
}) {
Text("click me")
//.accentColor(colorScheme == .dark ? Image("") : Image("Info-Icon"))
}.sheet(isPresented: $showSheet) {
SheetView(showSheet: self.$showSheet)
}
.alert(isPresented: $alertShouldBeShown, content: {
Alert(title: Text("Headline"),
message: Text("Text"),
dismissButton: Alert.Button.default(
Text("Ok"), action: {
UserDefaults.standard.set(true, forKey: "Start")
}
)
)
})
}
}
struct SheetView: View {
#Binding var showSheet: Bool
var body: some View {
NavigationView {
DetailView()
.navigationBarTitle(Text("Headline"), displayMode: .inline)
.navigationBarItems(trailing: Button(action: {
self.showSheet = false
}) {
Text("Done")
.bold()
})
}.navigationViewStyle(StackNavigationViewStyle())
}
}
struct DetailView: View {
var body: some View {
List {
HStack {
NavigationLink(destination: DetailViewOne()) {
Text("View 1")
}
}
HStack {
NavigationLink(destination: DetailViewTwo()) {
Text("View 2")
}
}
}
}
}
struct DetailViewOne: View {
var body: some View {
Text("1")
}
}
struct DetailViewTwo: View {
var body: some View {
Text("2")
}
}
You can change the NavigationBar accent color by using accentColor but you need to apply it to the SheetView (the root view of a given environment):
SheetView(showSheet: self.$showSheet)
.accentColor(.red)
Unfortunately SwiftUI doesn't allow much of Alert customisation so far.
However, as Alert is built on top of UIKit components (UIAlertController) this also means you can change the appearance of UIView when contained in UIAlertController.
You can put this code in your #main App init or in the SceneDelegate:
UIView.appearance(whenContainedInInstancesOf: [UIAlertController.self]).tintColor = .red

SwiftUI: How can I customize the sheet only for iPad?

I´m new in SwiftUI and I have the following problem. When I click the button on the iPhone the following comes up
but when I press the button on the iPad the following comes up
The picker is not on the whole sheet. How can I show the picker on the iPad on the whole sheet like on the iPhone?
struct ContentView: View {
#State var value_2 = 1
#State var show_1 = false
var body: some View {
VStack {
Button(action: {
self.show_1.toggle()
}) {
Text("Push")
}
.sheet(isPresented: $show_1) {
Sheet(show_0: self.$show_1, value_1: self.$value_2)
}
}
}
}
struct Sheet: View {
#Binding var show_0: Bool
#Binding var value_1: Int
var body: some View {
NavigationView {
number(value_0: $value_1)
.navigationBarTitle(Text("Enter number"), displayMode: .inline)
.navigationBarItems(trailing: Button(action: {
self.show_0 = false
}) {
Text("Done").bold()
})
}
}
}
struct number: View {
#Binding var value_0: Int
var body: some View {
Section {
Text("Headline")
Picker("",selection: $value_0)
{
ForEach(1..<101) { value in
Text("\(value)")
}
}
}
.labelsHidden()
}
}
As far as I understood your intention, you need just change a style of navigation view, like
var body: some View {
NavigationView {
number(value_0: $value_1)
.navigationBarTitle(Text("Enter number"), displayMode: .inline)
.navigationBarItems(trailing: Button(action: {
self.show_0 = false
}) {
Text("Done").bold()
})
}
.navigationViewStyle(StackNavigationViewStyle()) // << here !!
}

.onDisappear() method isn't triggered when clicking the NavigationLink, SwiftUI

NavigationView {
List{
ForEach(self.data.firebaseObj.lists, id: \.self) { item in
NavigationLink(
destination: DetailView(
list: item,
listIndex: self.data.firebaseObj.lists.firstIndex(of: item) ?? -1
).environmentObject(self.data)
){
Text(item.name)
}
}
.onDelete(perform: delete)
}
.navigationBarTitle(Text("Le liste").font(.largeTitle), displayMode: .inline)
.navigationBarItems(
leading: SignOutButton(),
trailing: Button(action: {
self.show_modal = true
}) {Image(systemName: "plus")}.sheet(isPresented: self.$show_modal) {
AddListForm(email: self.session.session!.email!).environmentObject(self.data)
})
}.onAppear(
perform:{
self.data.createList(username: self.session.session!.email!)
})
.onDisappear(
perform: {
self.data.listener.remove()
print("should be removed")
})
That's the code I have and, as written in the title, clicking on the NavigationLink doesn't trigger the .onDisappear() method. Instead, changing to another tab view works fine. Am I doing something wrong or is this just the way it is supposed to work? In the second case, is there a simple way to execute some code when clicking on a NavigationLink?
This is how it is supposed to work, because your DetailView is a subview of your MainView if you use NavigationLink. That is why your MainView isn't really disappearing programmatically speaking.
Nevertheless you can do it like this:
struct ContentView: View {
#State private var showDetailView = false
var body: some View {
NavigationView {
VStack {
NavigationLink(destination: DetailView(), isActive: $showDetailView) {
Button(action: {
print("should be removed")
self.showDetailView = true
}, label: {
Text("Listitem")
})
}
Spacer()
}.navigationBarTitle(Text("MainView"))
}
}
}
struct DetailView: View {
var body: some View {
Text("DetailView")
}
}

Button, how to open a new View in swiftUI embedded in navigation bar

I embedded a button on on the NavigationBar.
I'm try to make button to open a new View called DetailView
I try to use NavigationLink but it does't work inside a button.
import SwiftUI
struct ContentView: View {
#ObservedObject var dm: DataManager
#State var isAddPresented = false
var body: some View {
NavigationView {
HStack {
List () {
ForEach (dm.storage) { data in
StileCella(dm2: data)
}
}
.navigationBarTitle("Lista Rubrica")
.navigationBarItems(trailing: Button(action: {
self.isAddPresented = true
// Load here the DetailView??? How??
DetailView()
}) {
Text("Button")
})
}
}
}
}
struct DetailView: View {
var body: some View {
VStack(alignment: .center) {
Text("CIAO").bold()
Spacer()
Image(systemName: "star")
.resizable()
}
}
}
You just need to add a sheet modifier to your view, which presents your view depending on the value of isAddPresented, just like this:
struct ContentView: View {
#State var isAddPresented = false
var body: some View {
NavigationView {
List(dm.storage){ data in
StileCella(dm2: data)
}
.navigationBarTitle("Lista Rubrica")
.navigationBarItems(trailing: Button("Button") {
self.isAddPresented = true
})
} .sheet(isPresented: $isAddPresented,
onDismiss: { self.isAddPresented = false }) {
DetailView()
}
}
}
The important bit is to remember to set isAddPresented back to false in on dismiss to prevent it form presenting again.
If you want to open a new view just like we used to open through storyboard other than sheet, you can update the code in the following way:
import SwiftUI
struct ContentView: View {
#ObservedObject var dm: DataManager
#State var isAddPresented = false
var body: some View {
NavigationView {
HStack {
List () {
ForEach (dm.storage) { data in
StileCella(dm2: data)
}
}
.navigationBarTitle("Lista Rubrica")
.navigationBarItems(leading:
NavigationLink(destination: DetailView()) {
Text("Button")
})
}
}
}
}
struct DetailView: View {
var body: some View {
VStack(alignment: .center) {
Text("CIAO").bold()
Spacer()
Image(systemName: "star")
.resizable()
}
}
}
Instead of button, simply add NavigationLink inside navigationBarItems. This would do the trick! I wrote the complete for guidance but main change point is, I used
.navigationBarItems(leading:
NavigationLink(destination: DetailView()) {
Text("Button")
})
instead of:
.navigationBarItems(trailing: Button(action: {
self.isAddPresented = true
// Load here the DetailView??? How??
DetailView()
}) {
Text("Button")
})