Capturar toques en una subvista fuera del marco de su supervisión (en varias capas)

Tengo un problema similar descrito en este hilo: Capturar toca una subview fuera del marco de su supervisa usando hitTest: withEvent:

Situación

Estamos desarrollando una aplicación en Xamarin iOS. Tenemos una vista personalizada para crear un campo de input autocompletado propio, que contiene un UiTextField y un UiTableView debajo para mostrar los resultados.

Para lograr una mejor modularidad, tenemos otra vista personalizada denominada LabeledContainer. Dentro de él, puedo establecer una label y agregar contenido a la vista inferior, que es la autocomplete en este caso.

AutoComplete LabeledContainer +---------------+ +---------------+ | UiView | | UiView | |+-------------+| |+-------------+| || UiTextField || || UiLabel || |+-------------+| |+-------------+| |+-------------+| |+-------------+| || UiTableView || || UiView || |+-------------+| |+-------------+| +---------------+ +---------------+ The following gets rendenetworking: MAINVIEW +------------------------------+ | | | | | | | | |+----------------------------+| || LabeledContainer || ||+--------------------------+|| ||| Label ||| ||+--------------------------+|| ||+--------------------------+|| ||| Content ||| |||+------------------------+||| |||| AutoComplete |||| |||+------------------------+||| ||+--------------------------+|| |+----------------------------+| | | | | | | | | +------------------------------+ 

Problema

Tengo problemas con el "hitarea" porque el menu desplegable de Autocompletar (tableView) está fuera del marco de vistas personalizado. El marco solo toma la altura del campo de input y el menu desplegable se superpone en la parte inferior. Entonces agregué el siguiente método para agregar el menu desplegable a hitArea.

 public override bool PointInside(CGPoint point, UIEvent uievent) { var bounds = Bounds; bounds.Height += DROPDOWN.Bounds.Height; return bounds.Contains(point); } 

Pero esto solo funciona si agrego mi autoComplete como subChild de mainView, porque PointInside se dispara allí. Si agrego el autocompletado al contenedor labeldo, que luego tiene una altura de marco de la label + campo de input del autocompletado, el método PointsInside nunca se dispara. Este es el caso porque el labeldo contenedor no es lo suficientemente alto, ¿verdad? Entonces PointsInside de una vista solo se activa cuando se toca la superView? Pero no puedo hacer que el contenedor labeldo o el Autocompletar sean más altos para evitar empujar otras vistas.

Traté de agregar el método PointsInside también a labeledContainer, pero no solucionó mi problema, porque no se toca el frameContainer labeldo y los PointsInside de AutoComplete nunca se llaman.

De forma pnetworkingeterminada, las UIViews no reciben events táctiles fuera de sus supervistas. Sin embargo, puede subclasificar la vista del contenedor para detectar toques fuera de su marco. La vista de contenedor debe reenviar los events táctiles no controlados a sus subvistas.

 - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { CGPoint pointForTargetView = [self.autoCompleteView convertPoint:point fromView:self]; if (CGRectContainsPoint(self.autoCompleteView.bounds, pointForTargetView)) { return [self.autoCompleteView hitTest:pointForTargetView withEvent:event]; } return [super hitTest:point withEvent:event]; } 

De la documentation de Apple :

Los puntos que se encuentran fuera de los límites del receptor nunca se informan como hits, incluso si realmente se encuentran dentro de una de las subvistas del receptor. Esto puede ocurrir si la propiedad Clips To Bounds de la vista actual está establecida en NO y la subvista afectada se extiende más allá de los límites de la vista.

Batu, muchas gracias por tu ayuda. Llegué a una solución similar con la ayuda de su sugerencia.

No estoy probando el golpe directamente en los límites de los desplegables, pero delegar el hitTest en la vista de autocomplete personalizada. Así que no tengo que hacer pública la propiedad desplegable y puedo probarlo dentro de mi vista personalizada de autocomplete.

 // Xamarin version - labeledContainer public override UIView HitTest(CGPoint p, UIEvent e) { var translatedP = AutoComplete.ConvertPointFromView(p, this); return AutoComplete.HitTest(translatedP, e) ?? base.HitTest(p, uievent); } 

Además, tengo que implementar el HitTest del autoComplete así:

 // Xamarin version - autoComplete public override UIView HitTest(CGPoint p, UIEvent e) { var translatedP = DropDown.ConvertPointFromView(p, this); return DropDown.HitTest(translatedP, e) ?? base.HitTest(p, uievent); } 

Aquí traduzco el punto del menu desplegable del resultado y verifique si está dentro de él. De lo contrario, se llama al HitTest por defecto para manejar el campo de input haga clic.