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

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

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

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

15 ответов

Решение

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

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

на viewWillAppear:

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

и при просмотре исчезнет:

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

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

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

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

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

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

на viewWillAppear:

[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];
}

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

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

Назначить 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

Версия Swift для ответа @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()
    }
}

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

Есть 2 этапа:

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

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

}

В методе viewWillAppear вашего контроллера элементов меню, просто создайте кнопку наложения на виде спереди и установите действие для showToggle: ofViewViewController

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

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

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

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

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

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

Есть 2 этапа:

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;

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

Дополнение к hardluckbaby ответа.

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

на viewWillAppear:

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

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

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

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

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

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

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

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

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

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

Во-первых, просто установите свой делегат: 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;
        }];
    }

}
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.
    }
Другие вопросы по тегам