Implement 3D touch on multiple collection views or table views in the same view controller

谁说我不能喝 提交于 2019-12-24 07:20:54

问题


I would like to have 3D touch on both of the collection views of my app(Only the "Peek" functionality). They are both contained in the same view controller. No matter what syntax I try it always shows the image and text for the a cell in the first collectionview, even if I choose a cell in the second collection view. How do I separate these so that only one happens specifically for the collectionview cell I have selected?

Here is how I am implementing the 3D touch functionality:

I put this in VC's viewDidAppear because it wasn't working in viewDidLoad for some reason:

  override func viewDidAppear(animated: Bool) {

  if( traitCollection.forceTouchCapability == .Available){

    registerForPreviewingWithDelegate(self, sourceView: collectionView1)
    registerForPreviewingWithDelegate(self, sourceView: collectionView2)

}

Here is what I also have in the VC that houses the two collectionviews:

func previewingContext(previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? {


guard let previewVC = storyboard?.instantiateViewControllerWithIdentifier("PreviewVC") as? PreviewViewController
    else{ return nil }

guard let indexPath = collectionView1?.indexPathForItemAtPoint(location) else { return nil }
guard let indexPath2 = collectionView2.indexPathForItemAtPoint(location) else { return nil }
guard let cell1 = collectionView1?.cellForItemAtIndexPath(indexPath) else { return nil }
guard let cell2 = collectionView2.cellForItemAtIndexPath(indexPath) else { return nil}

    previewVC.selectedItem = String(Gifs.row1[indexPath.row])
    previewVC.selectedItem2 = String(Gifs.row2[indexPath.rown])

    previewVC.preferredContentSize = CGSize(width: 245, height: 200)
    previewingContext.sourceRect = cell1.frame

return previewVC
}

And here is what I have in the previewVC:

class PreviewViewController: UIViewController {


 @IBOutlet weak var selectedGifImageView: UIImageView!

 @IBOutlet weak var textLabel: UILabel!


 var selectedItem: String?
 var selectedItem2: String?
 var delegate: MoveScrollViewController?

override func viewWillAppear(animated: Bool) {

 textLabel.text = Gifs.gifDictionary[selectedItem]
 selectedGifImageView.setGifImage(UIImage(name: selectedItem))

 textLabel.text = Gifs.gifDictionary[selectedItem2]
 selectedGifImageView.setGifImage(UIImage(name: selectedItem2))

}

gif of what's happening


回答1:


This is what I did in my project.

I have a scrollView on the top of the viewController and a tableView on the bottom. And I would like two of them to adopt the peek and pop. So the following is what I did.

First, you need to add UIViewControllerPreviewingDelegate to the viewController that you would like to implement the peek and pop function.

Second, register the container view (usually is self.view) by calling

if self.traitCollection.forceTouchCapability == .Available {
    registerForPreviewingWithDelegate(self, sourceView: view)
}

Third, you convert the CGPoint of the view coordinate system to any view that you would like to have peek and pop feature in the previewingContext delegate

func previewingContext(previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController?

For example:

a. Convert CGPoint on the self.view to the point inside tableView

let tableViewPoint = tableView.convertPoint(location, fromView: view)

b. After you have this point, you can confirm if the tableViewPoint is inside the tableView, get the tableViewCell from the tableViewPoint and do something with it.

if self.tableView.pointInside(tableViewPoint, withEvent: nil) {
    guard let indexPath =  self.tableView.indexPathForRowAtPoint(tableViewPoint) else {
            return nil
        }

    guard let tableViewCell = self.tableView.cellForRowAtIndexPath(indexPath) else {
            return nil
        }
    // do something with your tableView cell here...
    let yourViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("YOURVIEWCONTROLLER") as! YOURVIEWCONTROLLER

    // set up the contentSize for peek
    yourViewController.preferredContentSize = CGSize(width: 0.0, height: 600)

    // set up the focusing rect for the tableViewCell so that it won't be blurred out.
    let viewPoint = self.view.convertPoint(tableCell.frame.origin, fromView: self.tableView)
    previewingContext.sourceRect = CGRect(origin: viewPoint, size: tableCell.frame.size)
    return yourViewController
}

And then do the exactly the same to the scroll view, then you will be able to have peek and pop for both scrollView and tableView in the same viewController.

Last implement the second delegate for pop

func previewingContext(previewingContext: UIViewControllerPreviewing, commitViewController viewControllerToCommit: UIViewController) {
    showViewController(viewControllerToCommit, sender: self)
}

It works for me perfectly. Hopefully it will help you out as well.



来源:https://stackoverflow.com/questions/38511133/implement-3d-touch-on-multiple-collection-views-or-table-views-in-the-same-view

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!