ThornTechPublic / LeftSlideoutMenu

Create a simple left slideout menu with Swift
http://www.thorntech.com/2015/06/want-to-implement-a-slideout-menu-in-your-swift-app-heres-how/
89 stars 24 forks source link

How can I go back to the tabbar without tapping on the menu button? #1

Open ghost opened 9 years ago

ghost commented 9 years ago

Currently I need to tap on the Menu button on the Navigation Controller to be able to go back to the main window. is it possible to add a gestureRecognizer for the view? thanks...

chenr2 commented 9 years ago

The way I did this in another app was to create a modal that covers or masks the TabBarController area. This modal mask not only obscures the selected tab from getting accidentally tapped, but you can add a gestureRecognizer to the modal mask's View to dismiss itself and send the toggleMenu event.

I'm trying to push up a commit that uses this approach, but I'm running into a snag that I ran into the first time. Whenever you open a modal, iOS removes everything underneath (maybe for performance reasons, who knows). Since the modal mask is transparent, there needs to be a way to keep the UI from disappearing.

I remember there was some combination of providing the current context and presenting the modal over the current context. And there was a subtle implementation difference between iOS 7 and 8. It's just a matter of digging up the exact set of changes that worked last time.

chenr2 commented 9 years ago

To answer your original question, I think a tap gesture on the First and Second View Controllers would be a simple way to close the menu. But if you wanted to prevent interaction while the menu was open, one approach would be to open a transparent modal. Here's a branch I created for this:

https://github.com/ThornTechPublic/LeftSlideoutMenu/tree/modalMask

This is the approach used:

The steps above are just a start. There's still the matter of getting the current context to cover up the tab bar buttons, and managing state between the slideout menu and modal mask.

chenr2 commented 9 years ago

For simplicity, I added a commit to the master branch that uses the approach you mentioned to close the menu when either the First or Second View Controllers are touched. Rather than adding a tap gesture, it leverages touchesBegan.

    override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
        // close the menu
        NSNotificationCenter.defaultCenter().postNotificationName("closeMenuViaNotification", object: nil)
        // dismiss the keyboard
        view.endEditing(true)
    }
ghost commented 8 years ago

Im a little late, but I used this on a project, and to close the view without the button, I create a invisible button of the size of the Right Container, make it a custom so you can leave it blank, and that button should call the closeMenu(). To work properly, you should use the scroll offset

    @IBAction func hideMenuButtonAction(sender: AnyObject) {
        if scrollView.contentOffset.x == 0 {
            closeMenu()
        }
    }
func scrollViewDidScroll(scrollView: UIScrollView) {
        if scrollView.contentOffset.x == 0 {
            hideMenuButton.hidden = false
        } else if scrollView.contentOffset.x == 260.0 {
            hideMenuButton.hidden = true
        }
    }
chenr2 commented 8 years ago

Was finally able to figure out how to get the modal mask to cover up the tab bar in this commit: https://github.com/ThornTechPublic/LeftSlideoutMenu/commit/e5e2912e091e176f4a0600dd9b035e6c00033b2c

  1. Delete the segues from the FirstViewController and SecondViewController that go to the ModalMask
  2. Create a new segue from the Tab Bar Controller, going to the ModalMask
  3. Give the new segue an Identifier of "OpenModalMask"
  4. Clear the Animates checkbox
  5. Set Kind to Modal
  6. Make sure Presentation is set to Default (important)
  7. On the Modal Mask View Controller, open the Attributes Inspector
  8. Set the Presentation to Over Current Context
  9. Within TabVCTemplate.swift, update the following line:
performSegueWithIdentifier("OpenModalMask", sender: nil)

To this line:

tabBarController?.performSegueWithIdentifier("OpenModalMask", sender: nil)

The modal now gets presented by the Tab View Controller. The presentation style is set to Over Current Context, so that it obscures the entire Tab Bar Controller.

The hardest part is setting the presentation style to Over Current Context. Normally, this is an option on the segue within the Storyboard. But if the option does not appear, you have to set it on the View Controller Attributes Inspector.