SWRevealViewController закрывает вид сзади при нажатии на вид спереди
Я использую 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;
}
}
Однако это не приводит к закрытию заднего вида при касании переднего вида. Любая помощь будет принята с благодарностью, спасибо!
9 ответов
Если вы используете 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.
В ViewDidLoad вашего frontViewController вам нужно добавить UITapGestureRecognizer
SWRevealViewController *revealController = [self revealViewController];
UITapGestureRecognizer *tap = [revealController tapGestureRecognizer];
tap.delegate = self;
[myView addGestureRecognizer:tap];
Это должно привести к закрытию заднего вида при постукивании переднего вида, которое SWRevealViewController
поведение по умолчанию.
РЕДАКТИРОВАТЬ: Измените autoivizingMask UIView, чтобы соответствовать Swift 2, благодаря комментарию Marcoc
Это версия Swift-SWRevealViewController 2.x ответа @avdyushin:
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
}
)
}
}
- Подкласс
SWRevealViewController
, - Воплощать в жизнь
revealController:willMoveToPosition:
изSWRevealViewControllerDelegate
, - Установите полноэкранный режим на контроллере переднего вида, чтобы отменить все касания.
- Добавить распознаватель жестов, чтобы скрыть меню.
Пример с хорошей анимацией:
- (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.
Рассмотрим это простое решение, отлично работает
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()
}
Поместите ниже код в меню просмотра контроллера, он работает для меня
@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];
}
Спасибо mixth & avdyushin за avdyushin помощь. Вот версия 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
}
)
}
}
}
Теперь вызовите эту функцию setupMenuGestureRecognizer из viewDidLoad вашего контроллера заднего вида.
Или вы можете также реализовать SWRevealViewControllerDelegate непосредственно в своем классе контроллера заднего вида и использовать функцию SWRevealViewControllerDelegate в самом классе.
Я использовал 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
Затем создайте свой класс View в Интерфейсном Разработчике класса IgnoreView
Затем в вашем ViewController выполните:
в - viewDidLoad
self.revealViewController.delegate = self;
[self.view addGestureRecognizer:self.revealViewController.tapGestureRecognizer];
Реализация в вашем viewcontroller также:
- (void)revealController:(SWRevealViewController *)revealController didMoveToPosition:(FrontViewPosition)position
{
IgnoreView *i = (id)self.view;
i.shouldAllTouchesBeForMe = position == FrontViewPositionRight;
}
И все готово!
На вашем контроллере представления меню, добавьте это:
-(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];
}
Затем на вашем контроллере представления элементов меню добавьте это в viewDidLoad:
SWRevealViewController *revealController = [self revealViewController];
[revealController tapGestureRecognizer];
Также проверьте мой ответ здесь. Он решает проблему взаимодействия с видом спереди (плюс жест слайда).