SwiftUI • 如何实现半屏 ShareSheet? [英] SwiftUI • How to implement half-Screen ShareSheet?

查看:64
本文介绍了SwiftUI • 如何实现半屏 ShareSheet?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用 UIViewControllerRepresentable 在我的 SwiftUI 应用程序 中实现了一个 ShareSheet.

I implemented a ShareSheet into my SwiftUI App using UIViewControllerRepresentable.

代码

struct ShareView: UIViewControllerRepresentable {
    typealias Callback = (_ activityType: UIActivity.ActivityType?, _ completed: Bool, _ returnedItems: [Any]?, _ error: Error?) -> Void
    
    let activityItems: [Any] = ["Some Text"]
    let applicationActivities: [UIActivity]? = nil
    let excludedActivityTypes: [UIActivity.ActivityType]? = nil
    let callback: Callback? = nil
    
    func makeUIViewController(context: Context) -> UIActivityViewController {
        let controller = UIActivityViewController(activityItems: activityItems, applicationActivities: applicationActivities)
        controller.excludedActivityTypes = excludedActivityTypes
        controller.completionWithItemsHandler = callback
        return controller
    }
    
    func updateUIViewController(_ uiViewController: UIActivityViewController, context: Context) {
        // ...
    }
}

// Presentation
View()
    .sheet(isPresented: $showShareSheet) {
        ShareView()
    }


问题:这很好用,但是 Share Sheet 总是覆盖整个屏幕.我在其他应用程序中看到 Share Sheets 只覆盖屏幕的下半部分.我怎样才能做到这一点?


Problem: This works great, however the Share Sheet always cover the entire Screen. I've seen Share Sheets in other Apps that only cover the bottom half of the Screen. How can I achieve this?

推荐答案

您可以创建Empty View Controller来呈现工作表

You can create the Empty View Controller to present the sheet

struct ShareSheet: UIViewControllerRepresentable {
  // To setup the share sheet
  struct Config {
    let activityItems: [Any]
    var applicationActivities: [UIActivity]?
    var excludedActivityTypes: [UIActivity.ActivityType]?
  }

  // Result object
  struct Result {
    let error: Error?
    let activityType: UIActivity.ActivityType?
    let completed: Bool
    let returnedItems: [Any]?
  }

  @Binding var isPresented: Bool

  private var handler: ((Result) -> Void)?
  private let shareSheet: UIActivityViewController

  init(
    isPresented: Binding<Bool>,
    config: Config,
    onEnd: ((Result) -> Void)? = nil
  ) {
    self._isPresented = isPresented
    shareSheet = UIActivityViewController(
      activityItems: config.activityItems,
      applicationActivities: config.applicationActivities
    )
    shareSheet.excludedActivityTypes = config.excludedActivityTypes
    shareSheet.completionWithItemsHandler = { activityType, completed, returnedItems, error in
      onEnd?(
        .init(
          error: error,
          activityType: activityType,
          completed: completed,
          returnedItems: returnedItems
        )
      )
      // Set isPresented to false after complete
      isPresented.wrappedValue = false
    }
  }

  func makeUIViewController(context: Context) -> UIViewController {
    UIViewController()
  }

  func updateUIViewController(
    _ uiViewController: UIViewController,
    context: Context
  ) {
    if isPresented, shareSheet.view.window == nil {
      uiViewController.present(shareSheet, animated: true, completion: nil)
    } else if !isPresented, shareSheet.view.window != nil {
      shareSheet.dismiss(animated: true)
    }
  }
}

您也可以在视图扩展中创建运算符

You can also create the operator in the view extension

extension View {
  func shareSheet(
    isPresented: Binding<Bool>,
    config: ShareSheet.Config,
    onEnd: ((ShareSheet.Result) -> Void)? = nil
  ) -> some View {
    self.background(
      ShareSheet(isPresented: isPresented, config: config, onEnd: onEnd)
    )
  }
}

这篇关于SwiftUI • 如何实现半屏 ShareSheet?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆