Подтвердить что ты не робот

Отклонить вид листа модальной формы на внешнем кране iOS 8

Я пытаюсь отклонить вид листа модальной формы на внешнем кране на iOS 8 без везения, Я пробовал этот код

UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapBehind:)];

[recognizer setNumberOfTapsRequired:1];
recognizer.cancelsTouchesInView = NO; //So the user can still interact with controls in the modal view
[self.view.window addGestureRecognizer:recognizer];

- (void)handleTapBehind:(UITapGestureRecognizer *)sender
{

if (sender.state == UIGestureRecognizerStateEnded)
 {
   CGPoint location = [sender locationInView:nil]; //Passing nil gives us coordinates in the window

 //Then we convert the tap location into the local view coordinate system, and test to see if it in or outside. If outside, dismiss the view.

    if (![self.view pointInside:[self.view convertPoint:location fromView:self.view.window] withEvent:nil]) 
    {
       // Remove the recognizer first so it view.window is valid.
      [self.view.window removeGestureRecognizer:sender];
      [self dismissModalViewControllerAnimated:YES];
    }
 }
}

Но он не обнаруживает внешние клики, любые предложения?

4b9b3361

Ответ 1

В iOS 8 есть две проблемы. Во-первых, распознавание жестов не начинается.

Я решил это, добавив протокол UIGestureRecognizerDelegate и выполнив

-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer*)otherGestureRecognizer
{
    return YES;
}

Кроме того, не забудьте зарегистрировать делегат с помощью

recognizer.delegate = self;

Теперь распознаватель жестов распознает жесты, и будет вызываться целевой метод (handleTapBehind:).

Вот вторая проблема в iOS 8: locationInView:, похоже, не учитывает ориентацию устройства, если в качестве представления передано nil. Вместо этого выполняется прохождение корневого представления.

Здесь мой целевой код, который работает для iOS 7.1 и 8.0:

if (sender.state == UIGestureRecognizerStateEnded) {
    UIView *rootView = self.view.window.rootViewController.view;
    CGPoint location = [sender locationInView:rootView];
    if (![self.view pointInside:[self.view convertPoint:location fromView:rootView] withEvent:nil]) {
        [self dismissViewControllerAnimated:YES completion:^{
            [self.view.window removeGestureRecognizer:sender];
        }];
    }
}

Ответ 2

В iOS 8 вы можете посмотреть новый класс UIPresentationController. Это дает вам лучший контроль над контейнером вокруг вашего пользовательского представления диспетчера представлений (позволяя вам правильно добавить собственный распознаватель жестов).

Вот ссылка на довольно простой учебник: http://dativestudios.com/blog/2014/06/29/presentation-controllers/

Затем добавьте затемнение для уменьшения яркости:

    UITapGestureRecognizer *singleFingerTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)];
    [self.dimmingView addGestureRecognizer:singleFingerTap];


- (void)handleSingleTap:(UITapGestureRecognizer *)recognizer {
    [self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
}

Ответ 3

Swift 3.1 решение, которое работает как в портретной, так и в альбомной ориентации.

class TapBehindModalViewController: UIViewController, UIGestureRecognizerDelegate {
    private var tapOutsideRecognizer: UITapGestureRecognizer!

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        if(self.tapOutsideRecognizer == nil) {
            self.tapOutsideRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.handleTapBehind))
            self.tapOutsideRecognizer.numberOfTapsRequired = 1
            self.tapOutsideRecognizer.cancelsTouchesInView = false
            self.tapOutsideRecognizer.delegate = self
            self.view.window?.addGestureRecognizer(self.tapOutsideRecognizer)
        }
    }

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

        if(self.tapOutsideRecognizer != nil) {
            self.view.window?.removeGestureRecognizer(self.tapOutsideRecognizer)
            self.tapOutsideRecognizer = nil
        }
    }

    func close(sender: AnyObject) {
        self.dismiss(animated: true, completion: nil)
    }

    // MARK: - Gesture methods to dismiss this with tap outside
    func handleTapBehind(sender: UITapGestureRecognizer) {
        if (sender.state == UIGestureRecognizerState.ended) {
            let location: CGPoint = sender.location(in: self.view)

            if (!self.view.point(inside: location, with: nil)) {
                self.view.window?.removeGestureRecognizer(sender)
                self.close(sender: sender)
            }
        }
    }

    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }
}