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)
}