Search code examples
swiftuipopover

SwiftUI: popover to persist (not be dismissed when tapped outside)


I created this popover:

import SwiftUI

struct Popover : View {
  @State var showingPopover = false

  var body: some View {

    Button(action: {
      self.showingPopover = true
    }) {
      Image(systemName: "square.stack.3d.up")
    }
    .popover(isPresented: $showingPopover){

    Rectangle()

      .frame(width: 500, height: 500)

    }
  }
}

struct Popover_Previews: PreviewProvider {
    static var previews: some View {
        Popover()
        .colorScheme(.dark)
        .previewDevice("iPad Pro (12.9-inch) (3rd generation)")
    }
}

enter image description here

Default behaviour is that is dismisses, once tapped outside.

Question: How can I set the popover to: - Persist (not be dismissed when tapped outside)? - Not block screen when active?


Solution

  • My solution to this problem doesn't involve spinning your own popover lookalike. Simply apply the .interactiveDismissDisabled() modifier to the parent content of the popover, as illustrated in the example below:

    import SwiftUI
    
    struct ContentView: View {
        @State private var presentingPopover = false
        @State private var count = 0
        
        var body: some View {
            VStack {
                Button {
                    presentingPopover.toggle()
                } label: {
                    Text("This view pops!")
                }.popover(isPresented: $presentingPopover) {
                    Text("Surprise!")
                        .padding()
                        .interactiveDismissDisabled()
                }.buttonStyle(.borderedProminent)
    
                Text("Count: \(count)")
                Button {
                    count += 1
                } label: {
                    Text("Doesn't block other buttons too!")
                }.buttonStyle(.borderedProminent)
            }
            .padding()
        }
    }
    

    Tested on iPadOS 16 (Xcode 14.1), demo video included below:

    Note: Although it looks like the buttons have lost focus, they are still interact-able, and might be a bug as such behaviour doesn't exist when running on macOS.