Positioning share sheet on VisionOS

I am trying to position the share sheet popped up by the shareLink API on VisionOS, but the share sheet is always anchored by at the label position.

I checked the Photos app is achieving this already, the share sheet there appears at very center of the window while the share button locates at the corner inside the menu.

How is this possible to make it?

Answered by Vision Pro Engineer in 806682022

Hi @nasufuu ,

The way that the share sheet looks on Photos, I'd create by doing this:

import SwiftUI
import UIKit

struct ContentView: View {
    @State private var url: URL = URL(string: "https://apple.com")!
    @State private var isSharePresented: Bool = false
    
    var body: some View {
        Button {
            isSharePresented.toggle()
        } label: {
            Label("share", systemImage: "square.and.arrow.up")
        }
        
        .sheet(isPresented: $isSharePresented, onDismiss: {
            print("Dismiss")
        }, content: {
            ActivityViewControllerRepresentable(activityItems: [url])
        })
    }
}

struct ActivityViewControllerRepresentable: UIViewControllerRepresentable {

    var activityItems: [Any]
    var applicationActivities: [UIActivity]? = nil
    
    func makeUIViewController(context: Context) -> some UIViewController {
        let controller = UIActivityViewController(activityItems: activityItems, applicationActivities: applicationActivities)
        return controller
    }
  

    func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {
        //
    }

}

Instead of using ShareLink, you can present a UIActivityViewController with the URL (or item) you want to share. This will give you the behavior you're looking for.

Best,

Sydney

Accepted Answer

Hi @nasufuu ,

The way that the share sheet looks on Photos, I'd create by doing this:

import SwiftUI
import UIKit

struct ContentView: View {
    @State private var url: URL = URL(string: "https://apple.com")!
    @State private var isSharePresented: Bool = false
    
    var body: some View {
        Button {
            isSharePresented.toggle()
        } label: {
            Label("share", systemImage: "square.and.arrow.up")
        }
        
        .sheet(isPresented: $isSharePresented, onDismiss: {
            print("Dismiss")
        }, content: {
            ActivityViewControllerRepresentable(activityItems: [url])
        })
    }
}

struct ActivityViewControllerRepresentable: UIViewControllerRepresentable {

    var activityItems: [Any]
    var applicationActivities: [UIActivity]? = nil
    
    func makeUIViewController(context: Context) -> some UIViewController {
        let controller = UIActivityViewController(activityItems: activityItems, applicationActivities: applicationActivities)
        return controller
    }
  

    func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {
        //
    }

}

Instead of using ShareLink, you can present a UIActivityViewController with the URL (or item) you want to share. This will give you the behavior you're looking for.

Best,

Sydney

Positioning share sheet on VisionOS
 
 
Q