Procedura dettagliata: Uso del tocco in Xamarin.iOS
Questa procedura dettagliata illustra come scrivere codice che risponde a diversi tipi di eventi di tocco. Ogni esempio è contenuto in una schermata separata:
- Esempi di tocco: come rispondere agli eventi di tocco.
- Esempi di Riconoscimento movimento: come usare i riconoscitori di movimento predefiniti.
- Esempio di Riconoscimento movimento personalizzato: come creare un riconoscimento movimento personalizzato.
Ogni sezione contiene istruzioni per scrivere il codice da zero.
Seguire le istruzioni seguenti per aggiungere codice allo storyboard e informazioni sui diversi tipi di eventi di tocco disponibili in iOS.
Esempi di tocco
In questo esempio verranno illustrate alcune delle API di tocco. Seguire questa procedura per aggiungere il codice necessario per implementare gli eventi di tocco:
Aprire il Touch_Start del progetto. Eseguire prima di tutto il progetto per assicurarsi che tutto sia corretto e toccare il pulsante Touch Samples (Esempi di tocco). Verrà visualizzata una schermata simile alla seguente (anche se nessuno dei pulsanti funzionerà):
Modificare il file TouchViewController.cs e aggiungere le due variabili di istanza seguenti alla classe
TouchViewController
:#region Private Variables private bool imageHighlighted = false; private bool touchStartedInside; #endregion
Implementare il
TouchesBegan
metodo , come illustrato nel codice seguente: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; } } }
Questo metodo funziona controllando la presenza di un
UITouch
oggetto e, se esistente, esegue alcune azioni in base alla posizione in cui si è verificato il tocco:- All'interno di TouchImage : visualizzare il testo
Touches Began
in un'etichetta e modificare l'immagine. - All'interno di DoubleTouchImage : modificare l'immagine visualizzata se il movimento è stato doppio tocco.
- All'interno di DragImage : impostare un flag che indica che il tocco è stato avviato. Il metodo
TouchesMoved
userà questo flag per determinare seDragImage
deve essere spostato sullo schermo o meno, come si vedrà nel passaggio successivo.
Il codice precedente riguarda solo i singoli tocchi, non esiste ancora alcun comportamento se l'utente sta spostando il dito sullo schermo. Per rispondere allo spostamento, implementare
TouchesMoved
come illustrato nel codice seguente: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); } } }
Questo metodo ottiene un
UITouch
oggetto e quindi verifica dove si è verificato il tocco. Se il tocco si è verificato inTouchImage
, il testo Touches Moved viene visualizzato sullo schermo.Se
touchStartedInside
è true, sappiamo che l'utente ha il dito suDragImage
e lo sta spostando. Il codice verrà spostatoDragImage
quando l'utente sposta il dito intorno allo schermo.- All'interno di TouchImage : visualizzare il testo
È necessario gestire il caso quando l'utente solleva il dito dallo schermo oppure iOS annulla l'evento di tocco. A tale scopo, verrà implementato
TouchesEnded
eTouchesCancelled
come illustrato di seguito: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; }
Entrambi questi metodi reimpostano il
touchStartedInside
flag su false.TouchesEnded
verrà visualizzataTouchesEnded
anche sullo schermo.A questo punto, la schermata Touch Samples (Esempi di tocco) è terminata. Si noti che la schermata cambia durante l'interazione con ognuna delle immagini, come illustrato nello screenshot seguente:
Esempi di riconoscimento dei movimenti
La sezione precedente ha illustrato come trascinare un oggetto intorno allo schermo usando gli eventi di tocco. In questa sezione si elimineranno gli eventi di tocco e si mostrerà come usare i seguenti riconoscitori di movimento:
- Oggetto
UIPanGestureRecognizer
per il trascinamento di un'immagine sullo schermo. - Oggetto
UITapGestureRecognizer
per rispondere a doppio tocco sullo schermo.
Seguire questa procedura per implementare i riconoscitori dei movimenti:
Modificare il file GestureViewController.cs e aggiungere la variabile di istanza seguente:
#region Private Variables private bool imageHighlighted = false; private RectangleF originalImageFrame = RectangleF.Empty; #endregion
Questa variabile di istanza è necessaria per tenere traccia della posizione precedente dell'immagine. Il riconoscimento movimento panoramica userà il
originalImageFrame
valore per calcolare l'offset necessario per ridisegnare l'immagine sullo schermo.Aggiungere il metodo seguente al controller:
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); }
Questo codice crea un'istanza
UIPanGestureRecognizer
di e lo aggiunge a una visualizzazione. Si noti che si assegna una destinazione al movimento sotto forma di metodoHandleDrag
. Questo metodo viene fornito nel passaggio successivo.Per implementare HandleDrag, aggiungere il codice seguente al controller:
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; } }
Il codice precedente controlla prima lo stato del riconoscimento movimento e quindi sposta l'immagine sullo schermo. Con questo codice sul posto, il controller può ora supportare il trascinamento dell'immagine intorno allo schermo.
Aggiungere un oggetto
UITapGestureRecognizer
che modificherà l'immagine visualizzata in DoubleTouchImage. Aggiungere il metodo seguente alGestureViewController
controller: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); }
Questo codice è molto simile al codice per ma
UIPanGestureRecognizer
invece di usare un delegato per una destinazione in cui viene usato un oggettoAction
.L'ultima operazione da eseguire è modificare
ViewDidLoad
in modo che chiami i metodi appena aggiunti. Modificare ViewDidLoad in modo che sia simile al codice seguente:public override void ViewDidLoad() { base.ViewDidLoad(); Title = "Gesture Recognizers"; // Save initial state originalImageFrame = DragImage.Frame; WireUpTapGestureRecognizer(); WireUpDragGestureRecognizer(); }
Si noti anche che si inizializza il valore di
originalImageFrame
.Eseguire l'applicazione e interagire con le due immagini. Lo screenshot seguente è un esempio di queste interazioni:
Riconoscimento movimento personalizzato
In questa sezione verranno applicati i concetti delle sezioni precedenti per creare un riconoscimento movimento personalizzato. Il riconoscimento movimento personalizzato sottoclasserà UIGestureRecognizer
e riconoscerà quando l'utente disegna una "V" sullo schermo e quindi attiva o disattiva una bitmap. Lo screenshot seguente è un esempio di questa schermata:
Per creare un riconoscimento movimento personalizzato, seguire questa procedura:
Aggiungere una nuova classe al progetto denominato
CheckmarkGestureRecognizer
e renderla simile al codice seguente: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 } }
Il metodo Reset viene chiamato quando la
State
proprietà viene modificata inRecognized
oEnded
. Questo è il momento di reimpostare qualsiasi stato interno impostato nel riconoscimento movimenti personalizzato. Ora la classe può iniziare nuovamente la prossima volta che l'utente interagisce con l'applicazione ed essere pronto a provare a riconoscere il movimento.Ora che è stato definito un riconoscimento movimento personalizzato (
CheckmarkGestureRecognizer
) modificare il file CustomGestureViewController.cs e aggiungere le due variabili di istanza seguenti:#region Private Variables private bool isChecked = false; private CheckmarkGestureRecognizer checkmarkGesture; #endregion
Per creare un'istanza e configurare il riconoscimento dei movimenti, aggiungere il metodo seguente al controller:
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); }
Modificare
ViewDidLoad
in modo che chiamiWireUpCheckmarkGestureRecognizer
, come illustrato nel frammento di codice seguente:public override void ViewDidLoad() { base.ViewDidLoad(); // Wire up the gesture recognizer WireUpCheckmarkGestureRecognizer(); }
Eseguire l'applicazione e provare a disegnare una "V" sullo schermo. Verrà visualizzata la modifica dell'immagine, come illustrato negli screenshot seguenti:
Le tre sezioni precedenti illustrano diversi modi per rispondere agli eventi di tocco in iOS: uso di eventi di tocco, riconoscitori di movimenti predefiniti o con un riconoscimento movimento personalizzato.