Swiftui - Navigation Bar Button Not Clickable After Sheet Has Been Presented

SwiftUI - Navigation bar button not clickable after sheet has been presented

I think this happens because the presentationMode is not inherited from the presenter view, so the presenter didn't know that the modal is already closed. You can fix this by adding presentationMode to presenter, in this case to ContentView.

struct ContentView: View {

@Environment(\.presentationMode) var presentation
@State var showSheet = false

var body: some View {
NavigationView {
VStack {
Text("Test")
}.sheet(isPresented: self.$showSheet) {
ModalView()
}.navigationBarItems(trailing:
Button(action: {
self.showSheet = true
}) {
Text("SecondView")
}
)
}
}
}

Tested on Xcode 12.5.

Here is the full working
example.

SwiftUI: Button in NavigationBar won't fire after modal dismissal

It is really a bug. The interesting thing is that after 'drag to dismiss' the issue is not observed, so it is a kind of 'sync/async' state changing or something.

Workaround (temporary of course, decreases visibility almost completely)

  .navigationBarItems(trailing: Button(action: { self.displayModal = true }) {
Text("Add").padding([.leading, .vertical], 4)
})

SwiftUI button in navigation bar only works once

It's a known bug related to navigation bar items and not relegated to just sheets, it seems to affect any modal, and I've encountered it in IB just the same when using modal segues.

Unfortunately this issue is still present in 11.3 build, hopefully they get this fixed soon.

SwiftUI Button not responding when added Padding to it

to be clear this is the code I'm using for testing:

    @main
struct TestApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}

struct ContactView: View {

@Binding var isContactViewActive: Bool
@State var searchBar = ""

var backgroundColor = Color(red: 14/255, green: 18/255, blue: 23/255, opacity: 1.0)

var body: some View {
NavigationView {
ZStack {
backgroundColor
VStack {
HStack {
Button(action: {print("magnifyingglass")}, label: {
Image(systemName: "magnifyingglass").font(.title)
})
Spacer()
Text("FireChat")
.font(.title)
.fontWeight(.light)
.foregroundColor(Color.white)
Spacer()
Button(action: {print("power")}, label: {
Image(systemName: "power").font(.title)
})
}.padding(.top, 50)
}
}.edgesIgnoringSafeArea(.all)
}
}
}

struct ContentView: View {
@State var isContactViewActive = false
var body: some View {
ContactView(isContactViewActive: $isContactViewActive)
}
}

SwiftUI - in sheet have a fixed continue button that is not scrollable

Here is a demo of possible approach (tuning & effects are out of scope - try to make demo code short). The idea is to inject UIView holder with button above sheet so it persist during sheet drag down (because as findings shown any dynamic offsets gives some ugly undesired shaking effects).

Tested with Xcode 12 / iOS 14

demo

            // ... your above code here

}//VStack for 3 criterias
.padding([.leading, .trailing], 20)

Spacer()

// button moved from here into below background view !!

}.background(BottomView(presentation: presentationMode) {
Button {
presentationMode.wrappedValue.dismiss()
UserDefaults.standard.set(true, forKey: "LaunchedBefore")
} label: {
Text("Continue")
.fontWeight(.medium)
.padding([.top, .bottom], 15)
.padding([.leading, .trailing], 90)
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(15)
}
})
//Main VStack
}
}

struct BottomView<Content: View>: UIViewRepresentable {
@Binding var presentationMode: PresentationMode
private var content: () -> Content

init(presentation: Binding<PresentationMode>, @ViewBuilder _ content: @escaping () -> Content) {
_presentationMode = presentation
self.content = content
}

func makeUIView(context: Context) -> UIView {
let view = UIView()

DispatchQueue.main.async {
if let window = view.window {
let holder = UIView()
context.coordinator.holder = holder

// simple demo background to make it visible
holder.layer.backgroundColor = UIColor.gray.withAlphaComponent(0.5).cgColor

holder.translatesAutoresizingMaskIntoConstraints = false

window.addSubview(holder)
holder.heightAnchor.constraint(equalToConstant: 140).isActive = true
holder.bottomAnchor.constraint(equalTo: window.bottomAnchor, constant: 0).isActive = true
holder.leadingAnchor.constraint(equalTo: window.leadingAnchor, constant: 0).isActive = true
holder.trailingAnchor.constraint(equalTo: window.trailingAnchor, constant: 0).isActive = true

if let contentView = UIHostingController(rootView: content()).view {
contentView.backgroundColor = UIColor.clear
contentView.translatesAutoresizingMaskIntoConstraints = false
holder.addSubview(contentView)

contentView.topAnchor.constraint(equalTo: holder.topAnchor, constant: 0).isActive = true
contentView.bottomAnchor.constraint(equalTo: holder.bottomAnchor, constant: 0).isActive = true
contentView.leadingAnchor.constraint(equalTo: holder.leadingAnchor, constant: 0).isActive = true
contentView.trailingAnchor.constraint(equalTo: holder.trailingAnchor, constant: 0).isActive = true
}
}
}
return view
}

func updateUIView(_ uiView: UIView, context: Context) {
if !presentationMode.isPresented {
context.coordinator.holder.removeFromSuperview()
}
}

func makeCoordinator() -> Coordinator {
Coordinator()
}

class Coordinator {
var holder: UIView!

deinit {
holder.removeFromSuperview()
}
}
}


Related Topics



Leave a reply



Submit