简体   繁体   中英

SwiftUI: Weird dismiss animation on iPad popover

When I create a popover on my iPad and start using split screen mode, the popover automatically transforms into a sheet. But unfortunately it is only dismissable with a weird kind of animation.

在此处输入图像描述

I don't think that apple wants developers to just deal with this weird behaviour since using split screen is a nice feature to use. Also there are popovers in apps such as the appstore where you can open popovers which transform to nice dismissable sheets in smaller screenclasses.

I already tried to handle the problem with conditional modifiers which apply when the screensize is either.regular oder.compact and assign either a sheet or a popover with

extension View {
    @ViewBuilder
    func `if`<Content: View>(_ condition: Bool, content: (Self) -> Content) -> some View {
        if condition {
            content(self)
        } else {
            self
        }
    }
}

but unfortunately I can't predictably controll the popoverIsShown state anymore when modifiers are closed and opened by the sizeClass.

Is there any other suitable workaround for this issue?

Thanks in advance.

So I figured out a solution that works really fine for myself. It may help people facing the same problem someday.

  1. Define sizeclasses and the presentation state in your main view
@Environment(\.horizontalSizeClass) var horizontalSizeClass
@State var ispresent = true
  1. Write own modifier which assigns either a sheet or a popover to your main view depending on the given sizeclass
struct PopoverSheet: ViewModifier {
    var size: UserInterfaceSizeClass?
    @Binding var isPresented:Bool
    var sheetContent: AnyView
    
    func body(content: Content) -> some View {
        VStack {
            if size == .compact {
                content
                    .sheet(isPresented: self.$isPresented){
                        self.sheetContent
                    }
            } else {
                content
                    .popover(isPresented: self.$isPresented){
                        self.sheetContent
                    }
            }
        }
    }
}
  1. Extend the View Class so that you can easily add the modifier to your main view
extension View {
    func popoverSheet(sizeClass: UserInterfaceSizeClass?, isPresented: Binding<Bool>, sheetContent: AnyView) -> some View {
        modifier(PopoverSheet(size: sizeClass, isPresented: isPresented, sheetContent: sheetContent))
    }
}
  1. Simply add the modifier to your main view
    var body: some View {
        VStack {
            Button(action: {
                self.ispresent = false
                // NEED TO RETOGGLE THE SHEET AFTER CHANGING SIZECLASSES
                DispatchQueue.main.asyncAfter(deadline: .now() + 0.1){
                    self.ispresent.toggle()
                }
            }){
                Text("Toggle Popover")
            }
            .popoverSheet(sizeClass: horizontalSizeClass,
                          isPresented: self.$ispresent,
                          sheetContent: AnyView(ThePopoverView(content: "Popover Content with any arguments")))
        }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM