20 votos

¿Cómo despedir a un controlador de vista modal presentado como "Hoja de formulario" cuando un toque fuera de la hoja formulario?

Tengo un controlador de vista (con un UIWebView) presento en estilo hoja de formulario. Tengo que poner un botón "Listo" en la UIToolbar de la vista en el controlador de vista que se despidió. Pero, desde que presenta él en estilo de la "hoja formulario" deja mucho espacio no utilizado fuera de la vista del controlador de vista... Yo estaba vagando... ¿Hay una manera de detectar un toque fuera de la vista? ¿en esa zona "atenuada"? Gracias de antemano

18voto

Lachlan Roche Puntos 16456

En iOS 4.2, el punto de vista de la jerarquía de Navegación de Controlador de base de la aplicación con un formulario modal de la hoja es como sigue durante viewWillAppear:. Una vez que el modal aparece la vista, el UITransitionView ha sido sustituido por un UIDropShadowView que contiene el valor modal de la vista de jerarquía.

UIWindow
    UILayoutContainerView (regular hierarchy)
    UIDimmingView 
    UITransitionView

Apple advertir en contra de confiar en las subvistas de vistas, ya que estos son considerados privados y puede cambiar en futuras versiones. Esto podría romper su aplicación.

Enfoque 1
Podemos insertar una visión transparente entre los dos últimos subvistas de la ventana, y tienen que responder a eventos de toque por la que desestimaba el formulario modal.

Esta aplicación comprueba que la visualización de la ventana de jerarquía es el esperado, y silenciosamente, no hacer nada si no.

Crear y utilizar DismissingView de viewWillAppear: en el modal de controlador de vista.

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

Y la aplicación.

@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

Enfoque 2
El primer método es el preferido, ya que este tiene más lógica para cada evento de toque en el formulario modal.

Agregar el transparente a la vista como la vista frontal de la ventana. Eventos de toque dentro de los modales de vista del marco se pasa, y los que están fuera del marco de despedir el formulario modal.

Antes de que aparezca el valor modal de la vista de jerarquía se parece a esto. Cuando aparece, la UIDropShadowView sustituye a la UITransitionView en la ventana del subvistas. El UILayoutContainerView

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

La aplicación es prácticamente el mismo que antes, con una nueva propiedad y addToWindow: reemplazado por addToWindow:modalView:.

DismissingView todavía puede ser añadido a la ventana en viewWillAppear:, desde el UIDropShadowView sustituye a la UITransitionView.

De nuevo nos silencio no hacer nada si la jerarquía no es el esperado.

@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];
}

-4voto

Ethical Paul Puntos 666

Creo que la respuesta correcta es, "no hacerlo"

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X