Demonstra Passo a passo: Usando o toque no Xamarin.iOS
Este passo a passo demonstra como escrever código que responde a diferentes tipos de eventos de toque. Cada exemplo está contido em uma tela separada:
- Amostras de toque – como responder a eventos de toque.
- Exemplos do Gesture Recognizer – como usar reconhecedores de gestos integrados.
- Exemplo de reconhecedor de gesto personalizado – como criar um reconhecedor de gesto personalizado.
Cada seção contém instruções para escrever o código do zero.
Siga as instruções abaixo para adicionar código ao storyboard e saiba mais sobre os diferentes tipos de eventos de toque disponíveis no iOS.
Amostras de toque
Neste exemplo, demonstraremos algumas das APIs de toque. Siga estas etapas para adicionar o código necessário para implementar eventos de toque:
Abra o Touch_Start do projeto. Primeiro, execute o projeto para garantir que tudo esteja bem e toque no botão Touch Samples . Você verá uma tela semelhante à seguinte (embora nenhum dos botões funcione):
Edite o TouchViewController.cs de arquivo e adicione as duas variáveis de instância a seguir à classe
TouchViewController
:#region Private Variables private bool imageHighlighted = false; private bool touchStartedInside; #endregion
Implemente o
TouchesBegan
método, conforme mostrado no código abaixo:public override void TouchesBegan(NSSet touches, UIEvent evt) { base.TouchesBegan(touches, evt); // If Multitouch is enabled, report the number of fingers down TouchStatus.Text = string.Format ("Number of fingers {0}", touches.Count); // Get the current touch UITouch touch = touches.AnyObject as UITouch; if (touch != null) { // Check to see if any of the images have been touched if (TouchImage.Frame.Contains(touch.LocationInView(TouchView))) { // Fist image touched TouchImage.Image = UIImage.FromBundle("TouchMe_Touched.png"); TouchStatus.Text = "Touches Began"; } else if (touch.TapCount == 2 && DoubleTouchImage.Frame.Contains(touch.LocationInView(TouchView))) { // Second image double-tapped, toggle bitmap if (imageHighlighted) { DoubleTouchImage.Image = UIImage.FromBundle("DoubleTapMe.png"); TouchStatus.Text = "Double-Tapped Off"; } else { DoubleTouchImage.Image = UIImage.FromBundle("DoubleTapMe_Highlighted.png"); TouchStatus.Text = "Double-Tapped On"; } imageHighlighted = !imageHighlighted; } else if (DragImage.Frame.Contains(touch.LocationInView(View))) { // Third image touched, prepare to drag touchStartedInside = true; } } }
Esse método funciona verificando um
UITouch
objeto e, se ele existir, execute alguma ação com base em onde o toque ocorreu:- Dentro de TouchImage – exibe o texto
Touches Began
em um rótulo e altera a imagem. - Dentro de DoubleTouchImage – altere a imagem exibida se o gesto foi um toque duplo.
- Dentro de DragImage – defina um sinalizador indicando que o toque foi iniciado. O método
TouchesMoved
usará esse sinalizador para determinar seDragImage
deve ser movido pela tela ou não, como veremos na próxima etapa.
O código acima trata apenas de toques individuais, ainda não há comportamento se o usuário estiver movendo o dedo na tela. Para responder ao movimento, implemente
TouchesMoved
como mostrado no código abaixo:public override void TouchesMoved(NSSet touches, UIEvent evt) { base.TouchesMoved(touches, evt); // get the touch UITouch touch = touches.AnyObject as UITouch; if (touch != null) { //==== IMAGE TOUCH if (TouchImage.Frame.Contains(touch.LocationInView(TouchView))) { TouchStatus.Text = "Touches Moved"; } //==== IMAGE DRAG // check to see if the touch started in the drag me image if (touchStartedInside) { // move the shape float offsetX = touch.PreviousLocationInView(View).X - touch.LocationInView(View).X; float offsetY = touch.PreviousLocationInView(View).Y - touch.LocationInView(View).Y; DragImage.Frame = new RectangleF(new PointF(DragImage.Frame.X - offsetX, DragImage.Frame.Y - offsetY), DragImage.Frame.Size); } } }
Esse método obtém um
UITouch
objeto e, em seguida, verifica onde o toque ocorreu. Se o toque ocorreu noTouchImage
, o texto Toques Movidos será exibido na tela.Se
touchStartedInside
for verdade, então sabemos que o usuário está com o dedo eDragImage
está movendo-o. O código se moveráDragImage
à medida que o usuário mover o dedo pela tela.- Dentro de TouchImage – exibe o texto
Precisamos lidar com o caso quando o usuário tira o dedo da tela ou o iOS cancela o evento de toque. Para isso, vamos implementar
TouchesEnded
eTouchesCancelled
conforme mostrado abaixo:public override void TouchesCancelled(NSSet touches, UIEvent evt) { base.TouchesCancelled(touches, evt); // reset our tracking flags touchStartedInside = false; TouchImage.Image = UIImage.FromBundle("TouchMe.png"); TouchStatus.Text = ""; } public override void TouchesEnded(NSSet touches, UIEvent evt) { base.TouchesEnded(touches, evt); // get the touch UITouch touch = touches.AnyObject as UITouch; if (touch != null) { //==== IMAGE TOUCH if (TouchImage.Frame.Contains(touch.LocationInView(TouchView))) { TouchImage.Image = UIImage.FromBundle("TouchMe.png"); TouchStatus.Text = "Touches Ended"; } } // reset our tracking flags touchStartedInside = false; }
Ambos os métodos redefinirão o
touchStartedInside
sinalizador para false.TouchesEnded
também será exibidoTouchesEnded
na tela.Neste ponto, a tela Touch Samples está concluída. Observe como a tela muda à medida que você interage com cada uma das imagens, conforme mostrado na captura de tela a seguir:
Exemplos do Reconhecedor de Gestos
A seção anterior demonstrou como arrastar um objeto pela tela usando eventos de toque. Nesta seção, vamos nos livrar dos eventos de toque e mostrar como usar os seguintes reconhecedores de gestos:
- O
UIPanGestureRecognizer
para arrastar uma imagem pela tela. - O
UITapGestureRecognizer
para responder a toques duplos na tela.
Siga estas etapas para implementar reconhecedores de gestos:
Edite o GestureViewController.cs de arquivo e adicione a seguinte variável de instância:
#region Private Variables private bool imageHighlighted = false; private RectangleF originalImageFrame = RectangleF.Empty; #endregion
Precisamos dessa variável de instância para acompanhar o local anterior da imagem. O reconhecedor de gestos de panorâmica usará o
originalImageFrame
valor para calcular o deslocamento necessário para redesenhar a imagem na tela.Adicione o seguinte método ao controlador:
private void WireUpDragGestureRecognizer() { // Create a new tap gesture UIPanGestureRecognizer gesture = new UIPanGestureRecognizer(); // Wire up the event handler (have to use a selector) gesture.AddTarget(() => HandleDrag(gesture)); // to be defined // Add the gesture recognizer to the view DragImage.AddGestureRecognizer(gesture); }
Esse código instancia uma
UIPanGestureRecognizer
instância e a adiciona a uma exibição. Observe que atribuímos um destino ao gesto na forma do métodoHandleDrag
– esse método é fornecido na próxima etapa.Para implementar HandleDrag, adicione o seguinte código ao controlador:
private void HandleDrag(UIPanGestureRecognizer recognizer) { // If it's just began, cache the location of the image if (recognizer.State == UIGestureRecognizerState.Began) { originalImageFrame = DragImage.Frame; } // Move the image if the gesture is valid if (recognizer.State != (UIGestureRecognizerState.Cancelled | UIGestureRecognizerState.Failed | UIGestureRecognizerState.Possible)) { // Move the image by adding the offset to the object's frame PointF offset = recognizer.TranslationInView(DragImage); RectangleF newFrame = originalImageFrame; newFrame.Offset(offset.X, offset.Y); DragImage.Frame = newFrame; } }
O código acima verificará primeiro o estado do reconhecedor de gestos e, em seguida, moverá a imagem pela tela. Com esse código no lugar, o controlador agora pode suportar arrastar uma imagem ao redor da tela.
Adicione um
UITapGestureRecognizer
que alterará a imagem que está sendo exibida em DoubleTouchImage. Adicione o seguinte método aoGestureViewController
controlador:private void WireUpTapGestureRecognizer() { // Create a new tap gesture UITapGestureRecognizer tapGesture = null; // Report touch Action action = () => { TouchStatus.Text = string.Format("Image touched at: {0}",tapGesture.LocationOfTouch(0, DoubleTouchImage)); // Toggle the image if (imageHighlighted) { DoubleTouchImage.Image = UIImage.FromBundle("DoubleTapMe.png"); } else { DoubleTouchImage.Image = UIImage.FromBundle("DoubleTapMe_Highlighted.png"); } imageHighlighted = !imageHighlighted; }; tapGesture = new UITapGestureRecognizer(action); // Configure it tapGesture.NumberOfTapsRequired = 2; // Add the gesture recognizer to the view DoubleTouchImage.AddGestureRecognizer(tapGesture); }
Esse código é muito semelhante ao código para o
UIPanGestureRecognizer
mas em vez de usar um delegado para um destino, estamos usando umAction
arquivo .A última coisa que precisamos fazer é modificar
ViewDidLoad
para que ele chame os métodos que acabamos de adicionar. Altere ViewDidLoad para que se assemelhe ao seguinte código:public override void ViewDidLoad() { base.ViewDidLoad(); Title = "Gesture Recognizers"; // Save initial state originalImageFrame = DragImage.Frame; WireUpTapGestureRecognizer(); WireUpDragGestureRecognizer(); }
Observe também que inicializamos o valor de
originalImageFrame
.Execute o aplicativo e interaja com as duas imagens. A captura de tela a seguir é um exemplo dessas interações:
Reconhecedor de gestos personalizados
Nesta seção, aplicaremos os conceitos das seções anteriores para criar um reconhecedor de gestos personalizado. O reconhecedor de gestos personalizados subclasses UIGestureRecognizer
e reconhecerá quando o usuário desenhar um "V" na tela e, em seguida, alternar um bitmap. A captura de tela a seguir é um exemplo dessa tela:
Siga estas etapas para criar um reconhecedor de gestos personalizado:
Adicione uma nova classe ao projeto chamado
CheckmarkGestureRecognizer
, e faça com que ele se pareça com o seguinte código:using System; using CoreGraphics; using Foundation; using UIKit; namespace Touch { public class CheckmarkGestureRecognizer : UIGestureRecognizer { #region Private Variables private CGPoint midpoint = CGPoint.Empty; private bool strokeUp = false; #endregion #region Override Methods /// <summary> /// Called when the touches end or the recognizer state fails /// </summary> public override void Reset() { base.Reset(); strokeUp = false; midpoint = CGPoint.Empty; } /// <summary> /// Is called when the fingers touch the screen. /// </summary> public override void TouchesBegan(NSSet touches, UIEvent evt) { base.TouchesBegan(touches, evt); // we want one and only one finger if (touches.Count != 1) { base.State = UIGestureRecognizerState.Failed; } Console.WriteLine(base.State.ToString()); } /// <summary> /// Called when the touches are cancelled due to a phone call, etc. /// </summary> public override void TouchesCancelled(NSSet touches, UIEvent evt) { base.TouchesCancelled(touches, evt); // we fail the recognizer so that there isn't unexpected behavior // if the application comes back into view base.State = UIGestureRecognizerState.Failed; } /// <summary> /// Called when the fingers lift off the screen /// </summary> public override void TouchesEnded(NSSet touches, UIEvent evt) { base.TouchesEnded(touches, evt); // if (base.State == UIGestureRecognizerState.Possible && strokeUp) { base.State = UIGestureRecognizerState.Recognized; } Console.WriteLine(base.State.ToString()); } /// <summary> /// Called when the fingers move /// </summary> public override void TouchesMoved(NSSet touches, UIEvent evt) { base.TouchesMoved(touches, evt); // if we haven't already failed if (base.State != UIGestureRecognizerState.Failed) { // get the current and previous touch point CGPoint newPoint = (touches.AnyObject as UITouch).LocationInView(View); CGPoint previousPoint = (touches.AnyObject as UITouch).PreviousLocationInView(View); // if we're not already on the upstroke if (!strokeUp) { // if we're moving down, just continue to set the midpoint at // whatever point we're at. when we start to stroke up, it'll stick // as the last point before we upticked if (newPoint.X >= previousPoint.X && newPoint.Y >= previousPoint.Y) { midpoint = newPoint; } // if we're stroking up (moving right x and up y [y axis is flipped]) else if (newPoint.X >= previousPoint.X && newPoint.Y <= previousPoint.Y) { strokeUp = true; } // otherwise, we fail the recognizer else { base.State = UIGestureRecognizerState.Failed; } } } Console.WriteLine(base.State.ToString()); } #endregion } }
O método Reset é chamado quando a
State
propriedade é alterada paraRecognized
ouEnded
. Este é o momento de redefinir qualquer estado interno definido no reconhecedor de gestos personalizado. Agora, a classe pode começar de novo na próxima vez que o usuário interagir com o aplicativo e estar pronto para tentar novamente reconhecer o gesto.Agora que definimos um reconhecedor de gestos personalizado (
CheckmarkGestureRecognizer
) edite o arquivo CustomGestureViewController.cs e adicione as duas variáveis de instância a seguir:#region Private Variables private bool isChecked = false; private CheckmarkGestureRecognizer checkmarkGesture; #endregion
Para instanciar e configurar nosso reconhecedor de gestos, adicione o seguinte método ao controlador:
private void WireUpCheckmarkGestureRecognizer() { // Create the recognizer checkmarkGesture = new CheckmarkGestureRecognizer(); // Wire up the event handler checkmarkGesture.AddTarget(() => { if (checkmarkGesture.State == (UIGestureRecognizerState.Recognized | UIGestureRecognizerState.Ended)) { if (isChecked) { CheckboxImage.Image = UIImage.FromBundle("CheckBox_Unchecked.png"); } else { CheckboxImage.Image = UIImage.FromBundle("CheckBox_Checked.png"); } isChecked = !isChecked; } }); // Add the gesture recognizer to the view View.AddGestureRecognizer(checkmarkGesture); }
Edite
ViewDidLoad
para que ele chameWireUpCheckmarkGestureRecognizer
, conforme mostrado no seguinte trecho de código:public override void ViewDidLoad() { base.ViewDidLoad(); // Wire up the gesture recognizer WireUpCheckmarkGestureRecognizer(); }
Execute o aplicativo e tente desenhar um "V" na tela. Você deve ver a imagem que está sendo exibida mudar, como mostrado nas seguintes capturas de tela:
As três seções acima demonstraram diferentes maneiras de responder a eventos de toque no iOS: usando eventos de toque, reconhecedores de gestos integrados ou com um reconhecedor de gestos personalizado.