Workaround for UIHostingConfiguration requiring iOS 16
This commit is contained in:
parent
e0e9d4a185
commit
96fdef0558
@ -8,34 +8,7 @@
|
||||
import UIKit
|
||||
import SwiftUI
|
||||
|
||||
final class AttachmentCollectionViewCell: UICollectionViewCell {
|
||||
let attachmentView: UIView// & UIContentView
|
||||
|
||||
override init(frame: CGRect) {
|
||||
attachmentView = UIView()
|
||||
attachmentView.backgroundColor = .red
|
||||
// attachmentView = UIHostingConfiguration(content: {
|
||||
// AttachmentCollectionViewCellView(attachment: nil)
|
||||
// }).makeContentView()
|
||||
|
||||
super.init(frame: frame)
|
||||
|
||||
attachmentView.frame = bounds
|
||||
addSubview(attachmentView)
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
func updateUI(attachment: DraftAttachment) {
|
||||
// attachmentView.configuration = UIHostingConfiguration(content: {
|
||||
// AttachmentCollectionViewCellView(attachment: attachment)
|
||||
// }).margins(.all, .zero)
|
||||
}
|
||||
}
|
||||
|
||||
private struct AttachmentCollectionViewCellView: View {
|
||||
struct AttachmentCollectionViewCellView: View {
|
||||
let attachment: DraftAttachment?
|
||||
|
||||
var body: some View {
|
||||
@ -147,6 +120,21 @@ private struct SquareFrame: Layout {
|
||||
}
|
||||
}
|
||||
|
||||
#if !os(visionOS)
|
||||
@available(iOS, obsoleted: 16.0)
|
||||
private struct LegacySquareFrame<Content: View>: View {
|
||||
@ViewBuilder let content: Content
|
||||
|
||||
var body: some View {
|
||||
GeometryReader { proxy in
|
||||
let minDimension = min(proxy.size.width, proxy.size.height)
|
||||
content
|
||||
.frame(width: minDimension, height: minDimension, alignment: .center)
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
private extension View {
|
||||
@ViewBuilder
|
||||
func squareFrame() -> some View {
|
||||
@ -160,8 +148,10 @@ private extension View {
|
||||
self
|
||||
}
|
||||
} else {
|
||||
LegacySquareFrame {
|
||||
self
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ private class WrappedCollectionViewController: UIViewController {
|
||||
var draft: Draft!
|
||||
private var dataSource: UICollectionViewDiffableDataSource<Section, Item>!
|
||||
fileprivate var currentInteractiveMoveStartOffsetInCell: CGPoint?
|
||||
fileprivate var currentInteractiveMoveCell: AttachmentCollectionViewCell?
|
||||
fileprivate var currentInteractiveMoveCell: HostingCollectionViewCell?
|
||||
fileprivate var addAttachment: ((DraftAttachment) -> Void)? = nil
|
||||
|
||||
init(spacing: CGFloat, minItemSize: CGFloat) {
|
||||
@ -91,14 +91,11 @@ private class WrappedCollectionViewController: UIViewController {
|
||||
section.interGroupSpacing = spacing
|
||||
return section
|
||||
}
|
||||
let attachmentCell = UICollectionView.CellRegistration<AttachmentCollectionViewCell, DraftAttachment> { cell, indexPath, attachment in
|
||||
cell.updateUI(attachment: attachment)
|
||||
let attachmentCell = UICollectionView.CellRegistration<HostingCollectionViewCell, DraftAttachment> { cell, indexPath, attachment in
|
||||
cell.setView(AttachmentCollectionViewCellView(attachment: attachment))
|
||||
}
|
||||
let addButtonCell = UICollectionView.CellRegistration<UICollectionViewCell, Bool> { [unowned self] cell, indexPath, item in
|
||||
cell.contentView.backgroundColor = .blue
|
||||
// cell.contentConfiguration = UIHostingConfiguration(content: {
|
||||
// AddAttachmentButton(viewController: self, enabled: item)
|
||||
// }).margins(.all, .zero)
|
||||
let addButtonCell = UICollectionView.CellRegistration<HostingCollectionViewCell, Bool> { [unowned self] cell, indexPath, item in
|
||||
cell.setView(AddAttachmentButton(viewController: self, enabled: item))
|
||||
}
|
||||
let collectionView = IntrinsicContentSizeCollectionView(frame: .zero, collectionViewLayout: layout)
|
||||
self.view = collectionView
|
||||
@ -187,14 +184,14 @@ private class WrappedCollectionViewController: UIViewController {
|
||||
case .ended:
|
||||
collectionView.endInteractiveMovement()
|
||||
UIView.animate(withDuration: 0.2) {
|
||||
self.currentInteractiveMoveCell?.attachmentView.transform = .identity
|
||||
self.currentInteractiveMoveCell?.hostView?.transform = .identity
|
||||
}
|
||||
currentInteractiveMoveCell = nil
|
||||
currentInteractiveMoveStartOffsetInCell = nil
|
||||
case .cancelled:
|
||||
collectionView.cancelInteractiveMovement()
|
||||
UIView.animate(withDuration: 0.2) {
|
||||
self.currentInteractiveMoveCell?.attachmentView.transform = .identity
|
||||
self.currentInteractiveMoveCell?.hostView?.transform = .identity
|
||||
}
|
||||
currentInteractiveMoveCell = nil
|
||||
currentInteractiveMoveStartOffsetInCell = nil
|
||||
@ -218,17 +215,20 @@ extension WrappedCollectionViewController: UIGestureRecognizerDelegate {
|
||||
let collectionView = gestureRecognizer.view as! UICollectionView
|
||||
let location = gestureRecognizer.location(in: collectionView)
|
||||
guard let indexPath = collectionView.indexPathForItem(at: location),
|
||||
let cell = collectionView.cellForItem(at: indexPath) as? AttachmentCollectionViewCell else {
|
||||
let cell = collectionView.cellForItem(at: indexPath) as? HostingCollectionViewCell else {
|
||||
return false
|
||||
}
|
||||
guard collectionView.beginInteractiveMovementForItem(at: indexPath) else {
|
||||
return false
|
||||
}
|
||||
UIView.animate(withDuration: 0.2) {
|
||||
cell.attachmentView.transform = CGAffineTransform(scaleX: 1.2, y: 1.2)
|
||||
cell.hostView?.transform = CGAffineTransform(scaleX: 1.2, y: 1.2)
|
||||
}
|
||||
currentInteractiveMoveCell = cell
|
||||
currentInteractiveMoveStartOffsetInCell = gestureRecognizer.location(in: cell)
|
||||
currentInteractiveMoveStartOffsetInCell!.x -= cell.bounds.midX
|
||||
currentInteractiveMoveStartOffsetInCell!.y -= cell.bounds.midY
|
||||
return collectionView.beginInteractiveMovementForItem(at: indexPath)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@ -279,6 +279,62 @@ private final class IntrinsicContentSizeCollectionView: UICollectionView {
|
||||
}
|
||||
}
|
||||
|
||||
#if os(visionOS)
|
||||
private class HostingCollectionViewCell: UICollectionViewCell {
|
||||
private(set) var hostView: UIView?
|
||||
|
||||
func setView<V: View>(_ view: V) {
|
||||
let config = UIHostingConfiguration(content: {
|
||||
view
|
||||
}).margins(.all, 0)
|
||||
|
||||
if let hostView = hostView as? UIContentView {
|
||||
hostView.configuration = config
|
||||
} else {
|
||||
hostView = config.makeContentView()
|
||||
hostView!.frame = contentView.bounds
|
||||
contentView.addSubview(hostView!)
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
@available(iOS, obsoleted: 16.0)
|
||||
private class HostingCollectionViewCell: UICollectionViewCell {
|
||||
@available(iOS, obsoleted: 16.0)
|
||||
private var hostController: UIHostingController<AnyView>?
|
||||
private(set) var hostView: UIView?
|
||||
|
||||
func setView<V: View>(_ view: V) {
|
||||
if #available(iOS 16.0, *) {
|
||||
let config = UIHostingConfiguration(content: {
|
||||
view
|
||||
}).margins(.all, 0)
|
||||
|
||||
// We don't just use the cell's contentConfiguration property because we need to animate
|
||||
// the size of the host view, and when the host view is the contentView, that doesn't work.
|
||||
if let hostView = hostView as? UIContentView {
|
||||
hostView.configuration = config
|
||||
} else {
|
||||
hostView = config.makeContentView()
|
||||
hostView!.frame = contentView.bounds
|
||||
contentView.addSubview(hostView!)
|
||||
}
|
||||
} else {
|
||||
if let hostController {
|
||||
hostController.rootView = AnyView(view)
|
||||
} else {
|
||||
let host = UIHostingController(rootView: AnyView(view))
|
||||
host.view.frame = contentView.bounds
|
||||
contentView.addSubview(host.view)
|
||||
hostController = host
|
||||
hostView = host.view
|
||||
// drop the hosting controller on the floor and hope nothing bad happens
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
private struct AddAttachmentButton: View {
|
||||
unowned let viewController: WrappedCollectionViewController
|
||||
let enabled: Bool
|
||||
@ -308,7 +364,7 @@ private struct AddAttachmentButton: View {
|
||||
}
|
||||
}
|
||||
} label: {
|
||||
Image(systemName: "photo.badge.plus")
|
||||
Image(systemName: iconName)
|
||||
.imageScale(.large)
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
.background {
|
||||
@ -321,6 +377,14 @@ private struct AddAttachmentButton: View {
|
||||
}
|
||||
.disabled(!enabled)
|
||||
}
|
||||
|
||||
private var iconName: String {
|
||||
if #available(iOS 17.0, *) {
|
||||
"photo.badge.plus"
|
||||
} else {
|
||||
"photo"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct AddAttachmentConditionsModifier: ViewModifier {
|
||||
|
Loading…
x
Reference in New Issue
Block a user