解释:
如果不通过迭代所有子视图并覆盖按钮的动作和目标来将其组合在一起,就没有办法做到这一点。
一种干净的方法是创建自己的预览控制器,如下所示。如果您添加QLPreviewController
to UINavigationController
,它会自动创建一个bottom toolbar
您不想要的。要解决此问题,请将其添加为常规的子控制器UIViewController
并创建自定义导航栏。
您还可以使用UTI
来UIActivityItem
确定如何共享项目。我只实现了预览和基本的共享功能,但其余的应该非常容易做到,而且至少它比UIDocumentInteractionController
你完全控制一切更可定制。
现在对于执行所有这些的代码:
//
// ViewController.swift
// CustomDocumentController
//
// Created by brandon on 2022-01-13.
//
import UIKit
import QuickLook
import MobileCoreServices
import UniformTypeIdentifiers
private class PreviewItem: NSObject, QLPreviewItem {
var previewItemURL: URL?
var previewItemTitle: String?
init(title: String, url: URL) {
super.init()
previewItemURL = url
previewItemTitle = title
}
}
class DocumentInteractionController: UIViewController {
private let url: URL
private lazy var navigationBar: UINavigationBar = {
let navigationBar = UINavigationBar()
let navigationItem = UINavigationItem(title: name ?? "Document")
navigationItem.hidesBackButton = true
navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(onDone))
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .action, target: self, action: #selector(onShare)) //UIImage(systemName: "square.and.arrow.up")
navigationBar.pushItem(navigationItem, animated: false)
return navigationBar
}()
private lazy var previewController: QLPreviewController = {
let previewController = QLPreviewController()
previewController.title = name
previewController.dataSource = self
previewController.delegate = self
previewController.reloadData()
return previewController
}()
var uti: String? {
didSet {
previewController.reloadData()
}
}
var name: String? {
didSet {
previewController.title = name
navigationBar.topItem?.title = name
}
}
init(url: URL) {
self.url = url
super.init(nibName: nil, bundle: nil)
//super.init(rootViewController: self.previewController)
self.modalPresentationStyle = .fullScreen
name = (try? url.resourceValues(forKeys: [.localizedNameKey]))?.localizedName
uti = (try? url.resourceValues(forKeys: [.typeIdentifierKey]))?.typeIdentifier
if uti == nil {
if #available(iOS 15.0, *) {
uti = UTType.url.identifier
} else {
uti = String(kUTTypeURL)
}
}
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
addChild(previewController)
previewController.didMove(toParent: self)
let separator = UIView()
separator.backgroundColor = .lightGray
view.addSubview(navigationBar)
view.addSubview(separator)
view.addSubview(previewController.view)
NSLayoutConstraint.activate([
navigationBar.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
navigationBar.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
navigationBar.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
separator.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
separator.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
separator.topAnchor.constraint(equalTo: navigationBar.bottomAnchor),
separator.heightAnchor.constraint(equalToConstant: 1.0 / UIScreen.main.scale),
previewController.view.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
previewController.view.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
previewController.view.topAnchor.constraint(equalTo: separator.bottomAnchor),
previewController.view.bottomAnchor.constraint(equalTo: view.bottomAnchor)
])
[navigationBar, separator, previewController.view].forEach({
$0?.translatesAutoresizingMaskIntoConstraints = false
})
navigationBar.barTintColor = previewController.view.backgroundColor
view.backgroundColor = previewController.view.backgroundColor
}
}
extension DocumentInteractionController: QLPreviewControllerDelegate, QLPreviewControllerDataSource {
func numberOfPreviewItems(in controller: QLPreviewController) -> Int {
return 1
}
func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {
return PreviewItem(title: name ?? "Document", url: url)
}
}
extension DocumentInteractionController {
@objc
private func onDone() {
self.dismiss(animated: true, completion: nil)
}
@objc
private func onShare() {
let activityViewController = UIActivityViewController(activityItems: [url],
applicationActivities: nil)
activityViewController.excludedActivityTypes = [.assignToContact]
if UIDevice.current.userInterfaceIdiom == .pad {
activityViewController.popoverPresentationController?.sourceView = self.view
}
self.present(activityViewController, animated: true, completion: nil)
}
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let url = Bundle.main.url(forResource: "Testing", withExtension: ".md")
let doc = DocumentInteractionController(url: url!)
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
self.present(doc, animated: true, completion: nil)
}
}
}
截图: