1

I'm making this design in my IOS app, the final design of what I want is here, I already have the collection view for one of the rows working shown here in a video and the storyboard looks like this.

It's just when I put the collection view in a stack view or scroll view to add similar collection views to the view, it either disappears or only half of it is shown? This is what it looks like in app in this photo, the storyboard looks like this.

Why am I doing wrong? As soon as the collection view gets added into a stack view or scroll view it changes. What's the best way to achieve the design I showed in this photo with the collection view I have built at the moment?

This is the code for the view at the moment:

import UIKit
import AVKit
import Firebase
import MMPlayerView


class HomeViewController: UIViewController {
    var offsetObservation: NSKeyValueObservation?
    lazy var mmPlayerLayer: MMPlayerLayer = {
         let l = MMPlayerLayer()
         l.cacheType = .memory(count: 5)
         l.coverFitType = .fitToPlayerView
         l.videoGravity = AVLayerVideoGravity.resizeAspect
         l.replace(cover: CoverA.instantiateFromNib())
         l.repeatWhenEnd = true
         return l
    }()

@IBOutlet weak var playerCollect: UICollectionView!
override func viewDidLoad() {
    super.viewDidLoad()

    // remove previous download fails file
    MMPlayerDownloader.cleanTmpFile()
    self.navigationController?.mmPlayerTransition.push.pass(setting: { (_) in

    })
    offsetObservation = playerCollect.observe(\.contentOffset, options: [.new]) { [weak self] (_, value) in
        guard let self = self, self.presentedViewController == nil else {return}
        NSObject.cancelPreviousPerformRequests(withTarget: self)
        self.perform(#selector(self.startLoading), with: nil, afterDelay: 0.2)
    }
    playerCollect.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 200, right:0)
    DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { [weak self] in
        self?.updateByContentOffset()
        self?.startLoading()
    }

        mmPlayerLayer.getStatusBlock { [weak self] (status) in
            switch status {
            case .failed(let err):
                let alert = UIAlertController(title: "err", message: err.description, preferredStyle: .alert)
                alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
                self?.present(alert, animated: true, completion: nil)
            case .ready:
                print("Ready to Play")
            case .playing:
                return
               // print("Playing")
            case .pause:
                return
               // print("Pause")
            case .end:
                return
              //  print("End")
            default: break
            }
        }
        mmPlayerLayer.getOrientationChange { (status) in
            print("Player OrientationChange \(status)")
        }
    }

deinit {

    offsetObservation?.invalidate()
    offsetObservation = nil
    print("ViewController deinit")
}

@IBAction func profileButtonTap(_ sender: Any) {
    let uid = (Auth.auth().currentUser?.uid)!
    let Splash = SpalshScreenViewController()
    Splash.GetProfilePicture(uid: uid)
    Splash.GetUsername(uid: uid)
    Splash.GetName(uid: uid)
    Splash.GetClipsNumber(uid: uid)
    Splash.GetFollowersNumber(uid: uid)
    Splash.GetFollowingsNumber(uid: uid)
    performSegue(withIdentifier: "showProfile", sender: nil)
}
}

 // This protocol use to pass playerLayer to second UIViewcontroller
 extension HomeViewController: MMPlayerFromProtocol {
    // when second controller pop or dismiss, this help to put player back to where you want
    // original was player last view ex. it will be nil because of this view on reuse view
     func backReplaceSuperView(original: UIView?) -> UIView? {
        guard let path = self.findCurrentPath(),
        let cell = self.findCurrentCell(path: path) as? PlayerCell else {
        return original
    }
    return cell.imgView
}

// add layer to temp view and pass to another controller
var passPlayer: MMPlayerLayer {
    return self.mmPlayerLayer
}
func transitionWillStart() {
}
// show cell.image
func transitionCompleted() {
    self.updateByContentOffset()
    self.startLoading()
}
}
extension HomeViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    let m = min(UIScreen.main.bounds.size.width, UIScreen.main.bounds.size.height)
    return CGSize(width: m, height: m*0.75)
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
   DispatchQueue.main.async { [unowned self] in
    if self.presentedViewController != nil || self.mmPlayerLayer.isShrink == true {
            //self.playerCollect.scrollToItem(at: indexPath, at: .centeredVertically, animated: true)
            //self.updateDetail(at: indexPath)
        } else {
            self.presentDetail(at: indexPath)
        }
    }
}

fileprivate func updateByContentOffset() {
    if mmPlayerLayer.isShrink {
        return
    }

    if let path = findCurrentPath(),
        self.presentedViewController == nil {
        self.updateCell(at: path)
        //Demo SubTitle
        if path.row == 0, self.mmPlayerLayer.subtitleSetting.subtitleType == nil {
        }
    }
}

fileprivate func presentDetail(at indexPath: IndexPath) {
    self.updateCell(at: indexPath)
    mmPlayerLayer.resume()

    if let vc = UIStoryboard.init(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "DetailViewController") as? DetailViewController {
        vc.data = DemoSource.shared.demoData[indexPath.row]
        self.present(vc, animated: true, completion: nil)
    }
}

fileprivate func updateCell(at indexPath: IndexPath) {
    if let cell = playerCollect.cellForItem(at: indexPath) as? PlayerCell, let playURL = cell.data?.play_Url {
        // this thumb use when transition start and your video dosent start
        mmPlayerLayer.thumbImageView.image = cell.imgView.image
        // set video where to play
        mmPlayerLayer.playView = cell.imgView
        mmPlayerLayer.set(url: playURL)
    }
}

@objc fileprivate func startLoading() {
    self.updateByContentOffset()
    if self.presentedViewController != nil {
        return
    }
    // start loading video
    mmPlayerLayer.resume()
}

private func findCurrentPath() -> IndexPath? {
    let p = CGPoint(x: playerCollect.contentOffset.x + playerCollect.frame.width/2, y: playerCollect.frame.height/2)
    return playerCollect.indexPathForItem(at: p)
}

private func findCurrentCell(path: IndexPath) -> UICollectionViewCell? {
   return playerCollect?.cellForItem(at: path)
}
}

extension HomeViewController: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return DemoSource.shared.demoData.count
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PlayerCell", for: indexPath) as? PlayerCell {
        cell.data = DemoSource.shared.demoData[indexPath.row]
        return cell
    }
    return UICollectionViewCell()
}

}

UPDATE:

Adding a height on the collection view makes it only show half of it shown here: Why does it do this? enter image description here

Nathan
  • 1,393
  • 1
  • 9
  • 40
  • have you given height constraints to your stackview?? – Keshu R. Jan 24 '20 at 10:28
  • @KeshuR. Yes. The stack view is 10 points away from the buttons at the top and all the other three sides are constrained to each side (to each left and right hand side and 10 points from the bottom of the screen) as I want it to take the whole view. – Nathan Jan 24 '20 at 10:30
  • I don't understand. You need 3 stack views as pet the image you showed. right? Each stackview will have 1 featured label and 1 collection view. Correct me if i am wrong. Try giving stackView a height constraint of 200 or something. Remove the bottom constraint. – Keshu R. Jan 24 '20 at 10:35
  • Does it have to be a stack view or scroll view? Can you not have tableview with collection view inside with flow of collection view being horizontal ? – chirag90 Jan 24 '20 at 10:46
  • @KeshuR. Removing the bottom constraint will make it worse apparently. I’d just want to have a title, then a collection view, a title, then a collection view. And so on – Nathan Jan 24 '20 at 10:51
  • @chirag90 no it doesn’t have to be a stack view, would a scroll view or table view work better? Once I’ve made it it’s going to be long enough for the need of a scroll view so or something similar. Could you explain how you would do it your way? I just went for a stack view since I’m more familiar with that. – Nathan Jan 24 '20 at 10:53
  • @NathanEllis have a look at [Collectionview inside tableview](https://slicode.com/collectionview-inside-tableview-cell-part-1/) – chirag90 Jan 24 '20 at 10:57
  • @chirag90 wouldn’t using a table view be worse? Laying out the collection view and titles and other items? Doesn’t give the features as a stack view or scroll view does? What’s the bonus? – Nathan Jan 24 '20 at 11:08
  • Please don't put links to images, but add them in your question. Like you did with the last one. – koen Jan 24 '20 at 16:04
  • @koen sorry but then the page would be 4 miles long. – Nathan Jan 24 '20 at 16:05
  • Try making the pics smaller. It's much easier to read if they are all in the question. – koen Jan 24 '20 at 16:14
  • @koen how do you make them smaller? – Nathan Jan 24 '20 at 16:15
  • @NathanEllis Just shrink them in Preview or something and then re-upload to imgur. – koen Jan 24 '20 at 16:16

0 Answers0