简体   繁体   中英

Swift 2 - SWRevealViewController: Remove interaction on frontview when menu is open

I've implemented SWRevealViewController for a slide-out menu in my Swift app. One issue with this framework is that when the menu (rearView) is expanded the user can still interact with the frontView. Since my frontView is a full bleed map it's very difficult to close the menu by tapping on the frontView, because instead of recognizing it as a pan/tap to close it just moves the map around.

There is the same questions for Objective-C here . The top answer from @hardluckbaby seems to be the best solution, but it's in Objective-C. I've gotten the first part of the answer working in Swift, I need help with the second part.

In my rearView controller if added these two functions which successfully disable interactions on the frontView when the rearView (menu) is open:

override func viewWillAppear(animated: Bool) {
  self.revealViewController().frontViewController.view.userInteractionEnabled = false  
}

override func viewWillDisappear(animated: Bool) {
  self.revealViewController().frontViewController.view.userInteractionEnabled = true
}

This final part I need help converting to Swift. It's suppose to re-enable the pan/tap gestures for my frontView. In my frontView I'm suppose to place the following in my ViewDidLoad function:

SWRevealViewController *revealController = [self revealViewController];
[revealController panGestureRecognizer];
[revealController tapGestureRecognizer];

How can this last part be written in Swift?

I tried adding it to this function, but it doesn't recognize my taps. Do I need to take it out of this IF statement?

override func viewDidLoad() {
   super.viewDidLoad()

   if self.revealViewController() != nil {
     self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
     self.view.addGestureRecognizer(self.revealViewController().tapGestureRecognizer())
   }
}

Found a different solution that still achieves the same result (disable interaction with frontView when rearView/menu is open). It also has an additional benefit of "dimming" the frontView to focus the user on the menu.

There is no code needed in the menuController, I removed the code in viewWillAppear and viewWillDisappear that I referenced in my question.

Below is what I added to my frontView controller. One downside is that this code needs to be included on all controllers that you want to disable interaction on when the menu is open.

Make sure to add SWRevealViewControllerDelegate to where you declare your class.

Full frontViewController code:

// make sure to add SWRevealViewControllerDelegate to the class declaration
class LocationConfirmViewController: UIViewController, SWRevealViewControllerDelegate {    

  @IBOutlet weak var menuBtn: UIBarButtonItem!

  override func viewDidLoad() {
      super.viewDidLoad()

      //menu button control
      if self.revealViewController() != nil {
        menuBtn.target = self.revealViewController()
        menuBtn.action = "revealToggle:"

        //new line to declare delegate
        self.revealViewController().delegate = self
        self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
      }
  }


  // MARK: - Navigation

  //controls the frontView when the menu is opened.
  //creates a mask that dims the view and blocks any interaction except for tap or pan to close the menu.
  func revealController(revealController: SWRevealViewController!, willMoveToPosition position: FrontViewPosition){
      let tagId = 4207868622

      if revealController.frontViewPosition == FrontViewPosition.Right {
          let lock = self.view.viewWithTag(tagId)
          UIView.animateWithDuration(0.25, animations: {
              lock?.alpha = 0
              }, completion: {(finished: Bool) in
                  lock?.removeFromSuperview()
              }
          )
          lock?.removeFromSuperview()
      } else if revealController.frontViewPosition == FrontViewPosition.Left {
          let lock = UIView(frame: self.view.bounds)
          lock.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
          lock.tag = tagId
          lock.alpha = 0
          lock.backgroundColor = UIColor.blackColor()
          lock.addGestureRecognizer(UITapGestureRecognizer(target: self.revealViewController(), action: "revealToggle:"))
          self.view.addSubview(lock)
          UIView.animateWithDuration(0.5, animations: {
              lock.alpha = 0.333
              }
          )
      }
  }
}

Credit to @mixth and his answer here to a similar question. I made some changes and added more of a description on how to exactly implement. Since I'm new to Swift I had trouble understanding his answer. Hopefully this help others.

您需要将该代码移到viewDidAppear因为viewDidLoad只会在第一次调用时调用,而其他功能将在每次视图重新显示在屏幕上时调用。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM