как отклонить контроллер модального представления, представленный как «Лист формы», когда касание происходит вне листа формы? - PullRequest
20 голосов
/ 09 февраля 2011

У меня есть View Controller (с UIWebView), который я представляю в стиле Form Sheet. Я должен поместить кнопку «Готово» в UIToolbar представления в контроллере вида, чтобы закрыть его. Но, поскольку представление в стиле Form Sheet оставляет много неиспользуемого пространства вне поля зрения View Controller ... Я бродил ... Есть ли способ обнаружить касание за пределами просмотра? в этой «серой» области? Заранее спасибо

Ответы [ 2 ]

18 голосов
/ 17 марта 2011

В iOS 4.2 иерархия представления приложения на основе контроллера навигации с листом модальной формы во время viewWillAppear: выглядит следующим образом.Как только модальное представление появляется, UITransitionView был заменен UIDropShadowView, который содержит модальную иерархию представления.

UIWindow
    UILayoutContainerView (regular hierarchy)
    UIDimmingView 
    UITransitionView

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

Подход 1
Мы можем вставить прозрачное представление между двумя последними подпредставлениями окна и заставить его реагировать на сенсорные события, отклоняя модальную форму.

Эта реализация проверяет, что иерархия представления окна соответствует ожидаемой, и в противном случае ничего не сделает.

Создайте и используйте DismissingView из viewWillAppear: в контроллере модального представления.

DismissingView *dismiss = [[DismissingView alloc] initWithFrame:window.frame 
                            selector:@selector(dismissView:) target:self];
[dismiss addToWindow:window];
[dismiss release];

И реализация.

@interface DismissingView : UIView {
}

@property (nonatomic, retain) id target;
@property (nonatomic) SEL selector;

- (id) initWithFrame:(CGRect)frame target:(id)target selector:(SEL)selector;

@end
@implementation DismissingView

@synthesize target;
@synthesize selector;

- (id) initWithFrame:(CGRect)frame target:(id)target selector:(SEL)selector
{
    self = [super initWithFrame:frame];

    self.opaque = NO;
    self.backgroundColor = [UIColor clearColor];
    self.selector = selector;
    self.target = target;

    return self;
}

- (void) addToWindow:(UIWindow*)window
{
    NSUInteger count = window.subviews.count;
    id v = [window.subviews objectAtIndex:count - 1];
    if (![@"UITransitionView" isEqual:NSStringFromClass([v class])]) return;
    v = [window.subviews objectAtIndex:count - 2];
    if (![@"UIDimmingView" isEqual:NSStringFromClass([v class])]) return;

    UIView *front = [window.subviews lastObject];
    [window addSubview:self];
    [window bringSubviewToFront:front];
}

- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
{
    [self removeFromSuperview];
    [target performSelector:selector withObject:self];
}

@end

Подход 2
Первый подход предпочтителен, так как у этого есть дополнительная логика для каждого события касания намодальная форма.

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

До того, как она появится, иерархия модального вида выглядит следующим образом.Когда это появляется, UIDropShadowView заменяет UITransitionView в подпредставлениях окна.UILayoutContainerView

UIDropShadowView
    UIImageView
    UILayoutContainerView
        UINavigationTransitionView
            UIViewControllerWrapperView
                UIView (the modal view)
        UINavigationBar

Реализация в основном такая же, как и раньше, с новым свойством и addToWindow:, замененным на addToWindow:modalView:.

DismissingView все еще можно добавить в окно в viewWillAppear:, поскольку UIDropShadowView заменяет UITransitionView.

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

@property (nonatomic, retain) UIView *view;

- (void) addToWindow:(UIWindow*)window modalView:(UIView*)v
{
    while (![@"UILayoutContainerView" isEqual:NSStringFromClass([v class])]) {
        v = v.superview;
        if (!v) {
            return;
        }
    }

    self.view = v;
    [window addSubview:self];
}

- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event
{
    CGPoint p = [self convertPoint:point toView:view];
    UIView *v = [view hitTest:p withEvent:event];

    return v ? v : [super hitTest:point withEvent:event];
}
0 голосов
/ 17 июня 2014

Я думаю, что правильный ответ "не делай этого"

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...