Middle
Como determinar se o utilizador clicou numa camada (layer) na aplicação?
sobes.tech IA
Resposta da IA
Para detectar toques em CALayer, podem ser usadas várias abordagens:
-
Usar
hitTest(_:event:)na vista (View):UIViewtem o métodohitTest(_:with:), que percorre recursivamente a hierarquia de subviews e devolve a subview mais profunda que contém o ponto dado.- Este método considera por padrão as camadas relacionadas às vistas.
- Pode-se sobrescrever
hitTest(_:with:)numa vista personalizada para um controlo mais detalhado ou para tratar toques diretamente nas subcamadas que não estão relacionadas com vistas.
-
Transformar coordenadas usando
convert:- Ao receber um evento de toque (por exemplo, em métodos de
UIView), tens as coordenadas do toque relativamente à janela (UIWindow) ou vista. - Para determinar se o toque caiu numa camada específica, precisas de converter essas coordenadas para o sistema de coordenadas dessa camada.
- Para isso, usam-se os métodos
convert(_:from:)ouconvert(_:to:)deCALayer. - Após a conversão, podes verificar se o ponto está dentro dos limites da camada (
bounds) ou usar verificações mais específicas, comocontains(_:).
- Ao receber um evento de toque (por exemplo, em métodos de
-
Anexar
UITapGestureRecognizerà vista:- Podes adicionar um gesto
UITapGestureRecognizeràUIViewassociada à camada. - No manipulador do gesto, obter a localização do toque relativamente à vista.
- Depois, usar o método de conversão de coordenadas (ponto 2) para verificar se o ponto de toque está dentro da camada ou das suas subcamadas.
- Podes adicionar um gesto
-
Criar uma
UIViewpara cada camada interativa:- Se tiveres camadas que devem ser interativas, uma forma simples é criar uma
UIViewpara cada uma. - Posicioná-la e ajustar o seu tamanho para coincidir com a camada.
- Adicionar manipuladores de gestos (
UITapGestureRecognizer) ou sobrescrever métodos de tratamento de eventos de toque (touchesBegan,touchesEnded, etc.) nessa vista. - Esta é a forma mais idiomática de tratar entrada do utilizador no UIKit, pois
UIViewfoi desenhada para isso.
- Se tiveres camadas que devem ser interativas, uma forma simples é criar uma
Exemplo de uso de hitTest em UIView:
// Numa vista personalizada
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
// Converter o ponto de toque para as coordenadas da subcamada
let pointInLayer = mySublayer.convert(point, from: layer!)
// Verificar se o ponto está dentro dos limites da subcamada
if mySublayer.contains(pointInLayer) {
// Se o ponto estiver dentro da subcamada, podemos devolver esta vista ou outra
// ou realizar as ações necessárias.
// Neste caso, determinamos que o toque foi "sobre" a subcamada.
print("Toque em mySublayer")
// Podemos devolver nil se não quisermos que esta vista trate o toque, ou super.hitTest se quisermos manter o comportamento padrão.
}
// Permitir que o hitTest padrão trate os outros casos
return super.hitTest(point, with: event)
}
Exemplo de uso da conversão de coordenadas no manipulador de gesto:
// Numa vista personalizada com UITapGestureRecognizer ligado
@objc func handleTap(_ sender: UITapGestureRecognizer) {
let tapLocationInView = sender.location(in: self)
// Converter a localização do toque para as coordenadas da subcamada
let tapLocationInSublayer = mySublayer.convert(tapLocationInView, from: layer!)
// Verificar se o ponto está dentro dos limites da subcamada
if mySublayer.contains(tapLocationInSublayer) {
print("Toque em mySublayer")
// Executar ações relacionadas com o toque na subcamada
}
}