NCViewerImageCollectionViewCell.swift 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. import UIKit
  2. protocol NCViewerImageCollectionViewCellDelegate: class {
  3. func didStartZooming(_ cell: NCViewerImageCollectionViewCell)
  4. }
  5. class NCViewerImageCollectionViewCell: UICollectionViewCell {
  6. static var reusableIdentifier: String = "NCViewerImageCollectionViewCell"
  7. private var dataTask: URLSessionDataTask?
  8. weak var delegate: NCViewerImageCollectionViewCellDelegate?
  9. @IBOutlet weak var imageWidthConstraint: NSLayoutConstraint!
  10. @IBOutlet weak var imageHeightConstraint: NSLayoutConstraint!
  11. @IBOutlet weak var topConstraint: NSLayoutConstraint!
  12. @IBOutlet weak var bottomConstraint: NSLayoutConstraint!
  13. @IBOutlet weak var scrollView: UIScrollView!
  14. @IBOutlet weak var galleryImageView: UIImageView!
  15. @IBOutlet weak var leadingConstraint: NSLayoutConstraint!
  16. @IBOutlet weak var trailingConstraint: NSLayoutConstraint!
  17. private var observer: NSKeyValueObservation?
  18. func withImageAsset(_ asset: NCViewerImageAsset?) {
  19. guard self.dataTask?.state != URLSessionDataTask.State.running else { return }
  20. guard let asset = asset else { return }
  21. let imagePath = CCUtility.getDirectoryProviderStorageOcId(asset.metadata!.ocId, fileNameView: asset.metadata!.fileNameView)!
  22. if let image = UIImage(contentsOfFile: imagePath) {
  23. self.apply(image: self.fitIntoFrame(image: image, type: asset.type))
  24. } else if asset.url != nil {
  25. self.galleryImageView.image = nil
  26. self.dataTask = asset.download(completion: { _ in
  27. //self.apply(image: self.fitIntoFrame(image: asset.image, type: asset.type))
  28. })
  29. }
  30. }
  31. func apply(image: UIImage?) {
  32. guard let image = image else { return }
  33. self.galleryImageView.alpha = 0
  34. self.galleryImageView.image = image
  35. UIView.animate(withDuration: 0.1) {
  36. self.galleryImageView.alpha = 1
  37. }
  38. }
  39. override func draw(_ rect: CGRect) {
  40. super.draw(rect)
  41. self.scrollView.maximumZoomScale = 4
  42. self.redrawConstraintIfNeeded()
  43. self.observer = self.observe(\.bounds, options: NSKeyValueObservingOptions.new, changeHandler: { (_, _) in
  44. self.apply(image: self.fitIntoFrame(image: self.galleryImageView.image, type: nil))
  45. self.redrawConstraintIfNeeded()
  46. })
  47. }
  48. func cancelPendingDataTask() {
  49. self.dataTask?.cancel()
  50. }
  51. override func layoutSubviews() {
  52. DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
  53. self.redrawConstraintIfNeeded()
  54. }
  55. super.layoutSubviews()
  56. }
  57. override func prepareForReuse() {
  58. super.prepareForReuse()
  59. self.scrollView.setZoomScale(1, animated: false)
  60. DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
  61. // limitation of cell lifecycle
  62. self.redrawConstraintIfNeeded()
  63. }
  64. }
  65. func setMargins(vertical: CGFloat, horizontal: CGFloat) {
  66. self.topConstraint.constant = vertical
  67. self.bottomConstraint.constant = vertical
  68. self.leadingConstraint.constant = horizontal
  69. self.trailingConstraint.constant = horizontal
  70. }
  71. func redrawConstraintIfNeeded() {
  72. let imageHeight = self.galleryImageView.frame.size.height
  73. let imageWidth = self.galleryImageView.frame.size.width
  74. let spaceLeftVertical = self.scrollView.frame.size.height-imageHeight
  75. let spaceLeftHorizontal = self.scrollView.frame.size.width-imageWidth
  76. let constraintConstantValueVertical = spaceLeftVertical/2 > 0 ? spaceLeftVertical/2 : 0
  77. let constraintConstantValueHorizontal = spaceLeftHorizontal/2 > 0 ? spaceLeftHorizontal/2 : 0
  78. self.setMargins(vertical: constraintConstantValueVertical, horizontal: constraintConstantValueHorizontal)
  79. self.layoutIfNeeded()
  80. }
  81. private func fitIntoFrame(image: UIImage?, type: NCViewerImageAsset.ImageType?) -> UIImage? {
  82. let type: NCViewerImageAsset.ImageType = type ?? .jpg
  83. guard let image = image else { return nil }
  84. guard image.size != CGSize.zero else { return nil }
  85. let screenRatio = UIScreen.main.bounds.size.width/UIScreen.main.bounds.size.height
  86. var reqWidth: CGFloat = frame.size.width
  87. if image.size.width > reqWidth {
  88. reqWidth = image.size.width
  89. }
  90. let imageRatio = image.size.width/image.size.height
  91. if imageRatio < screenRatio {
  92. reqWidth = frame.size.height*imageRatio
  93. }
  94. let size = CGSize(width: reqWidth, height: reqWidth/imageRatio)
  95. if imageRatio < screenRatio {
  96. self.imageHeightConstraint.constant = frame.size.height
  97. self.imageWidthConstraint.constant = frame.size.height*imageRatio
  98. } else {
  99. self.imageHeightConstraint.constant = frame.size.width/imageRatio
  100. self.imageWidthConstraint.constant = frame.size.width
  101. }
  102. switch type {
  103. case .gif: return image
  104. case .jpg:
  105. UIGraphicsBeginImageContext(size)
  106. image.draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
  107. let finalImage: UIImage? = UIGraphicsGetImageFromCurrentImageContext()
  108. UIGraphicsEndImageContext()
  109. return finalImage
  110. }
  111. }
  112. func redrawImage() {
  113. self.apply(image: self.fitIntoFrame(image: self.galleryImageView.image, type: nil))
  114. self.redrawConstraintIfNeeded()
  115. }
  116. }
  117. extension NCViewerImageCollectionViewCell: UIScrollViewDelegate {
  118. func viewForZooming(in scrollView: UIScrollView) -> UIView? {
  119. return self.galleryImageView
  120. }
  121. func scrollViewWillBeginZooming(_ scrollView: UIScrollView, with view: UIView?) {
  122. self.delegate?.didStartZooming(self)
  123. }
  124. func scrollViewDidZoom(_ scrollView: UIScrollView) {
  125. self.redrawConstraintIfNeeded()
  126. }
  127. }