Home > Enterprise >  Screen Swipe is working only when I swipe above arrows for next picture
Screen Swipe is working only when I swipe above arrows for next picture

Time:06-16

I have a photoview which opens photo in foreground after tapping on the photo. Photo has a left and right arrow, which are working as next and previous photo. This arrows works fine when I'm using them. The left arrows hide itself when I go to the most left photo and also the right arrows hide itself when I go to the most right (last) photo. But this processing is not working when I'm using a swipe on the photos. The arrows are still there and not hidden.

So I made a function for swiping which will hide the arrows as the above. swiping function working but only in case when I swipe over the arrow and not the photo itself. Naturally the photo wont move to the next one when I'm swiping over the arrows... Could someone explain me what I'm doing wrong please?

Update Swipe over photos is possible, but gesSwipe() is not called

Here is my PhotoViewcontroller.swift

import Foundation
import UIKit

struct PhotoParam {
    let urls: [URL]
}

class PhotoViewController: ModalViewController, UIGestureRecognizerDelegate {
    // MARK: properties
    @IBOutlet private weak var imageCollection: UICollectionView!
    @IBOutlet weak var arrowLeftButton: UIButton!
    @IBOutlet weak var arrowRightButton: UIButton!
    
    var urls: [URL] = [] {
        didSet {
            imageCollection?.reloadData()
        }
    }
    
    // MARK: init
    override func initPresenter() {
        
    }
    
    override func setParam(param: Any) {
        guard let param = param as? PhotoParam else {
            return
        }
        
        self.urls = param.urls
    }
    
    
    @IBAction func gesSwipe(_ sender: UISwipeGestureRecognizer) {
        
        let screenW = UIScreen.main.bounds.width
        let offset: CGPoint = imageCollection.contentOffset
        let page = CGFloat(Int(offset.x / screenW) - 1)

        
            switch sender.direction {

            case .left:
                print("swipe right")
                print("%%%", page)
                print("%%%", CGFloat(urls.count - 2))
                if page >= CGFloat(urls.count - 2) {
                    self.arrowRightButton.isHidden = true
                } else {
                    self.arrowRightButton.isHidden = false
                }
                
            case .right:
                print("swipe left")
                if page < 0 {
                    self.arrowLeftButton.isHidden = true
                } else {
                    self.arrowLeftButton.isHidden = false
                }

            default:
                break
            }
    }
    
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.arrowLeftButton.isHidden = true
        self.imageCollection.delegate = self
        self.imageCollection.dataSource = self
        self.imageCollection.isPagingEnabled = true
        self.imageCollection.reloadData()
        

        let leftSwipeGesture = UISwipeGestureRecognizer(
                target: self,
                action: #selector(PhotoViewController.gesSwipe(_:))
        
        )
        
        leftSwipeGesture.direction = .left
        self.view.addGestureRecognizer(leftSwipeGesture)
        
        
        let rightSwipeGesture = UISwipeGestureRecognizer(
                target: self,
                action: #selector(PhotoViewController.gesSwipe(_:))
        
        )
        
        rightSwipeGesture.direction = .right
        self.view.addGestureRecognizer(rightSwipeGesture)
        
    }
    
    
    // MARK: methods
    @IBAction func arrowLeftTapped(_ sender: Any) {
        let screenW = UIScreen.main.bounds.width
        let offset: CGPoint = imageCollection.contentOffset
        let page = CGFloat(Int(offset.x / screenW) - 1)
        self.arrowRightButton.isHidden = false
        if page <= 0 {
            self.arrowLeftButton.isHidden = true
        } else {
            self.arrowLeftButton.isHidden = false
        }
        if page >= 0 {
            imageCollection.setContentOffset(CGPoint(x: screenW * page, y: 0), animated: true)
        }
    }
    
    @IBAction func arrowRightTapped(_ sender: Any) {
        let screenW = UIScreen.main.bounds.width
        let offset: CGPoint = imageCollection.contentOffset
        let page = CGFloat(Int(offset.x / screenW)   1)
        self.arrowLeftButton.isHidden = false
        if page >= CGFloat(urls.count - 1) {
            self.arrowRightButton.isHidden = true
        } else {
            self.arrowRightButton.isHidden = false
        }
        if page < CGFloat(urls.count) {
            imageCollection.setContentOffset(CGPoint(x: screenW * page, y: 0), animated: true)
        }
    }
}

extension PhotoViewController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
    // section数
    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }
    
    // 列数
    func collectionView(_ collectionView: UICollectionView,
                        numberOfItemsInSection section: Int) -> Int {
        return self.urls.count
    }
    
    // セル生成
    func collectionView(_ collectionView: UICollectionView,
                        cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let photoCell: PhotoCell = collectionView.dequeueReusableCell(withReuseIdentifier: "PhotoCell", for: indexPath) as! PhotoCell

        if indexPath.row < self.urls.count {
            photoCell.setImageURL(url: self.urls[indexPath.row])
        }
        return photoCell
    }
    
    // Screenサイズに応じたセルサイズを返す
    // UICollectionViewDelegateFlowLayoutの設定が必要
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
    }
}

extension PhotoViewController: PhotoCellDelegate {
    func isNotFound(url: URL) {
        if let index = urls.firstIndex(of: url) {
            self.urls.remove(at: index)
            self.imageCollection.reloadData()
        }
    }
}

UPDATE THIS worked for me

public func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
        let pageWidth = self.imageCollection.bounds.width
        let targetXContentOffset = Float(targetContentOffset.pointee.x)
        let contentWidth = Float(self.imageCollection!.contentSize.width)
        
        if targetXContentOffset == 0.0 {
            self.arrowLeftButton.isHidden = true
        }
                
        else {
            self.arrowLeftButton.isHidden = false
        }
        
        if contentWidth == targetXContentOffset   Float(pageWidth) {
            self.arrowRightButton.isHidden = true
        }
        
        else {
            self.arrowRightButton.isHidden = false
        }
    }

CodePudding user response:

Alternately you can use the following code to achieve the same functionality.

Let's declare a variable globally in your class

// By default this will be first page
var currentPage: Int = 0

And then you can confirm the following UIScrollViewDelegate to your class, since UICollectionViewDelegate is derived from UIScrollViewDelegate

    public func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
        let pageWidth = self.collectionView.bounds.width
        let targetXContentOffset = Float(targetContentOffset.pointee.x)
        let contentWidth = Float(self.collectionView!.contentSize.width)
        var newPage = Float(currentPage)

        if velocity.x == 0 {
            newPage = floor( (targetXContentOffset - Float(pageWidth) / 2) / Float(pageWidth))   1.0
        } else {
            newPage = Float(velocity.x > 0 ? currentPage   1 : currentPage - 1)
            if newPage < 0 {
                newPage = 0
            }
            if (newPage > contentWidth / Float(pageWidth)) {
                newPage = ceil(contentWidth / Float(pageWidth)) - 1.0
            }
        }
        let point = CGPoint (x: CGFloat(newPage * Float(pageWidth)), y: targetContentOffset.pointee.y)
        targetContentOffset.pointee = point
        currentPage = Int(newPage)
    }

And also your button actions can be simplified like this

 @IBAction func leftArrowTapped(_ sender: UIButton) {
        // Validate for previous page presence
        guard currentPage > 0 else {
            return
        }
        currentPage -= 1
        let indexPath = IndexPath(item: currentPage, section: 0)
        collectionView.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: true)
    }
    
    @IBAction func rightArrowTapped(_ sender: UIButton) {
        // Validate for next page presence
        guard currentPage < (urls.count-1) else {
            return
        }
        currentPage  = 1
        let indexPath = IndexPath(item: currentPage, section: 0)
        collectionView.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: true)
    }
  • Related