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

Как отклонить контроллер модального представления, представленный как "Лист формы", когда прикосновение происходит за пределами листа формы?

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

4b9b3361

Ответ 1

В 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 в окнах subviews. 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];
}

Ответ 2

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