Essentially I would like to trigger the MainButton
in ContentView
to Open SheetView
and then use NavCloseButton
to Close the SheetView
to Return Back to ContentView
. I've been trying to do this using @State
and @Binding
. While getting SheetView
presented using .sheet(isPresented:
is simple I'm having trouble dismissing it when the buttons are extracted out.
Can someone please show example how these actions would be performed?
ContentView:
struct ContentView: View {
var body: some View {
NavigationView {
VStack {
Spacer()
Image(systemName: "hand.thumbsup.circle.fill")
.resizable()
.frame(width: 200, height: 200)
.symbolRenderingMode(.hierarchical)
Spacer()
MainButton(color: .blue, title: "Tap to Open", image: "lock.open.laptopcomputer")
}
.navigationTitle("Page One")
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
.preferredColorScheme(.dark)
}
}
SheetView:
struct SheetView: View {
var body: some View {
NavigationView {
VStack {
Text("Hello, World!")
}
.navigationTitle("Sheet View")
.navigationBarItems(trailing: NavCloseButton(color: .red,
title: "Close",
image: ""))
}
}
}
struct SheetView_Previews: PreviewProvider {
static var previews: some View {
SheetView()
.preferredColorScheme(.dark)
}
}
AppButtons:
struct NavCloseButton: View {
var color: Color
var title: String
var image: String
var body: some View {
Button {
print("Closing")
} label: {
Text(title)
.padding()
.frame(width: 100, height: 40)
.background(color)
.foregroundColor(.white)
.cornerRadius(10)
.font(.system(.body))
}
}
}
struct MainButton: View {
var color: Color
var title: String
var image: String
var body: some View {
Button {
print("Opened")
} label: {
Label {
Text(title)
} icon: {
Image(systemName: image)
}
.padding()
.frame(width: 350, height: 60)
.background(color)
.foregroundColor(.white)
.cornerRadius(15)
.font(.title2)
}
}
}
CodePudding user response:
Following your code this is how you would do it.
Changes are commented.
struct ContentView: View {
@State private var showSheet = false // define state
var body: some View {
NavigationView {
VStack {
Spacer()
Image(systemName: "hand.thumbsup.circle.fill")
.resizable()
.frame(width: 200, height: 200)
.symbolRenderingMode(.hierarchical)
Spacer()
MainButton(color: .blue, title: "Tap to Open", image: "lock.open.laptopcomputer", showSheet: $showSheet) // pass binding
}
.navigationTitle("Page One")
.sheet(isPresented: $showSheet) { // present sheet
SheetView(showSheet: $showSheet) // pass binding
}
}
}
}
struct SheetView: View {
@Binding var showSheet: Bool // pass binding here
var body: some View {
NavigationView {
VStack {
Text("Hello, World!")
}
.navigationTitle("Sheet View")
.navigationBarItems(
trailing:
NavCloseButton(color: .red,
title: "Close",
image: "",
showSheet: $showSheet)) // pass binding
}
}
}
struct NavCloseButton: View {
var color: Color
var title: String
var image: String
@Binding var showSheet: Bool // pass binding here
var body: some View {
Button {
print("Closing")
showSheet = false // set binding to dismiss sheet
} label: {
Text(title)
.padding()
.frame(width: 100, height: 40)
.background(color)
.foregroundColor(.white)
.cornerRadius(10)
.font(.system(.body))
}
}
}
struct MainButton: View {
var color: Color
var title: String
var image: String
@Binding var showSheet: Bool // pass binding here
var body: some View {
Button {
print("Opened")
showSheet = true // set binding to show sheet
} label: {
Label {
Text(title)
} icon: {
Image(systemName: image)
}
.padding()
.frame(width: 350, height: 60)
.background(color)
.foregroundColor(.white)
.cornerRadius(15)
.font(.title2)
}
}
}
But it might be easier to change the buttons to vars or define custom Button styles.
Here is another variant with one CutomButton that is taking a button action as a closure, reducing the Binding passing around:
struct ContentView: View {
@State private var showSheet = false // define state
var body: some View {
NavigationView {
VStack {
Spacer()
Image(systemName: "hand.thumbsup.circle.fill")
.resizable()
.frame(width: 200, height: 200)
.symbolRenderingMode(.hierarchical)
Spacer()
CustomButton(color: .blue, title: "Tap to Open", image: "lock.open.laptopcomputer") {
showSheet = true // passed button action
}
.font(.title2)
}
.navigationTitle("Page One")
.sheet(isPresented: $showSheet) { // present sheet
SheetView(showSheet: $showSheet) // pass binding
}
}
}
}
struct SheetView: View {
@Binding var showSheet: Bool // pass binding here
var body: some View {
NavigationView {
VStack {
Text("Hello, World!")
}
.navigationTitle("Sheet View")
.navigationBarItems(
trailing:
CustomButton(color: .red, title: "Close") {
showSheet = false // passed button action
}
)
}
}
}
struct CustomButton: View {
let color: Color
let title: String
var image: String? = nil
let action: () -> Void // button action (as trailing closure)
var body: some View {
Button {
action() // run the passed action
} label: {
Group {
if let image {
Label(title, systemImage: image)
} else {
Text(title)
}
}
.padding()
.background(color)
.foregroundColor(.white)
.cornerRadius(15)
}
}
}