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