– implementación para reenviar events

Tengo una window personalizada (que debería estar encima de todo, incluido el keyboard) para mostrar una cosa de superposition, algo así como la superposition que ves cuando presionas los botones de upload / bajar el volumen del dispositivo.

Así que hice una window personalizada OverlayWindow hasta ahora todo funciona bien y las windows en la parte posterior están recibiendo sus events normalmente. Sin embargo, hitTest:withEvent: se hitTest:withEvent: varias veces y, a veces, incluso devuelve nil. Me pregunto si eso es normal / correcto? Si no, ¿cómo puedo arreglar eso?

 // A small (WIDTH_MAX:100) window in the center of the screen. If it matters const CGSize screenSize = [[UIScreen mainScreen] bounds].size; const CGRect rect = CGRectMake(((int)(screenSize.width - WIDTH_MAX)*0.5),       ((int)(screenSize.height - WIDTH_MAX)*0.5), WIDTH_MAX, WIDTH_MAX); overlayWindow = [[CustomWindow alloc] initWithFrame:rect]; overlayWindow.windowLevel = UIWindowLevelStatusBar; //1000.0 overlayWindow.hidden = NO; // I don't need it to be the key (no makeKeyAndVisible) 

 - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { // Find the front most window (with the highest window level) and // call this method on that window. It should will make the event be // forwarded to it // Situation1: This method is called twice (or even more, it depend // on the number of windows the app has) per event: Why? Is this the // *normal* behaviour? NSLog(@" "); NSLog(@"Point: %@ Event: %p\n", NSStringFromCGPoint(point), event); UIView *view = nil; if (CGRectContainsPoint(self.bounds, point)) { NSLog(@"inside window\n"); NSArray *wins = [[UIApplication shanetworkingApplication] windows]; __block UIWindow *frontMostWin = nil; [wins enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { NSLog(@"win: %@\n", obj); if ([obj windowLevel] >= [frontMostWin windowLevel] && obj != self) { frontMostWin = obj; } }]; NSLog(@"frontMostWindow:%@\n finding a new view ...\n", frontMostWin); CGPoint p = [frontMostWindow convertPoint:point fromWindow:self]; view = [frontMostWindow hitTest:p withEvent:event]; // Situation2: sometimes view is nil here, Is that correct? } NSLog(@"resultView: %@\n", view); return view; } 

EDITAR:

También he notado eso

  1. if hitTest:withEvent: siempre devuelve nil también funciona. Esto es solo cuando overlayWindow.hidden = NO;

  2. si [overlayWindow makeKeyAndVisible] devolverá nil en hitTest:withEvent: no siempre funciona. Parece que una window key requiere una implementación adecuada del método de testing de éxito.

¿Me estoy perdiendo algo sobre el reenvío de events aquí?

¿FrontMostWindow significa frontMostWin?

Parece que incluso si usamos solo una UIWindow, hitTest:withEvent: se ejecutará en ella al less 2 veces. Entonces, supongo que es normal.

Puedes recibir null en

 view = [frontMostWindow hitTest:p withEvent:event]; 

debido a los siguientes motivos:

  • frontMostWindow es nulo (como ejemplo, si solo tiene una window)
  • p es ouside frontMostWindow bounds (como ejemplo, cuando frontMostWindow es el keyboard y su toque está en otro lugar)
  • frontMostWindow tiene la propiedad userInteractionEnabled establecida en NO;

hitTest: withEvent: la llamada varias veces es normal. Esto probablemente se deba a que solo muestra una UILabel o UIImageView en la window superpuesta y, por lo tanto, los toques se guardan automáticamente.

Sin embargo, creo que realmente no necesitas otra OverlayWindow, en su lugar podrías considerar una UIView en la parte superior de keyWindow. Esto debería hacer que tu aplicación sea más limpia …

Me enfrenté al mismo problema.

Traté de resolverlo basado en tu publicación y encontré otra solución.

Este código se implementó en superposition uiwindow en la parte superior.

Este código pasará events a través de la window inferior cuando el área no tenga vista.

 - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { NSLog(@" "); NSLog(@"Point: %@ Event: %p\n", NSStringFromCGPoint(point), event); UIView *view = nil; UIView *resultView = [super hitTest:point withEvent:event]; if (resultView == self) { NSLog(@"touched in transparent window !!"); return nil; } else { NSLog(@"touched in view!!"); return resultView; } return resultView; }