Eventos e gestos de toque no Xamarin.iOS
É importante entender os eventos de toque e as APIs de toque em um aplicativo iOS, pois eles são centrais para todas as interações físicas com o dispositivo. Todas as interações por toque envolvem um UITouch
objeto . Neste artigo, aprenderemos a usar a UITouch
classe e suas APIs para dar suporte ao toque. Posteriormente, expandiremos nosso conhecimento para aprender a dar suporte a gestos.
Habilitando o Toque
Os controles em UIKit
– aqueles subclasses de UIControl – são tão dependentes da interação do usuário que têm gestos integrados ao UIKit e, portanto, não é necessário habilitar o Touch. Ele já está habilitado.
No entanto, muitos dos modos de exibição no UIKit
não têm toque habilitado por padrão. Há duas maneiras de habilitar o toque em um controle. A primeira maneira é marcar caixa de seleção Interação do Usuário Habilitada no Painel de Propriedades do Designer do iOS, conforme mostrado na captura de tela a seguir:
Também podemos usar um controlador para definir a UserInteractionEnabled
propriedade como true em uma UIView
classe. Isso será necessário se a interface do usuário for criada no código.
A seguinte linha de código é um exemplo:
imgTouchMe.UserInteractionEnabled = true;
Eventos de Toque
Há três fases de toque que ocorrem quando o usuário toca na tela, move o dedo ou remove o dedo. Esses métodos são definidos em UIResponder
, que é a classe base para UIView. O iOS substituirá os métodos associados no UIView
e no para manipular o UIViewController
toque:
TouchesBegan
– Isso é chamado quando a tela é tocada pela primeira vez.TouchesMoved
– Isso é chamado quando o local do toque é alterado à medida que o usuário desliza os dedos ao redor da tela.TouchesEnded
ouTouchesCancelled
–TouchesEnded
é chamado quando os dedos do usuário são retirados da tela.TouchesCancelled
será chamado se o iOS cancelar o toque – por exemplo, se um usuário deslizar o dedo para longe de um botão para cancelar uma tecla.
Os eventos de toque percorrem recursivamente para baixo pela pilha de UIViews, para marcar se o evento de toque estiver dentro dos limites de um objeto de exibição. Isso geralmente é chamado de Teste de clique. Eles serão chamados primeiro na parte superior UIView
ou UIViewController
, em seguida, serão chamados UIView
no e UIViewControllers
abaixo deles na hierarquia de exibição.
Um UITouch
objeto será criado sempre que o usuário tocar na tela. O UITouch
objeto inclui dados sobre o toque, como quando o toque ocorreu, onde ocorreu, se o toque foi um deslize etc. Os eventos de toque são passados por uma propriedade de toques – um NSSet
que contém um ou mais toques. Podemos usar essa propriedade para obter uma referência a um toque e determinar a resposta do aplicativo.
As classes que substituem um dos eventos de toque devem primeiro chamar a implementação base e, em seguida, obter o UITouch
objeto associado ao evento. Para obter uma referência ao primeiro toque, chame a propriedade e converta-a AnyObject
como uma UITouch
conforme mostrado no exemplo a seguir:
public override void TouchesBegan (NSSet touches, UIEvent evt)
{
base.TouchesBegan (touches, evt);
UITouch touch = touches.AnyObject as UITouch;
if (touch != null)
{
//code here to handle touch
}
}
O iOS reconhece automaticamente toques rápidos sucessivos na tela e coletará todos eles como um toque em um único UITouch
objeto. Isso torna a verificação de um toque duplo tão fácil quanto verificar a TapCount
propriedade, conforme ilustrado no código a seguir:
public override void TouchesBegan (NSSet touches, UIEvent evt)
{
base.TouchesBegan (touches, evt);
UITouch touch = touches.AnyObject as UITouch;
if (touch != null)
{
if (touch.TapCount == 2)
{
// do something with the double touch.
}
}
}
Multi-Touch
O multitoque não está habilitado por padrão em controles. O multitoque pode ser habilitado no Designer do iOS, conforme ilustrado pela captura de tela a seguir:
Também é possível definir vários toques programaticamente definindo a MultipleTouchEnabled
propriedade conforme mostrado na seguinte linha de código:
imgTouchMe.MultipleTouchEnabled = true;
Para determinar quantos dedos tocaram na tela, use a Count
propriedade na UITouch
propriedade :
public override void TouchesBegan (NSSet touches, UIEvent evt)
{
base.TouchesBegan (touches, evt);
lblNumberOfFingers.Text = "Number of fingers: " + touches.Count.ToString();
}
Determinando o local de toque
O método UITouch.LocationInView
retorna um objeto CGPoint que contém as coordenadas do toque em uma determinada exibição. Além disso, podemos testar para ver se esse local está dentro de um controle chamando o método Frame.Contains
. O snippet de código a seguir mostra um exemplo disso:
if (this.imgTouchMe.Frame.Contains (touch.LocationInView (this.View)))
{
// the touch event happened inside the UIView imgTouchMe.
}
Agora que temos uma compreensão dos eventos de toque no iOS, vamos aprender sobre reconhecedores de gestos.
Reconhecedores de Gestos
Os reconhecedores de gestos podem simplificar e reduzir muito o esforço de programação para dar suporte ao toque em um aplicativo. Os reconhecedores de gestos do iOS agregam uma série de eventos de toque em um único evento de toque.
O Xamarin.iOS fornece a classe UIGestureRecognizer
como uma classe base para os seguintes reconhecedores de gestos internos:
- UITapGestureRecognizer – isso é para um ou mais toques.
- UIPinchGestureRecognizer – Pinçando e espalhando dedos separados.
- UIPanGestureRecognizer – Movimento panorâmico ou arrastar.
- UISwipeGestureRecognizer – passando o dedo em qualquer direção.
- UIRotationGestureRecognizer – girar dois dedos em um movimento no sentido horário ou no sentido anti-horário.
- UILongPressGestureRecognizer – pressione e segure, às vezes chamado de pressionamento longo ou clique longo.
O padrão básico para usar um reconhecedor de gestos é o seguinte:
- Criar uma instância do reconhecedor de gestos – primeiro, instancie uma
UIGestureRecognizer
subclasse. O objeto instanciado será associado por uma exibição e será coletado como lixo quando a exibição for descartada. Não é necessário criar essa exibição como uma variável de nível de classe. - Definir qualquer configuração de gesto – a próxima etapa é configurar o reconhecedor de gestos. Consulte a documentação do Xamarin sobre
UIGestureRecognizer
e suas subclasses para obter uma lista de propriedades que podem ser definidas para controlar o comportamento de umaUIGestureRecognizer
instância. - Configurar o destino – devido à sua Objective-C herança, o Xamarin.iOS não gera eventos quando um reconhecedor de gestos corresponde a um gesto.
UIGestureRecognizer
tem um método –AddTarget
– que pode aceitar um delegado anônimo ou um Objective-C seletor com o código a ser executado quando o reconhecedor de gestos faz uma correspondência. - Habilitar o reconhecedor de gestos – assim como acontece com eventos de toque, os gestos só serão reconhecidos se as interações por toque estiverem habilitadas.
- Adicionar o reconhecedor de gestos ao modo de exibição – a etapa final é adicionar o gesto a um modo de exibição chamando
View.AddGestureRecognizer
e passando-lhe um objeto de reconhecimento de gestos.
Consulte os exemplos do reconhecedor de gestos para obter mais informações sobre como implementá-los no código.
Quando o destino do gesto for chamado, ele será passado uma referência ao gesto que ocorreu. Isso permite que o destino do gesto obtenha informações sobre o gesto ocorrido. A extensão das informações disponíveis depende do tipo de reconhecedor de gestos usado. Consulte a documentação do Xamarin para obter informações sobre os dados disponíveis para cada UIGestureRecognizer
subclasse.
É importante lembrar que, depois que um reconhecedor de gestos for adicionado a um modo de exibição, o modo de exibição (e quaisquer exibições abaixo dele) não receberá nenhum evento de toque. Para permitir eventos de toque simultaneamente com gestos, a CancelsTouchesInView
propriedade deve ser definida como false, conforme ilustrado pelo seguinte código:
_tapGesture.Recognizer.CancelsTouchesInView = false;
Cada UIGestureRecognizer
um tem uma propriedade State que fornece informações importantes sobre o status do reconhecedor de gestos. Sempre que o valor dessa propriedade for alterado, o iOS chamará o método de assinatura, dando-lhe uma atualização. Se um reconhecedor de gestos personalizado nunca atualizar a propriedade State, o assinante nunca será chamado, tornando o reconhecedor de gestos inútil.
Gestos podem ser resumidos como um dos dois tipos:
- Discreto – esses gestos só disparam na primeira vez em que são reconhecidos.
- Contínuo – esses gestos continuam a disparar desde que sejam reconhecidos.
Reconhecedores de gestos existem em um dos seguintes estados:
- Possível – esse é o estado inicial de todos os reconhecedores de gestos. Esse é o valor padrão da propriedade State.
- Iniciado – quando um gesto contínuo é reconhecido pela primeira vez, o estado é definido como Iniciado. Isso permite que as assinaturas diferenciem entre quando o reconhecimento de gestos é iniciado e quando ele é alterado.
- Alterado – depois que um gesto contínuo tiver começado, mas não tiver terminado, o estado será definido como Alterado sempre que um toque for movido ou alterado, desde que ainda esteja dentro dos parâmetros esperados do gesto.
- Cancelado – esse estado será definido se o reconhecedor passou de Iniciado para Alterado e, em seguida, os toques foram alterados de forma a não se ajustar mais ao padrão do gesto.
- Reconhecido – o estado será definido quando o reconhecedor de gestos corresponder a um conjunto de toques e informará ao assinante que o gesto foi concluído.
- Encerrado – esse é um alias para o estado Reconhecido.
- Falha – quando o reconhecedor de gestos não puder mais corresponder aos toques que está escutando, o estado será alterado para Falha.
O Xamarin.iOS representa esses valores na UIGestureRecognizerState
enumeração .
Trabalhando com vários gestos
Por padrão, o iOS não permite que gestos padrão sejam executados simultaneamente. Em vez disso, cada reconhecedor de gestos receberá eventos de toque em uma ordem não determinística. O snippet de código a seguir ilustra como fazer um reconhecedor de gestos ser executado simultaneamente:
gesture.ShouldRecognizeSimultaneously += (UIGestureRecognizer r) => { return true; };
Também é possível desabilitar um gesto no iOS. Há duas propriedades delegadas que permitem que um reconhecedor de gestos examine o estado de um aplicativo e os eventos de toque atuais, para tomar decisões sobre como e se um gesto deve ser reconhecido. Os dois eventos são:
- ShouldReceiveTouch – esse delegado é chamado logo antes que o reconhecedor de gestos seja passado por um evento de toque e oferece uma oportunidade para examinar os toques e decidir quais toques serão tratados pelo reconhecedor de gestos.
- ShouldBegin – isso é chamado quando um reconhecedor tenta alterar o estado de Possível para algum outro estado. Retornar false forçará o estado do reconhecedor de gestos a ser alterado para Falha.
Você pode substituir esses métodos com um fortemente tipado UIGestureRecognizerDelegate
, um delegado fraco ou associar por meio da sintaxe do manipulador de eventos, conforme ilustrado pelo seguinte snippet de código:
gesture.ShouldReceiveTouch += (UIGestureRecognizer r, UITouch t) => { return true; };
Por fim, é possível enfileirar um reconhecedor de gestos para que ele só tenha êxito se outro reconhecedor de gestos falhar. Por exemplo, um reconhecedor de gestos de toque único só deve ter êxito quando um reconhecedor de gestos de toque duplo falhar. O snippet de código a seguir fornece um exemplo disso:
singleTapGesture.RequireGestureRecognizerToFail(doubleTapGesture);
Criando um gesto personalizado
Embora o iOS forneça alguns reconhecedores de gestos padrão, pode ser necessário criar reconhecedores de gestos personalizados em determinados casos. A criação de um reconhecedor de gestos personalizado envolve as seguintes etapas:
- Subclasse
UIGestureRecognizer
. - Substitua os métodos de evento de toque apropriados.
- O reconhecimento de bolhas status por meio da propriedade State da classe base.
Um exemplo prático disso será abordado no passo a passo Usando o Toque no iOS .