SWRevealViewController: удалять взаимодействие на лицевой панели при обнаружении заднего обзора

Мне нужно отключить взаимодействие с пользователем при просмотре заднего вида. Нашли некоторые другие, которые задавали одно и то же, но не могут понять, где и как реализовать код, который я видел.

Пример: я нашел этот код из link,

- (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;
    } 
}

Также найдено несколько других ссылок

У меня есть этот код, но не совсем уверен в правильном месте для вставки этого кода. Я попытался добавить его в свои виды спереди и сзади, а также в методе SWRevealViewController без успеха

Цените, если кто-то может указать мне в правильном направлении.

Ответы

Ответ 1

Недавно я придумал решение, которое я хотел бы разделить (извините, если он опоздал на 2 месяца).

Чтобы отключить взаимодействие с пользователем в режиме Front View при открытии меню, я добавил следующие коды на мой MenuViewController:

в представленииWillAppear:

[self.revealViewController.frontViewController.view setUserInteractionEnabled:NO];

и на viewWillDisappear:

[self.revealViewController.frontViewController.view setUserInteractionEnabled:YES];

Это отключит все пользовательские взаимодействия на Front View Controller, что означает, что жесты слайда/нажатия для ЗАКРЫТИЯ меню также будут отключены.

Теперь я создал ParentViewController и сделал все контроллеры представлений (элементы меню) подклассом.

на моем viewDidLoad, я поместил следующие коды:

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

Если вы запустите свое приложение в этот момент, похоже, что "Жест жестокости" работает (кратковременное нажатие на Front View закрывает меню), но не "Жест". Я не уверен, почему это так, но чтобы включить слайд-жест, чтобы ЗАКРЫТЬ свое меню, добавьте следующий код в свой MenuViewController:

в представленииWillAppear:

[self.revealViewController.view addGestureRecognizer:self.revealViewController.panGestureRecognizer];

Подводя итог, вот что вам нужно:

На вашем MenuViewController:

-(void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    [self.revealViewController.frontViewController.view setUserInteractionEnabled:NO];
    [self.revealViewController.view addGestureRecognizer:self.revealViewController.panGestureRecognizer];
}

-(void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];

    [self.revealViewController.frontViewController.view setUserInteractionEnabled:YES];
}

И в контроллере просмотра элементов вашего меню (вы можете сделать ParentViewController для всех из них):

-(void)viewDidLoad {
    [super viewDidLoad];

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

Надеюсь, это поможет!

Ответ 2

Я использовал другой подход для достижения того же результата, если не уверен, что он помогает.

Назначить SWRevealViewControllerDelegate AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    SWRevealViewController* reveal = (SWRevealViewController*)self.window.rootViewController;
    reveal.delegate = self;

    // other bootstrapping code
}

а затем в методе делегат -(void)revealController:(SWRevealViewController *)revealController willMoveToPosition:(FrontViewPosition)position, как показано ниже:

-(void)revealController:(SWRevealViewController *)revealController willMoveToPosition:(FrontViewPosition)position
{
    if(position == FrontViewPositionLeft){
        [revealController.frontViewController.view setUserInteractionEnabled:YES];
        [revealController.frontViewController.revealViewController tapGestureRecognizer];
    }else{
        [revealController.frontViewController.view setUserInteractionEnabled:NO];
    }
}

ОБНОВЛЕНО: добавлена ​​эта строка [revealController.frontViewController.revealViewController tapGestureRecognizer], чтобы закрыть обнаруженный контроллер при нажатии на frontviewcontroller

Ответ 3

Эй, ребята, как пояснил Джон: Хотя эти решения действительно работают, я не думаю, что кто-то из них обращается к исходному вопросу, что на самом деле довольно просто:

Есть два шага:

1) Добавьте в свой FrontViewController.m следующие методы:

- (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;
    } 
}

2) Сделайте свой контроллер переднего плана делегатом SWRevealViewController в файле FrontViewController.h:

(например, @interface HomeViewController: UIViewController) где мой FrontViewController был назван HomeViewController

а также в файле FrontViewController.m со ссылкой на ViewDidLoad:

self.revealViewController.delegate = self; Задача решена! Гораздо проще, чем создавать родительские классы и т.д.

Это поможет вам решить пользовательские взаимодействия для контроллера FrontView. Я просто добавлю следующее изменение, взятое из ответа Xun, также выше, и вы будете решать как пользовательские взаимодействия, так и меню скрыть, когда пользователь кранит FrontViewController.

- (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;
      //Hides the menu when user taps FrontViewController
       [revealController.frontViewController.revealViewController tapGestureRecognizer];
    } 
}

Ответ 4

Добавить вид в виде спереди, когда вид сзади открыт.

Ответ 5

В режиме viewWillAppear вашего контроллера элементов меню. Просто создайте кнопку наложения на лицевом экране и установите действие для обнаруженияToggle: из showViewController

-(void)viewWillAppear:(BOOL)animated 
{
    [super viewWillAppear:animated];
    overlayView = [UIButton buttonWithType:UIButtonTypeCustom];
    overlayView.frame = self.revealViewController.frontViewController.view.bounds;
    overlayView.backgroundColor = [UIColor colorWithWhite:0.5 alpha:0.8];
    overlayView.tag = 999;
    [overlayView addTarget:self.revealViewController action:@selector(revealToggle:) forControlEvents:UIControlEventTouchUpInside];
    [overlayView addTarget:self.revealViewController action:@selector(revealToggle:) forControlEvents:UIControlEventTouchDragOutside];
    [self.revealViewController.frontViewController.view addSubview:overlayView];
}

В методе openTogglle удалите кнопку наложения, если таковая имеется:

- (void)revealToggleAnimated:(BOOL)animated
{
    UIButton *overlayView = (UIButton*)[self.view viewWithTag:999];
    if (overlayView) {
        [overlayView removeFromSuperview];
        overlayView = nil;
    }
    // rest of the code...
}

Ответ 6

Хотя эти решения действительно работают, я не думаю, что кто-либо из них обращается к исходному вопросу, что на самом деле довольно просто:

Есть два шага:

1) Добавьте в свой FrontViewController.m следующие методы:

- (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;
    } 
}

2) Сделайте свой контроллер переднего вида делегатом SWRevealViewController в файле FrontViewController.h:

(e.g. @interface HomeViewController : UIViewController <SWRevealViewControllerDelegate>)

где мой FrontViewController был назван HomeViewController

а также в файле FrontViewController.m со следующим: ViewDidLoad:

self.revealViewController.delegate = self;

Проблема решена! Гораздо проще, чем создавать родительские классы и т.д.

Ответ 7

Другой способ состоит в том, чтобы иметь оверлейный вид при обнаружении заднего вида. Вы можете использовать эту обновленную библиотеку https://github.com/NSRover/SWRevealViewController и убедитесь, что вы включили shouldUseFrontViewOverlay = true при обнаружении заднего вида.

Ответ 8

Быстрая версия для ответа @hardluckbaby:

В MenuViewController (Контроллер заднего вида):

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)

    self.revealViewController().frontViewController.view.userInteractionEnabled = false
    self.revealViewController().view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
}

override func viewWillDisappear(animated: Bool) {
    super.viewWillDisappear(animated)

    self.revealViewController().frontViewController.view.userInteractionEnabled = true
}

В FrontViewController (вы можете сделать ParentViewController для всех ваших контроллеров переднего вида, как сказал @hardluckbaby):

override func viewDidLoad() {
    super.viewDidLoad()

    if let revealController = self.revealViewController() {
        revealController.panGestureRecognizer()
        revealController.tapGestureRecognizer()
    }
}

Ответ 9

On MenuTableViewController/ Rear VC, add SWRevealViewControllerDelegate.

    override func viewDidLoad() {
        super.viewDidLoad()
        self.revealViewController().delegate = self

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

Add this delegate method.

func revealController(revealController: SWRevealViewController!, didMoveToPosition position: FrontViewPosition) {
        if(position.rawValue == 4)
        {
            //move to rear
            self.revealViewController().frontViewController.view.userInteractionEnabled =  false
        }
        else if (position.rawValue == 3)
        {
            //move to front - dashboard VC
            self.revealViewController().frontViewController.view.userInteractionEnabled =  true
        }
    }
    func revealController(revealController: SWRevealViewController!, willMoveToPosition position: FrontViewPosition) {

//will perform the same function as the above delegate method.
    }

Ответ 10

class SideMenuViewController: UITableViewController {

  override func viewDidLoad() {
    super.viewDidLoad()
    self.revealViewController().delegate = self
  }

}

extension SideMenuViewController: SWRevealViewControllerDelegate {

  func revealController(revealController: SWRevealViewController!, willMoveToPosition position: FrontViewPosition) {
    if position == .Left {
      revealController.frontViewController.view.userInteractionEnabled = true
    }

    if position == .Right {
      revealController.frontViewController.view.userInteractionEnabled = false
    }
  }

}

Ответ 11

Рассмотрим следующее решение, отлично работает

private let DimmingViewTag = 10001

extension UIViewController: SWRevealViewControllerDelegate {    

    func removeInteractionFromFrontViewController() {

        revealViewController().delegate = self

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

    //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)

    removeInteractionFromFrontViewController()
}

Ответ 12

Дополнить hardluckbaby ответ.

Если вы запустите свое приложение в этот момент, похоже, что Tap Жест работает (нажмите на Вид спереди, закройте меню), но НЕ "Жест Пан". Я не уверен, почему это так, но для того, чтобы жест слайдов, чтобы ЗАКРЫТЬ меню, добавьте следующий код в свой MenuViewController:

в представленииWillAppear:

[self.revealViewController.view addGestureRecognizer:self.revealViewController.panGestureRecognizer];

Он добавляет некоторое нежелательное поведение, например. жест передвижения закрывает вид сзади при запуске.

Жест жесткого диска по умолчанию может не работать, если вы добавили его в свой собственный вид где-нибудь, что-то вроде viewDidLoad вашего контроллера внешнего вида:

[self.view addGestureRecognizer:self.revealViewController.panGestureRecognizer];

Удалите такие строки, и это должно работать так, как ожидалось, для жесты панорамирования и касания

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

Ответ 13

Я использовал функции viewWillAppear и viewWillDisappear, но поскольку у меня есть subviews для почти каждого элемента в боковом меню, которое у меня было. Моя проблема заключалась в том, что у меня было активное поле ввода (отображение клавиатуры) и доступ к боковому меню. В корневом меню клавиатура спряталась, но после того, как я ввел клавиатуру подменю, снова появился. Чтобы решить эту проблему, я изменил подход к включению и отключению взаимодействия в opensController следующим образом:

- (void)revealController:(SWRevealViewController *)revealController 
        didMoveToPosition:(FrontViewPosition)position {
    if (position == FrontViewPositionRight) {
        [self.revealViewController.frontViewController.view setUserInteractionEnabled:NO];
    } else if (position == FrontViewPositionLeft) {
        [self.revealViewController.frontViewController.view setUserInteractionEnabled:YES];
    }
}

Ответ 14

Сначала просто установите делегат:  self.revealViewController.delegate = self; и метод делегата приведен ниже:

- (void)revealController:(SWRevealViewController *)revealController willMoveToPosition:(FrontViewPosition)position
{
    static NSInteger tagLockView = 123456789;
    if (revealController.frontViewPosition == FrontViewPositionRight)
    {
        UIView *lockView = [self.view viewWithTag:tagLockView];

        [UIView animateWithDuration:0.3 animations:^{
            lockView.alpha = 0;
        } completion:^(BOOL finished) {
            [lockView removeFromSuperview];
        }];
    }
    else if (revealController.frontViewPosition == FrontViewPositionLeft)
    {
        UIView *lockView = [[UIView alloc] initWithFrame:self.view.bounds];
        lockView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
        lockView.tag = tagLockView;
        lockView.backgroundColor = [UIColor blackColor];
        lockView.alpha = 0;
        [lockView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self.revealViewController action:@selector(revealToggle:)]];
        [self.view addSubview:lockView];
        [UIView animateWithDuration:0.3 animations:^{
            lockView.alpha = 0.5;
        }];
    }

}

Ответ 15

Swift 3.0 простой и быстрый метод.

Код Frontviewcontoller здесь...

override func viewDidLoad() {
    super.viewDidLoad()
     if self.revealViewController() != nil {
        let rewel:SWRevealViewController  = revealViewController()
        rewel.panGestureRecognizer()
        rewel.tapGestureRecognizer() 
    }
}

Код SideDrowerviewcontoller здесь...

override func viewWillAppear(_ animated: Bool) {
  let rewel = self.revealViewController()
      rewel?.frontViewController.view.isUserInteractionEnabled = false
    rewel?.frontViewController.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
}

override func viewWillDisappear(_ animated: Bool) {
    let rewel = self.revealViewController()
        rewel?.frontViewController.view.isUserInteractionEnabled = true
}