struct GridView<CellView: View>: UIViewRepresentable {
let cellView: (Int) -> CellView
let proxy: GeometryProxy
var numbers: [Int]
init(_ numbers: [Int], proxy: GeometryProxy, @ViewBuilder cellView: @escaping (Int) -> CellView) {
self.proxy = proxy
self.cellView = cellView
self.numbers = numbers
}
func makeUIView(context: Context) -> UICollectionView {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .vertical
layout.minimumLineSpacing = 20
layout.minimumInteritemSpacing = 10
layout.itemSize = CGSize(width: 234, height: 240)
let collectionView = UICollectionView(frame: proxy.frame(in: .global), collectionViewLayout: layout)
collectionView.backgroundColor = bcBodyBackUIColor
collectionView.register(GridCellView.self, forCellWithReuseIdentifier: "CELL")
collectionView.dragInteractionEnabled = true
collectionView.dataSource = context.coordinator
collectionView.delegate = context.coordinator
collectionView.contentInset = UIEdgeInsets(top: 28, left: 28, bottom: 28, right: 28)
return collectionView
}
func updateUIView(_ uiView: UICollectionView, context: Context) {
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
class Coordinator: NSObject, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
var parent: GridView
var collectionView: UICollectionView?
init(_ parent: GridView) {
self.parent = parent
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
self.collectionView = collectionView
return parent.numbers.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CELL", for: indexPath) as! GridCellView
cell.layer.backgroundColor = bcBodyBackUIColor.cgColor
cell.backgroundColor = .clear
cell.cellView.rootView = AnyView(parent.cellView(parent.numbers[indexPath.row]).fixedSize())
let tap = UILongPressGestureRecognizer(target: self, action: #selector(delectBtn(_:)))
tap.minimumPressDuration = 0.1
cell.addGestureRecognizer(tap)
return cell
}
@objc func delectBtn(_ sender: UILongPressGestureRecognizer) {
switch sender.state {
case .began:
let selectedCellIndex = self.collectionView!.indexPathForItem(at: sender.location(in: collectionView))
self.collectionView!.beginInteractiveMovementForItem(at: selectedCellIndex!)
case .changed:
self.collectionView!.updateInteractiveMovementTargetPosition(sender.location(in: collectionView))
case .ended:
self.collectionView!.endInteractiveMovement()
default:
self.collectionView!.cancelInteractiveMovement()
}
}
func collectionView(_ collectionView: UICollectionView, moveItemAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
let tempMybook = self.parent.numbers[sourceIndexPath.item]
self.parent.numbers.remove(at: sourceIndexPath.item)
self.parent.numbers.insert(tempMybook, at: destinationIndexPath.item)
}
}
}
class GridCellView: UICollectionViewCell {
public var cellView = UIHostingController(rootView: AnyView(EmptyView()))
public override init(frame: CGRect) {
super.init(frame: frame)
configure()
}
public required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
configure()
}
private func configure() {
contentView.addSubview(cellView.view)
cellView.view.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
cellView.view.leftAnchor.constraint(equalTo: contentView.leftAnchor),
cellView.view.rightAnchor.constraint(equalTo: contentView.rightAnchor),
cellView.view.topAnchor.constraint(equalTo: contentView.topAnchor),
cellView.view.bottomAnchor.constraint(equalTo: contentView.bottomAnchor)
])
cellView.view.layer.masksToBounds = true
cellView.view.layer.backgroundColor = bcBodyBackUIColor.cgColor
}
}
struct MyView: View {
var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]
var body: some View {
GeometryReader { proxy in
GridView(self.numbers, proxy: proxy) { number in
Text(String(number))
}
}.frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height - 150)
}
}