7

I have this big UICollectionView occupying major part of screen and there is a UIButton that shows a menu. I want to hide the menu when the user taps on any side of the screen which becomes unfortunately any part of UICollectionView for me. Tried on other view the below code, it works well...but not for UICollectionView. The function does not gets called.

override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {            
   hidemenu()
   self.view.endEditing(true)            
}

What is the problem? Thanks for your time.

OR How to trigger touchesBegan in the UIViewController where UICollectionView resides

Here is the project.

Ratnesh Jain
  • 671
  • 7
  • 14
  • You can try by disabling userinteraction of collection view when menu opens , this way `touchesBegan` should be called. You can enable it again when menu is closed. – Bhumit Mehta May 08 '15 at 09:56
  • i cannot do that...menu and collection view are in different class..so quiet complex i think –  May 08 '15 at 09:58
  • Ok , than this thread might help you. Here its discussed for tableview , you can try same for collectionview http://stackoverflow.com/questions/5848221/touch-events-on-uitableview – Bhumit Mehta May 08 '15 at 10:00

3 Answers3

6

While tapping on scrolling controllers (like UIScrollView, UITableView, UICollection etc) does not call touchesBegan method. because they have their own selector method. To handle such situation, you need to create UITapGesture on UICollectionView. While tapping on UICollectionView, its selector method called and do what ever you want.

Here are the link that guide you. how to create double Tap Gesture on UICollectionView. with help of this you can created single Tap gesture as well.

Collection View + Double Tap Gesture

Edit : Do the following changes, it work fine.

Step 1 : Declare handleTap in SwipeMenuViewController.

func handleTap(sender: UITapGestureRecognizer) {

        println("called swipe")

    }

Step 2 : Create global variable of SwipeMenuViewController controller. that is out side of viewDidLoad()

var vc2 = SwipeMenuViewController()

enter image description here

Step 3 : Declare TapGesture in viewDidLoad()

var tap = UITapGestureRecognizer(target: vc2, action : "handleTap:")
        tap.numberOfTapsRequired = 1
        self.collectionView.addGestureRecognizer(tap)

Output :

called swipe

Hope this help you.

Jatin Patel - JP
  • 3,725
  • 2
  • 21
  • 43
  • ok i am trying this..but i want the target to another viewcontroller because the method that hides the menu is in other class...it doesnot work...can i assign target to another class? –  May 08 '15 at 10:44
  • var tap = UITapGestureRecognizer(target: SwipeMenuViewController(), action : "show") collectionView.addGestureRecognizer(tap) but the action doesnot get call..it throws and exception unrecognized selector sent to an instance –  May 08 '15 at 10:47
  • but doesnot...i checked the method name..its fine...: ( –  May 08 '15 at 10:51
  • right now i am chating with help of phone. i will check out and inform you. still you can redirect tap gesture event from current class to another class with help of delegate. – Jatin Patel - JP May 08 '15 at 10:52
  • @copeME, i have checked out scenario and it seems working fine. – Jatin Patel - JP May 08 '15 at 11:09
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/77298/discussion-between-copeme-and-none). –  May 08 '15 at 11:22
  • i have uploaded project please have alook –  May 08 '15 at 11:56
  • @copeME, i am unable to download it. can you please upload it on dropbox. – Jatin Patel - JP May 08 '15 at 12:10
  • @copeME, check my edited answer. here need to create global variable instead of local variable. – Jatin Patel - JP May 08 '15 at 13:22
  • hey thanks man!!! i dont have mac at home....will implement it tomorrow at office :)...anyway i will accept your answer –  May 08 '15 at 14:10
  • Actually you declared local variable inside viewdidload so once you tapped on collection view that object is deallocated so crash happened – Jatin Patel - JP May 08 '15 at 14:44
  • did you try calling the hideMenu() method..instead if printing called swipe.....i have got some problem there –  May 09 '15 at 02:24
5

You can add a UITapGestureRecognizer to the UICollectionView and create an action to dismiss the view if the user touch outside your collection or anywhere.

Step 1 Create a tap gesture for dismiss the view

override func viewDidLoad() {
    super.viewDidLoad()
     ...

    let tap = UITapGestureRecognizer(target: self, action: #selector(didTapOutsideCollectionView(recognizer:)))
    tap.numberOfTapsRequired = 1
    self.collectionView.addGestureRecognizer(tap)
}

Step 2 With the tap location implement your desired action

@objc func didTapOutsideCollectionView(recognizer: UITapGestureRecognizer){
    let tapLocation = recognizer.location(in: self.view)
    //The point is outside of collection cell
    if collectionView.indexPathForItem(at: tapLocation) == nil {
         dismiss(animated: true, completion: nil)
    }
}
Ariel Antonio Fundora
  • 1,330
  • 15
  • 20
0

You can directly use this method , whenever user taps on any part of collection view , your menu will be automatically hidden:-

func collectionView(_ collectionView: UICollectionView,
    didSelectItemAtIndexPath indexPath: NSIndexPath)
{
    hidemenu()
        self.view.endEditing(true)    
}

To detect tap on spaces between the cell, here is the code

self.collectionView.backgroundView = [[UIView alloc] initWithFrame:self.collectionView.frame];
self.collectionView.backgroundView.userInteractionEnabled = YES;

UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onTap:)];
self.collectionView.backgroundView.gestureRecognizers = @[tapRecognizer];
Vizllx
  • 9,135
  • 1
  • 41
  • 79
  • might not work ..if i have large collection view and few cells on it ?? –  May 08 '15 at 10:07
  • I don't think you are getting the point mate.. only tapping it works. – Vizllx May 08 '15 at 10:22
  • sorry..i was saying i must tapp a cell for that..i have some spaces between the cell..so what when the user taps on the space..so it doesnot work for me –  May 08 '15 at 10:23
  • ok..i am trying that...but setting target to another class doesnot call the action –  May 08 '15 at 10:45
  • what do you mean by "setting target to another class"? – Vizllx May 08 '15 at 11:09
  • var tap = UITapGestureRecognizer(target: SwipeMenuViewController(), action : "handleTap:") –  May 08 '15 at 11:19
  • Can you just check by adding tap gesture to Collectionview not its background view, whether handleTap is getting fired or not? – Vizllx May 08 '15 at 11:30
  • i have uploaded project please have a look –  May 08 '15 at 11:56