123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236 |
- // _____ _
- // |_ _| |_ _ _ ___ ___ _ __ __ _
- // | | | ' \| '_/ -_) -_) ' \/ _` |_
- // |_| |_||_|_| \___\___|_|_|_\__,_(_)
- //
- // Threema iOS Client
- // Copyright (c) 2020 Threema GmbH
- //
- // This program is free software: you can redistribute it and/or modify
- // it under the terms of the GNU Affero General Public License, version 3,
- // as published by the Free Software Foundation.
- //
- // This program is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU Affero General Public License for more details.
- //
- // You should have received a copy of the GNU Affero General Public License
- // along with this program. If not, see <https://www.gnu.org/licenses/>.
- import UIKit
- class ImagePreviewCollectionViewCell: UICollectionViewCell, UIScrollViewDelegate, UIGestureRecognizerDelegate {
-
- @IBOutlet weak var scrollView: UIScrollView!
- @IBOutlet weak var imageView: UIImageView!
-
- @IBOutlet weak var gifContainerView: UIView!
- @IBOutlet weak var gifPlayImageView: UIImageView!
- @IBOutlet weak var gifContentVIew: UIView!
-
- @IBOutlet weak var loadingText: UILabel!
- @IBOutlet weak var activityIndicator: UIActivityIndicatorView!
- @IBOutlet weak var loadingView: UIView!
-
- var indexPath : IndexPath?
- var isPlaying : Bool = false
- var animatedImageView : FLAnimatedImageView?
- var imageSize : CGSize?
-
- required init?(coder: NSCoder) {
- super.init(coder: coder)
- NotificationCenter.default.addObserver(self, selector: #selector(self.pauseVideo), name: NSNotification.Name(rawValue: kMediaPreviewPauseVideo), object: nil)
- }
-
- func addAccessibilityLabels() {
- self.imageView.accessibilityLabel = String(format: NSLocalizedString("image", comment: ""))
- self.loadingView.accessibilityLabel = String(format: NSLocalizedString("loading_image", comment: ""))
- }
-
- func viewForZooming(in scrollView: UIScrollView) -> UIView? {
- self.imageView
- }
-
- @objc func tapTwice(gesture: UIGestureRecognizer) {
- if self.scrollView.zoomScale > self.scrollView.minimumZoomScale {
- self.scrollView.setZoomScale(self.scrollView.minimumZoomScale, animated: true)
- } else {
- self.scrollView.setZoomScale(self.scrollView.maximumZoomScale / 2, animated: true)
- }
- }
-
- override func prepareForReuse() {
- super.prepareForReuse()
- self.imageView.image = nil
- self.animatedImageView?.animatedImage = nil
-
- self.showLoadingScreen()
- }
-
- override func layoutSubviews() {
- super.layoutSubviews()
-
- self.animatedImageView?.frame = CGRect(x: 0, y: 0, width: self.bounds.width, height: self.bounds.height)
-
- // This checks if the displayed media type is a static image
- // It could be made more robust.
- guard let size = self.imageSize else {
- return
- }
- self.setupZooming(size)
- self.centerImage()
- }
-
- func setColors() {
- self.gifPlayImageView.tintColor = .white
- self.activityIndicator.color = Colors.fontNormal()
-
- self.loadingText.textColor = Colors.fontNormal()
- self.loadingView.backgroundColor = Colors.background()
-
- self.gifPlayImageView.image = self.gifPlayImageView.image?.draw(withTintColor: .white)
- }
-
- func showLoadingScreen() {
- self.setColors()
-
- self.imageView.isHidden = true
-
- UIView.animate(withDuration: 0.1, animations: {
- self.gifContainerView.isHidden = true
- self.gifPlayImageView.isHidden = true
-
- self.activityIndicator.startAnimating()
-
- self.loadingText.text = String(format: NSLocalizedString("loading_image", comment: ""))
-
- self.activityIndicator.isHidden = false
- self.loadingView.isHidden = false
- self.loadingText.isHidden = false
- })
-
- self.scrollView.gestureRecognizers?.removeAll()
- }
-
- func updateImageTo(data : Data) {
-
- //Setup gif image view
- let image = FLAnimatedImage(animatedGIFData: data)
- let animImageView = FLAnimatedImageView()
-
- animImageView.animatedImage = image
- animImageView.contentMode = .scaleAspectFit
- animImageView.frame = self.bounds
-
- // Add gif image view and bring the play button to the foreground
- self.gifContainerView.addSubview(animImageView)
- self.gifContainerView.bringSubviewToFront(self.gifPlayImageView)
-
- // Store a reference to the image view to be able to relayout it when layoutSubviews is called
- self.animatedImageView = animImageView
-
- // FLAnimatedImageView starts animating immediately by default
- animatedImageView?.stopAnimating()
-
- // Hide loading screen and unhide gif image view
- self.gifPlayImageView.isHidden = false
- self.gifContainerView.isHidden = false
- self.loadingView.isHidden = true
- self.loadingText.isHidden = true
- self.activityIndicator.stopAnimating()
-
- let imageFrame = AVMakeRect(aspectRatio: image!.size, insideRect: animImageView.frame)
-
- let tapView = UIView(frame: imageFrame)
-
- self.gifContainerView.addSubview(tapView)
- self.gifContainerView.bringSubviewToFront(tapView)
-
- // Add a tap gesture recognizer for play pause
- let tapGR = UITapGestureRecognizer(target: self, action: #selector(ImagePreviewCollectionViewCell.handleTap(_:)))
- tapGR.delegate = self
- tapGR.numberOfTapsRequired = 1
- self.animatedImageView!.isUserInteractionEnabled = true
- tapView.addGestureRecognizer(tapGR)
- }
-
- func updateImageTo(image : UIImage) {
-
- self.imageView.image = image
- //
- // Setup imageview
- self.imageView.contentMode = .scaleAspectFit
-
- // Show imageview and hide loading view
- self.imageView.isHidden = false
- self.loadingView.isHidden = true
- self.activityIndicator.stopAnimating()
- self.loadingText.isHidden = true
-
- self.imageSize = image.size
- self.setupZooming(image.size)
-
- self.centerImage()
- }
-
- private func setupZooming(_ imageSize: CGSize) {
- let minZoom = min(self.bounds.size.width / imageSize.width, self.bounds.size.height / imageSize.height);
-
- self.imageView.isUserInteractionEnabled = true
- self.imageView.isMultipleTouchEnabled = true
-
- let doubleTapGesture = UITapGestureRecognizer(target: self, action: #selector(self.tapTwice))
- doubleTapGesture.numberOfTapsRequired = 2;
- self.scrollView.gestureRecognizers?.append(doubleTapGesture)
-
-
- self.scrollView.contentSize = self.imageView.frame.size
- self.scrollView.delegate = self
- self.scrollView.isScrollEnabled = false
-
- self.scrollView.minimumZoomScale = minZoom
- self.scrollView.setZoomScale(minZoom, animated: false)
- self.scrollView.maximumZoomScale = 6
-
- // Set the image frame size after scaling down
- let imageWidth = imageSize.width * minZoom
- let imageHeight = imageSize.height * minZoom
- let newImageFrame = CGRect(x: 0, y: 0, width: imageWidth, height: imageHeight)
- self.imageView.frame = newImageFrame
- }
-
- private func centerImage() {
- let imageViewSize = imageView.frame.size
- let scrollViewSize = self.frame.size
- let verticalPadding = imageViewSize.height < scrollViewSize.height ? (scrollViewSize.height - imageViewSize.height) / 2 : 0
- let horizontalPadding = imageViewSize.width < scrollViewSize.width ? (scrollViewSize.width - imageViewSize.width) / 2 : 0
-
- self.scrollView.contentInset = UIEdgeInsets(top: verticalPadding, left: horizontalPadding, bottom: verticalPadding, right: horizontalPadding)
- }
-
- @objc func handleTap(_ gesture: UITapGestureRecognizer) {
- DispatchQueue.main.async {
- self.togglePlaying()
- }
- }
-
- func togglePlaying() {
- if self.isPlaying {
- self.pauseVideo()
- } else {
- self.playVideo()
- }
- self.isPlaying = !self.isPlaying
- }
-
- @objc func pauseVideo() {
- self.animatedImageView?.stopAnimating()
- self.gifPlayImageView.isHidden = false
- }
-
- func playVideo() {
- self.animatedImageView?.startAnimating()
- self.gifPlayImageView.isHidden = true
- }
- }
|