added iOS source code
[wl-app.git] / iOS / WolneLektury / Screens / NewsDetails / Gallery / Cells / GalleryCell.swift
1 //
2 //  GalleryCell.swift
3 //  WolneLektury
4 //
5 //  Created by Pawel Dabrowski on 17/09/2018.
6 //  Copyright © 2018 Fundacja Nowoczesna Polska. All rights reserved.
7 //
8
9 import UIKit
10 import Kingfisher
11 import MBProgressHUD
12
13 public class GalleryCell: UICollectionViewCell {
14     
15     var url: String?{
16         didSet {
17             configureForNewImageUrl()
18         }
19     }
20     
21     private var scrollView: UIScrollView
22     fileprivate let imageView: UIImageView
23     var progressHud: MBProgressHUD?
24     
25     func setScrollEnabled(scrollEnabled: Bool){
26         scrollView.isUserInteractionEnabled = scrollEnabled
27         if !scrollEnabled{
28             setZoomScale()
29         }
30     }
31     
32     override init(frame: CGRect) {
33         
34         imageView = UIImageView()
35         imageView.translatesAutoresizingMaskIntoConstraints = false
36         scrollView = UIScrollView(frame: frame)
37         scrollView.translatesAutoresizingMaskIntoConstraints = false
38         scrollView.backgroundColor = Constants.Colors.darkGreenBgColor()
39         super.init(frame: frame)
40         
41         var scrollViewConstraints: [NSLayoutConstraint] = []
42         var imageViewConstraints: [NSLayoutConstraint] = []
43         
44         scrollViewConstraints.append(NSLayoutConstraint(item: scrollView, attribute: .leading, relatedBy: .equal, toItem: contentView, attribute: .leading, multiplier: 1, constant: 0))
45         scrollViewConstraints.append(NSLayoutConstraint(item: scrollView, attribute: .top, relatedBy: .equal, toItem: contentView, attribute: .top, multiplier: 1, constant: 0))
46         scrollViewConstraints.append(NSLayoutConstraint(item: scrollView, attribute: .trailing, relatedBy: .equal, toItem: contentView, attribute: .trailing, multiplier: 1, constant: 0))
47         scrollViewConstraints.append(NSLayoutConstraint(item: scrollView, attribute: .bottom, relatedBy: .equal, toItem: contentView, attribute: .bottom, multiplier: 1, constant: 0))
48         contentView.addSubview(scrollView)
49         contentView.addConstraints(scrollViewConstraints)
50         
51         imageViewConstraints.append(NSLayoutConstraint(item: imageView, attribute: .leading, relatedBy: .equal, toItem: scrollView, attribute: .leading, multiplier: 1, constant: 0))
52         imageViewConstraints.append(NSLayoutConstraint(item: imageView, attribute: .top, relatedBy: .equal, toItem: scrollView, attribute: .top, multiplier: 1, constant: 0))
53         imageViewConstraints.append(NSLayoutConstraint(item: imageView, attribute: .trailing, relatedBy: .equal, toItem: scrollView, attribute: .trailing, multiplier: 1, constant: 0))
54         imageViewConstraints.append(NSLayoutConstraint(item: imageView, attribute: .bottom, relatedBy: .equal, toItem: scrollView, attribute: .bottom, multiplier: 1, constant: 0))
55         scrollView.addSubview(imageView)
56         scrollView.addConstraints(imageViewConstraints)
57
58         scrollView.delegate = self
59         
60         let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(tapGestureRecognizerAction(recognizer:)))
61         tapGestureRecognizer.numberOfTapsRequired = 2
62         self.addGestureRecognizer(tapGestureRecognizer)
63     }
64     
65     @objc public func tapGestureRecognizerAction(recognizer: UITapGestureRecognizer) {
66         if (scrollView.zoomScale > scrollView.minimumZoomScale) {
67             scrollView.setZoomScale(scrollView.minimumZoomScale, animated: true)
68         } else {
69             scrollView.setZoomScale(scrollView.maximumZoomScale, animated: true)
70         }
71     }
72
73     required public init?(coder aDecoder: NSCoder) {
74         fatalError("init(coder:) has not been implemented")
75     }
76
77     public func configureForNewImageUrl() {
78         
79         guard let imageUrl = url?.getPhotoUrl() else{
80             self.setupImage(image: nil)
81             return
82         }
83         
84         if progressHud == nil{
85             progressHud = MBProgressHUD.showAdded(to: contentView, animated: true)
86             progressHud?.label.text = "loading".localized
87         }
88         else{
89             progressHud?.show(animated: true)
90         }
91         
92         //        let freeSpace = contentView.bounds.size.height - textContainerHeight
93         let contentOffsetY = ((contentView.bounds.size.height/2 /*- freeSpace/2*/) * -1)
94         progressHud!.offset.y = contentOffsetY
95         
96         KingfisherManager.shared.retrieveImage(with: ImageResource(downloadURL: imageUrl), options: nil, progressBlock: nil) { (image, error, cacheType, url) in
97             self.progressHud?.hide(animated: true)
98             self.setupImage(image: image)
99         }
100     }
101
102     
103     // ############################################
104     // MARK: - Private
105     // ############################################
106     
107     private func setupImage(image: UIImage?){
108         imageView.image = image
109         imageView.sizeToFit()
110         imageView.alpha = 0.0
111         
112         setZoomScale()
113         scrollViewDidZoom(scrollView)
114         
115         UIView.animate(withDuration: 0.5) {
116             self.imageView.alpha = 1.0
117         }
118     }
119     
120     private func setZoomScale() {
121         
122         let imageViewSize = imageView.bounds.size
123         
124         guard imageViewSize.width > 0 && imageViewSize.height > 0 else {
125             return
126         }
127         
128         let scrollViewSize =  UIScreen.main.bounds.size// scrollView.bounds.size
129         let widthScale = scrollViewSize.width / imageViewSize.width
130         let heightScale = scrollViewSize.height / imageViewSize.height
131         let miminumZoomScale = min(widthScale, heightScale)
132         scrollView.minimumZoomScale = miminumZoomScale
133         
134         let initialZoomScale = max(widthScale, heightScale)
135         
136         scrollView.maximumZoomScale = initialZoomScale * 1.5
137         
138         scrollView.setZoomScale(miminumZoomScale, animated: false)
139         
140         let newContentOffsetX = (scrollView.contentSize.width/2) - (scrollView.bounds.size.width/2);
141         
142         scrollView.contentOffset = CGPoint(x: newContentOffsetX, y: scrollView.contentOffset.y)
143     }
144 }
145
146 extension GalleryCell: UIScrollViewDelegate {
147     
148     public func viewForZooming(in scrollView: UIScrollView) -> UIView? {
149         return imageView
150     }
151     
152     public func scrollViewDidZoom(_ scrollView: UIScrollView) {
153         
154         let imageViewSize = imageView.frame.size
155         let scrollViewSize = scrollView.bounds.size
156         
157         let verticalPadding = imageViewSize.height < scrollViewSize.height ? (scrollViewSize.height - imageViewSize.height) / 2 : 0
158         let horizontalPadding = imageViewSize.width < scrollViewSize.width ? (scrollViewSize.width - imageViewSize.width) / 2 : 0
159         
160         if verticalPadding >= 0 {
161             // Center the image on screen
162             scrollView.contentInset = UIEdgeInsets(top: verticalPadding, left: horizontalPadding, bottom: verticalPadding, right: horizontalPadding)
163         } else {
164             // Limit the image panning to the screen bounds
165             scrollView.contentSize = imageViewSize
166         }
167     }
168 }