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
}