es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

“Intercepción de clicks de UIButton por capa programática”

Estoy trabajando en una aplicación que incluye la pantalla mostrada a continuación. El panel con la vista en lista se instancia desde un Nib, pero el panel gris claro con el dibujo en él es una UIView generada dinámicamente, que es una subvista de una subclase de UIView llamada FrameView (para los propósitos de la pregunta).

El punto rojo en la esquina es un botón de eliminación para ese dibujo. El dibujo es el contenido de un objeto de dibujo, que tiene una relación muchos a muchos con el elemento seleccionado en la lista. Cuando selecciono un elemento en la lista, se agregan cero o más paneles de este tipo, que muestran los dibujos para ese elemento, como subvistas de FrameView.

Para que esos botones de eliminación sean seleccionables, FrameView tiene la interacción del usuario habilitada. Esto sucede cuando selecciono un elemento en la lista. Está desactivada cuando FrameView aparece por primera vez.

En la esquina inferior izquierda está el botón de navegación principal. Tiene una variedad de gestos y clics asociados, que permiten al usuario moverse entre diferentes editores que usan la pantalla principal. Este botón tiene una posición z relativamente alta en la vista principal.

Pero una vez que FrameView tiene su interacción de usuario habilitada, impide que los clics y gestos lleguen al botón de navegación.

Habría pensado que aumentar la posición z del botón de navegación por encima de FrameView solucionaría el problema, pero no lo hace. ¿Cómo puedo hacer que el botón de navegación reciba toques y gestos, incluso cuando FrameView tiene la interacción del usuario habilitada? ¿O estoy haciendo esto de la manera equivocada?

EDITAR: Me referí a mencionar que el botón de navegación es el único elemento agregado a través de Storyboard, en caso de que importe.

EDITAR 2: después de jugar un poco, estoy anulando el hitTest, por lo que:

override func hitTest (_ point: CGPoint, with event: UIEvent?) -> UIView? {
let view = super.hitTest (point, with: event)
return view == self? Nil: view
}

Esto no se obtuvo de SO, y aunque hubo algunas respuestas aquí que sugerían vagamente este enfoque, eran (como es común en SO) a) asociadas con versiones obsoletas de Swift, b) enterradas en diferentes contextos y c) no se encontraron en ninguna búsqueda obvia.

Este sitio tiene que hacer algo con las respuestas obsoletas y altamente votadas. Creo que Swift tiene que ser el peor caso para esto, ya que realmente hay tan pocos usuarios de las versiones antiguas, gracias a las políticas forzadas de actualización de Apple.

Gracias a Ptit Xav por meter su cabeza en mi lío.

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Pregunta

    ¿Cómo puedo hacer que el botón de navegación reciba toques y gestos, incluso cuando el FrameView generado dinámicamente tiene la interacción del usuario activada?

    Contexto

    La aplicación incluye una pantalla con un panel que tiene una vista de lista instanciada desde un Nib y un UIView generada dinámicamente (panel gris claro) que es una subvista de una subclase de UIView llamada FrameView. El punto rojo en la esquina de FrameView es un botón para eliminar el dibujo.

    Cuando se selecciona un elemento de la lista, se agregan cero o más paneles que muestran los dibujos relevantes como subvistas de FrameView. Para que el botón de eliminación sea clickeable, FrameView debe tener activada la interacción del usuario (inactiva por defecto).

    Sin embargo, activar la interacción del usuario en FrameView hace que bloquee los clics y gestos que llegan al botón de navegación, que tiene una zPosition relativamente alta en la vista principal y es el único elemento añadido a través de Storyboard.

    Solución Propuesta

    Aumentar la zPosition del botón de navegación por encima de FrameView no resuelve el problema.

    Después de alguna experimentación, sobrescribir el método hitTest en la clase FrameView puede resolver el problema:

    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        let view = super.hitTest(point, with: event)
        return view == self ? nil : view
    }
    

    Este enfoque no se encontró en respuestas anteriores de SO y podría ayudar a asegurar que los toques y gestos aún sean reconocidos por el botón de navegación, incluso cuando FrameView tiene activada la interacción del usuario.

Comments are closed.