1
votes

In my app using UIPageViewController to display full size images, and at the bottom of screen have thumbnail CollectionView each thumbnail is representing UIPageViewController full size image.My question is how to achieve paging of UIpageViewController when user select different thumbnail collection view cell? if anyone know how to achieve this functionality , please help me with code or advice or links. Thanks

I believe I have to work with UICollectionView’s didSelectItemAtIndexPath method ,but not too sure how best to do it and would really appreciate help, please.

My Collection View File

protocol ThumbnailViewDelegate: class {

func didSelectThumbnail(at index: Int)

} class ThumbnailView: UIView, UICollectionViewDelegate, UICollectionViewDataSource,UICollectionViewDelegateFlowLayout, PhotoCollectionViewModelPresenter{

weak var delegate: ThumbnailViewDelegate?

var assets: [PHAsset] = []

private let viewModel = PhotoCollectionViewModel()
//private var myViewModel: DetailViewModel!

private let imageDownloader = ImageDownloader(targetSize: CGSize(width: 80, height: 80 ))

//var selectedImage: UIImage?

lazy var thumbnailCollectionView: UICollectionView = {

    let layout = UICollectionViewFlowLayout()
    layout.scrollDirection = .horizontal

    let view =  UICollectionView(frame: CGRect.zero, collectionViewLayout: layout)
    view.translatesAutoresizingMaskIntoConstraints = false
    view.isPagingEnabled = true
    view.delegate = self
    view.dataSource = self
    view.isPrefetchingEnabled = false
    view.register(ThumbnailCollectionViewCell.self, forCellWithReuseIdentifier: "Cell")
    let cellImageView = ThumbnailCollectionViewCell()
    view.addSubview(cellImageView.imageView)
   view.backgroundColor = UIColor.white
    return view
}()


let  imageView: ThumbnailCollectionViewCell = {
    let view = ThumbnailCollectionViewCell()
    view.contentMode = .scaleAspectFit
    view.translatesAutoresizingMaskIntoConstraints = false

    return view

}()




override init(frame: CGRect) {
    super.init(frame: frame)


    self.addSubview(thumbnailCollectionView)


    thumbnailCollectionView.leftAnchor.constraint(equalTo: leftAnchor).isActive = true
    thumbnailCollectionView.rightAnchor.constraint(equalTo: rightAnchor).isActive = true
    thumbnailCollectionView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
    thumbnailCollectionView.heightAnchor.constraint(equalToConstant: 100).isActive = true



}



required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}


func propagateReload() {
    thumbnailCollectionView.reloadData()
}


func numberOfSections(in collectionView: UICollectionView) -> Int {

    // #warning Incomplete implementation, return the number of sections
    return 1
}


func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return assets.count


}



func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath as IndexPath) as! ThumbnailCollectionViewCell

    cell.layer.masksToBounds = true
    cell.layer.cornerRadius = 8

        let image = assets[indexPath.item]
        imageDownloader.download(asset: image) { [weak self] (image) in
           self?.configureCell(indexPath: indexPath, image: image)



    }



    return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
{
    return CGSize(width: 80.0, height: 80.0)
}






func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {

    delegate?.didSelectThumbnail(at: indexPath.item)



}


func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {

}

func configureCell(indexPath: IndexPath, image: UIImage) {
    guard let cell = thumbnailCollectionView.cellForItem(at: indexPath) as? ThumbnailCollectionViewCell else {
        return
    }
    cell.configure(image: image)
}

}

PageViewController File

class MainPageViewController: UIPageViewController {

var mainImageIndex: Int?

var pageViewModels: [DetailPageViewModel]!

var viewModel: DetailViewModel!

var collectionAssets: [PHAsset] = []

var selectedAsset: UIImage?

  private var pendingIndex: Int?


    // Collection View
    lazy var collectionView: ThumbnailView = {
        let view = ThumbnailView()
        view.delegate = self
        view.assets = self.collectionAssets
        view.translatesAutoresizingMaskIntoConstraints = false
        return view
    }()


//MARK: - Create VC

lazy  var pageViewControllersArray: [PageViewController] = {
    return pageViewModels.map {
        return PageViewController(viewModel: $0)
    }



}()


var currentIndex:Int {
    get {
        return pageViewControllersArray.index(of: self.viewControllers!.first! as! PageViewController)!
    }

    set {
        guard newValue >= 0,
            newValue < pageViewControllersArray.count else {
                return
        }

        let vc = pageViewControllersArray[newValue]
        let direction:UIPageViewController.NavigationDirection = newValue > currentIndex ? .forward : .reverse
        self.setViewControllers([vc], direction: direction, animated: true, completion: nil)
    }
}

override func viewDidLoad() {

super.viewDidLoad()


dataSource = self
delegate = self

view.backgroundColor = UIColor.white
setViewControllers([pageViewControllersArray[mainImageIndex ?? 0]], direction: .forward, animated: true, completion: nil)

self.view.addSubview(collectionView)
setupCollectioViewAutoLayout()



}



func setupCollectioViewAutoLayout(){

    collectionView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
    collectionView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
    collectionView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
    collectionView.heightAnchor.constraint(equalToConstant: 100).isActive = true
}

func viewWillAppear() { super.viewWillAppear(true)

}

}

extension MainPageViewController: UIPageViewControllerDelegate, UIPageViewControllerDataSource, ThumbnailViewDelegate {

func didSelectThumbnail(at index: Int) {


}

func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {


    guard let viewController = viewController as? PageViewController else {return nil}



    if let index = pageViewControllersArray.index(of: viewController){


        if index > 0{

            return pageViewControllersArray[index - 1]

        }

    }
    return  nil

}


func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {

    guard let viewController = viewController as? PageViewController else {return nil}


    if let index = pageViewControllersArray.index(of: viewController){

        if index < pageViewControllersArray.count - 1{

            return pageViewControllersArray[index + 1]
        }

    }
    return nil
}

func presentationCountForPageViewController(pageViewController: UIPageViewController) -> Int {
    return pageViewControllersArray.count
}

func presentationIndexForPageViewController(pageViewController: UIPageViewController) -> Int {

    return currentIndex
}

}

1
You've proposed a novel interface. Now you need to work out how to implement it. I would suggest setiting up a view controller that contains child view controllers for both your page view controller and your collection view, and then creating logic to sync between them.Duncan C
Thanks for advice, will try to do thatFedir Kryvyi
I created DetailViewController that contains PageViewController as a child view and my thumbnail Collection View is child view of PageViewController ,but I still can't figure out how to do logic to sync between themFedir Kryvyi
So you need to define protocols that the page view controller and collection view controller use to communicate with each other, give them pointers to each other, and send messages when the user switches images.Duncan C
In my Thumbnail View created protocol with " func didSelectThumbnail(at index: Int),then inside collection view( didSelectItemAt indexPath: IndexPath) defined my delegate like this : delegate?.didSelectThumbnail(at: indexPath.item).Them confirmed my MainPageViewController to this protocol and at the moment I have current index of each thumbnail in my PageViewController.how can I send this index to the each View Controller of the PageViewController so the user can see main image same as thumbnail?Fedir Kryvyi

1 Answers

0
votes

When the select method is called, show another page view or page view controller on the whole screen.