NCViewerImageCollectionViewCell.swift 6.0 KB

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