【问题标题】:SWRevealViewController close rear view when tapping front viewSWRevealViewController 在点击前视图时关闭后视图
【发布时间】:2014-04-12 02:59:14
【问题描述】:

我正在使用SWRevealViewController 在我的应用程序中实现侧导航菜单。我想让它在打开后视图时不能与前视图交互,除非当用户点击前视图时,后视图将关闭并且可以再次与前视图交互。我有这两个 SWRevealViewController 委托方法,它们当前从前视图中删除交互。

- (void)revealController:(SWRevealViewController *)revealController willMoveToPosition:    (FrontViewPosition)position {
    if(position == FrontViewPositionLeft) {
        self.view.userInteractionEnabled = YES;
    } else {
        self.view.userInteractionEnabled = NO;
    }
}

- (void)revealController:(SWRevealViewController *)revealController didMoveToPosition:    (FrontViewPosition)position {
    if(position == FrontViewPositionLeft) {
        self.view.userInteractionEnabled = YES;
    } else {
        self.view.userInteractionEnabled = NO;
    }
}

但是,当点击前视图时,这不会导致后视图关闭。任何帮助将不胜感激,谢谢!

【问题讨论】:

标签: ios objective-c swrevealviewcontroller


【解决方案1】:

如果您使用的是 SWIFT,您可以在 frontViewController 中执行以下操作:

override func viewDidLoad() {
    super.viewDidLoad()

    if self.revealViewController() != nil {

        self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
        self.view.addGestureRecognizer(self.revealViewController().tapGestureRecognizer())
    }

}

代码适用于 TAP 和 PAN 手势。

【讨论】:

  • 完美运行! Xcode 7.1, ios9, SWReveal 版本 2.4.0
  • 有谁知道如何快速测试侧边菜单是否打开?
  • 我们应该在 viewDidAppear 或 viewWillAppear 上添加@Adam 的代码以使其正常工作。
【解决方案2】:

在你的frontViewController的ViewDidLoad中你需要添加一个UITapGestureRecognizer

SWRevealViewController *revealController = [self revealViewController];
UITapGestureRecognizer *tap = [revealController tapGestureRecognizer];
tap.delegate = self;

[myView addGestureRecognizer:tap];

当点击前视图时,这应该会导致后视图关闭,这是SWRevealViewController 的默认行为。

【讨论】:

  • 这太棒了。如果有按钮可以阻止您的关闭点击,请在前面添加一个虚拟视图。
  • 有一个 SWRevealViewController 的分支:nsrover.wordpress.com/2014/08/06/…
  • 有人可以建议任何方法,如何覆盖 SWRevealViewController 的滑动手势以作用于前视图上的其他手势,例如当用户从屏幕边缘滑动时滚动视图?
【解决方案3】:

编辑: 更改 UIView 的 autoresizingMask 以适应 Swift 2,感谢 Marroccomment

这是@avdyushin 答案的Swift-SWRevealViewController 2.x 版本:

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.75, animations: {
                lock.alpha = 0.333
            }
        )
    }
}

【讨论】:

  • 如果你使用 Swift 2,将 "lock.autoresizingMask" 行更改为: lock.autoresizingMask = [UIViewAutoresizing.FlexibleWidth, UIViewAutoresizing.FlexibleHeight]
  • 正确而简单的答案具有相当有用的逻辑,除此之外也可以应用于许多地方。
  • @mixth 。对我来说,为什么根本没有调用 willMoveToPosition 你能帮我解释为什么会发生这种情况
【解决方案4】:
  1. SWRevealViewController 的子类。
  2. 实现revealController:willMoveToPosition: of SWRevealViewControllerDelegate
  3. 在前视图控制器上设置全屏视图以覆盖所有触摸。
  4. 添加点击手势识别器以隐藏菜单。

带有漂亮动画的示例:

- (void)revealController:(SWRevealViewController *)revealController willMoveToPosition:(FrontViewPosition)position;
{
    static NSInteger tagLockView = 4207868622;
    if (revealController.frontViewPosition == FrontViewPositionRight) {
        UIView *lock = [self.frontViewController.view viewWithTag:tagLockView];
        [UIView animateWithDuration:0.25 animations:^{
            lock.alpha = 0;
        } completion:^(BOOL finished) {
            [lock removeFromSuperview];
        }];
    } else if (revealController.frontViewPosition == FrontViewPositionLeft) {
        UIView *lock = [[UIView alloc] initWithFrame:self.frontViewController.view.bounds];
        lock.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
        lock.tag = tagLockView;
        lock.backgroundColor = [UIColor blackColor];
        lock.alpha = 0;
        [lock addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(revealToggle:)]];
        [self.frontViewController.view addSubview:lock];
        [UIView animateWithDuration:0.75 animations:^{
            lock.alpha = 0.333;
        }];
    }
}

此解决方案适用于旧版本 1.x SWRevealViewController。

【讨论】:

    【解决方案5】:

    考虑一下这个简单的解决方案,效果很好

    private let DimmingViewTag = 10001
    
    extension UIViewController: SWRevealViewControllerDelegate {    
    
        func setupMenuGestureRecognizer() {
    
            revealViewController().delegate = self
    
            view.addGestureRecognizer(revealViewController().panGestureRecognizer())
            view.addGestureRecognizer(revealViewController().tapGestureRecognizer())
        }
    
        //MARK: - SWRevealViewControllerDelegate
    
        public func revealController(revealController: SWRevealViewController!, didMoveToPosition position: FrontViewPosition) {
    
            if case .Right = position {
    
                let dimmingView = UIView(frame: view.frame)
                dimmingView.tag = DimmingViewTag
    
                view.addSubview(dimmingView)
                view.bringSubviewToFront(dimmingView)
    
            } else {
                view.viewWithTag(DimmingViewTag)?.removeFromSuperview()
            }
        }
    }
    

    UIViewController中的简单用法:

    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)
    
        setupMenuGestureRecognizer()
    }
    

    【讨论】:

      【解决方案6】:

      将下面的代码放在菜单视图控制器上它对我有用

      @interface SidebarTableViewController() {
          UIView* coverView;
      }
      
      - (void)viewWillDisappear:(BOOL)animated {
          [coverView removeFromSuperview];
          //[self.revealViewController.frontViewController.view setUserInteractionEnabled:YES];
          // get your window screen size
      }
      
      - (void)viewWillAppear:(BOOL)animated {
          // get your window screen size
          CGRect screenRect = [[UIScreen mainScreen] bounds];
          //create a new view with the same size
          coverView = [[UIView alloc] initWithFrame:screenRect];
          // change the background color to black and the opacity to 0.6
          coverView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.6];
          // add this new view to your main view
          [self.revealViewController.frontViewController.view addSubview:coverView];
          // [self.revealViewController.frontViewController.view setUserInteractionEnabled:NO];
      }
      

      【讨论】:

        【解决方案7】:

        感谢mixthavdyushin 的大力帮助。这是从那里获得的 Swift 4 版本,可以节省您的几个小时:

        extension UIViewController: SWRevealViewControllerDelegate {
        
        func setupMenuGestureRecognizer() {
        
            revealViewController().delegate = self
        
            view.addGestureRecognizer(revealViewController().panGestureRecognizer())
            view.addGestureRecognizer(revealViewController().tapGestureRecognizer())
        }
        
        //MARK: - SWRevealViewControllerDelegate
        public func revealController(_ revealController: SWRevealViewController!, willMoveTo position: FrontViewPosition) {
            let tagId = 112151
            print("revealController delegate called")
            if revealController.frontViewPosition == FrontViewPosition.right {
                let lock = self.view.viewWithTag(tagId)
                UIView.animate(withDuration: 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.black
                lock.addGestureRecognizer(UITapGestureRecognizer(target: self.revealViewController(), action: #selector(SWRevealViewController.revealToggle(_:))))
                self.view.addSubview(lock)
                UIView.animate(withDuration: 0.75, animations: {
                    lock.alpha = 0.333
                }
                )
            }
        }
        
        }
        

        现在从后视控制器的 viewDidLoad 调用此函数 setupMenuGestureRecognizer

        或者您也可以直接在您的后视控制器类中实现 SWRevealViewControllerDelegate,并在类本身中使用 SWRevealViewControllerDelegate 函数。

        【讨论】:

        • 多么棒的解决方案,没有比这更好的了。非常感谢。
        • @ArafinRussell 谢谢✌?
        【解决方案8】:

        我使用了tapGestureRecognizer,但还是有一些问题。我试过了,效果很好!

        定义类:

        @interface IgnoreView : UIView
        
        @property (nonatomic, assign) BOOL shouldAllTouchesBeForMe;
        
        @end
        

        实现:

        @implementation IgnoreView
        
        - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
        {
            if( self.shouldAllTouchesBeForMe ){
                return self;
            }
            return [super hitTest:point withEvent:event];
        }
        
        @end
        

        然后在 IgnoreView 类的 Interface Builder 中创建您的 View 类

        然后,在您的 ViewController 中执行以下操作:

        在 - viewDidLoad

        self.revealViewController.delegate = self;
        [self.view addGestureRecognizer:self.revealViewController.tapGestureRecognizer];
        

        你的视图控制器中的实现也是:

        - (void)revealController:(SWRevealViewController *)revealController didMoveToPosition:(FrontViewPosition)position
        {
            IgnoreView *i = (id)self.view;
            i.shouldAllTouchesBeForMe = position == FrontViewPositionRight;
        }
        

        一切就绪!

        【讨论】:

          【解决方案9】:

          在您的 菜单视图控制器上,添加:

          -(void)viewWillAppear:(BOOL)animated {
              [super viewWillAppear:animated];
          
              [self.revealViewController.frontViewController.view setUserInteractionEnabled:NO];
          }
          
          -(void)viewDidDisappear:(BOOL)animated {
              [super viewDidDisappear:animated];
          
              [self.revealViewController.frontViewController.view setUserInteractionEnabled:YES];
          }
          

          然后在您的 Menu Item View Controller 上,将其添加到 viewDidLoad

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

          还请查看我的回答 here。它解决了前视图交互(加上滑动手势)的问题。

          【讨论】:

          • 正因为如此,菜单不会因为一切都被禁用而隐藏起来!!!你有“运气不好的宝贝”。
          猜你喜欢
          • 2015-07-03
          • 2017-01-14
          • 2014-05-01
          • 2017-01-19
          • 2015-07-01
          • 2017-08-22
          • 2017-01-16
          • 1970-01-01
          • 2017-05-24
          相关资源
          最近更新 更多