Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When presenting a popover view, how can I let the user select cell in parent collection view?

I have a collection view and when a cell is selected it presents a popover view showing more information about that cell.

I would like to allow the user to click another cell and then have the popover view change to showing that cell's information without having to close the popover. If the user were to click somewhere on the parent view that isn't a cell then the popover should close. But, I would like the user to still be able to scroll the collection view without closing the popover.

How can that be done?

like image 887
webmagnets Avatar asked Apr 07 '15 12:04

webmagnets


3 Answers

According to Apple :

When a popover is active, interactions with other views are normally disabled until the popover is dismissed. Assigning an array of views to this property allows taps outside of the popover to be handled by the corresponding views.

Then you can use the passthroughViews in the following way :

CollectionViewController

import UIKit

let reuseIdentifier = "Cell"

class CollectionViewController: UICollectionViewController {

   var popoverViewController : PopoverViewController?

   override func viewDidLoad() {
       super.viewDidLoad()         

   }

   override func didReceiveMemoryWarning() {
      super.didReceiveMemoryWarning()
      // Dispose of any resources that can be recreated.
   }   

   override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
      //#warning Incomplete method implementation -- Return the number of sections
      return 1
   }    

   override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
      //#warning Incomplete method implementation -- Return the number of items in the section
      return 15
   }

   override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {

      let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! CollectionViewCell
      cell.labelInfo.text = "Cell \(indexPath.row)"        
      return cell
   }

   override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {

      println("tapped")

      if let popover = self.popoverViewController {

          var cell = self.collectionView!.cellForItemAtIndexPath(indexPath) as! CollectionViewCell
          popover.labelPop.text = cell.labelInfo.text

      }
      else {

          self.popoverViewController = self.storyboard?.instantiateViewControllerWithIdentifier("PopoverViewController") as? PopoverViewController

          var cell = self.collectionView!.cellForItemAtIndexPath(indexPath) as! CollectionViewCell

          var t = self.popoverViewController!.view
          self.popoverViewController!.labelPop.text = cell.labelInfo.text

          self.popoverViewController!.modalPresentationStyle = .Popover
          var popover = self.popoverViewController!.popoverPresentationController


          popover?.passthroughViews = [self.view]
          popover?.sourceRect = CGRect(x: 250, y: 500, width: 0, height: 0)
          self.popoverViewController!.preferredContentSize = CGSizeMake(250, 419)

          popover!.sourceView = self.view

          self.presentViewController(self.popoverViewController!, animated: true, completion: nil)
      }
   }    
}

The above code is the CollectionViewController to handle the UICollectionViewController and all its delegates.

CollectionViewCell

class CollectionViewCell: UICollectionViewCell {    
    @IBOutlet weak var labelInfo: UILabel!        
}

The custom cell with just a UILabel inside.

PopoverViewController

class PopoverViewController: UIViewController {

   @IBOutlet var labelPop: UILabel!

   override func viewDidLoad() {
      super.viewDidLoad()

      // Do any additional setup after loading the view.
   }

   override func didReceiveMemoryWarning() {
      super.didReceiveMemoryWarning()
      // Dispose of any resources that can be recreated.
   }   
}

And finally the PopoverViewController to show in form of .Popover.

There are some observations in answer I would like to point out :

  • I set a reference to the class PopoverViewController to keep it through the life cycle and pass it data when it remains open yet.

  • The line var t = self.popoverViewController!.view it's necessary because if not the @IBOutlet inside the PopoverViewController was not init until it's presented, there could be other ways to do it.

  • I present the popover in the middle of the screen to handle the tap in several cell and test it the scroll too, you can display it in any position you want.

  • In the views to allow when the popover is opened , I set the self.view, but in this way you need to dismiss it for you own, because it never is dismissed when you make taps in the view, you can put any view you want instead.

Any trouble you have with the solution I can share it the project on Github.

I hope this help you

like image 180
Victor Sigler Avatar answered Sep 20 '22 17:09

Victor Sigler


What you are looking for is the passthroughViews property of the popover.

However, if you open the popover as a result of tapping a cell, I don't see how scrolling the collectionView will make sense. Don't you open the popover with the arrow pointing to your cell? Scrolling the view will make the presenting cell to move away...

like image 44
pteofil Avatar answered Sep 23 '22 17:09

pteofil


You can use property of UIViewController 'modalInPopover' to enable touches outside the popover boundary. Just write the line given below in your view controller which you are presenting using popover controller.

self.modalInPopover = false;

where self is kind of UIViewController.

I have attached a screenshot for the same.

enter image description here

In swift the line will remain same

self.modalInPopover = false

enter image description here

like image 26
Vijay Masiwal Avatar answered Sep 23 '22 17:09

Vijay Masiwal