É possível para um UIButton (ou qualquer outro controle para esse assunto) receber eventos de toque quando o quadro do UIButton está fora do quadro do pai? Porque quando tento fazer isso, meu UIButton não parece ser capaz de receber nenhum evento. Como faço para contornar isso?
92
Respostas:
Sim. Você pode substituir o
hitTest:withEvent:
método para retornar uma vista para um conjunto maior de pontos do que aquele que a vista contém. Consulte a Referência de classe UIView .Editar: Exemplo:
Edição 2: (Após esclarecimento :) Para garantir que o botão seja tratado como estando dentro dos limites do pai, você precisa substituir
pointInside:withEvent:
no pai para incluir o quadro do botão.Observe que o código ali para substituir pointInside não está totalmente correto. Como Summon explica abaixo, faça o seguinte:
Observe que você provavelmente faria isso com
self.oversizeButton
um IBOutlet nesta subclasse de UIView; então você pode simplesmente arrastar o "botão de tamanho grande" em questão, para a vista especial em questão. (Ou, se por algum motivo você estivesse fazendo muito isso em um projeto, você teria uma subclasse UIButton especial e poderia procurar por essas classes em sua lista de subvisualização.) Espero que ajude.fonte
pointInside:withEvent:
para incluir a moldura do botão. Vou adicionar alguns códigos de amostra à minha resposta acima.hitTest:withEvent:
e apointInside:withEvent:
área não é chamada por mim quando pressiono um botão que está fora dos limites dos pais. O que pode estar errado?@jnic, estou trabalhando no iOS SDK 5.0 e para que seu código funcione corretamente, tive que fazer o seguinte:
A visualização do contêiner no meu caso é um UIButton e todos os elementos filhos também são UIButtons que podem se mover para fora dos limites do UIButton pai.
Melhor
fonte
Na visualização pai, você pode substituir o método de teste de clique:
Nesse caso, se o ponto estiver dentro dos limites do seu botão, você encaminha a chamada para lá; se não, reverta para a implementação original.
fonte
No meu caso, eu tinha uma
UICollectionViewCell
subclasse que continha aUIButton
. DesativeiclipsToBounds
a célula e o botão ficou visível fora dos limites da célula. No entanto, o botão não estava recebendo eventos de toque. Consegui detectar os eventos de toque no botão usando a resposta de Jack: https://stackoverflow.com/a/30431157/3344977Esta é uma versão do Swift:
Swift 4:
fonte
Porque isso está acontecendo?
Isso ocorre porque quando sua subvisualização está fora dos limites de sua supervisão, os eventos de toque que realmente acontecem nessa subvisualização não serão entregues a ela. No entanto, ele vai ser entregue ao seu superview.
O que você precisa fazer?
Quando seu superview receber o evento de toque mencionado acima, você precisará informar ao UIKit explicitamente que meu subview deve ser o único a receber este evento de toque.
E quanto ao código?
Em sua visão geral, implemente
func hitTest(_ point: CGPoint, with event: UIEvent?)
Fascinante gotchya: você deve ir para a "visão superior muito pequena"
Você tem que ir "para cima" até a visão "mais elevada", da qual a visão do problema está fora.
Exemplo típico:
Digamos que você tenha uma tela S, com uma visualização de contêiner C. A visualização do controlador de visualização de contêiner é V. (Lembre-se de que V ficará dentro de C e terá o mesmo tamanho.) V tem uma subvisualização (talvez um botão) B. B é o problema vista que está realmente fora de V.
Mas observe que B também está fora de C.
Neste exemplo você tem que aplicar a solução
override hitTest
de fato para C, para não V . Se você aplicá-lo a V - não faz nada.fonte
Rápido:
Onde targetView é a visualização que você deseja receber o evento (que pode estar total ou parcialmente localizada fora do quadro de sua visualização pai).
fonte
Para mim (como para outros), a resposta não foi ignorar o
hitTest
método, mas sim opointInside
método. Eu tive que fazer isso em apenas dois lugares.A Supervisão Esta é a visão que se fosse
clipsToBounds
definida como verdadeira, faria todo o problema desaparecer. Então aqui está o meu simplesUIView
no Swift 3:A subvisualização Sua milhagem pode variar, mas no meu caso também tive que substituir o
pointInside
método da subvisualização que decidiu que o toque estava fora dos limites. O meu está em Objective-C, então:Esta resposta (e algumas outras sobre a mesma pergunta) pode ajudar a esclarecer seu entendimento.
fonte
Swift 4.1 atualizado
Para obter eventos de toque no mesmo UIView, você só precisa adicionar o seguinte método de substituição, ele identificará a visualização específica tocada no UIView que está fora do limite
fonte